I am using Laravel's bcrypt function for hashing passwords. When I do,
bcrypt('secret')
I get
=> "$2y$10$mnPgYt2xm9pxb/c2I.SH.uuhgrOj4WajDQTJYssUbTjmPOcgQybcu"
But if I run it again, I get
=> "$2y$10$J8h.Xmf6muivJ4bDweUlcu/BaNzI2wlBiAcop30PbPoKa0kDaf9xi"
and so on...
So, won't the password matching process fail if I get different values every time?
This is how bcrypt is supposed to work. See wikipedia.
Bcrypt generates a random 128-bit salt during hashing. This salt becomes part of the hash, hence we always get a different hash value for the same input string. The random salt is actually used to deter brute-force attacks.
The password matching process won't fail due to different values of hashes.
Try the following in tinker
$hash1 = bcrypt('secret')
$hash2 = bcrypt('secret')
Hash::check('secret', $hash1)
Hash::check('secret', $hash2)
You should get true in both the cases of Hash::check.
So even if the hash values are different, the password matching won't fail.
Bcrypt uses a 128-bit salt and encrypts a 192-bit magic value. It takes advantage of the expensive key setup in eksblowfish.
The bcrypt algorithm runs in two phases, sketched in Figure 3. In the first phase, EksBlowfishSetup is called with the cost, the salt, and the password, to initialize eksblowfish's state. Most of bcrypt's time is spent in the expensive key schedule. Following that, the 192-bit value ``OrpheanBeholderScryDoubt'' is encrypted 64 times using eksblowfish in ECB mode with the state from the previous phase. The output is the cost and 128-bit salt concatenated with the result of the encryption loop.
How it works in laravel :
if (! function_exists('bcrypt')) {
/**
* Hash the given value against the bcrypt algorithm.
*
* #param string $value
* #param array $options
* #return string
*/
function bcrypt($value, $options = [])
{
return app('hash')->driver('bcrypt')->make($value, $options);
}
}
Supported options for PASSWORD_BCRYPT:
salt (string) - to manually provide a salt to use when hashing the password. Note that this will override and prevent a salt from being automatically generated.
If omitted, a random salt will be generated by password_hash() for each password hashed. This is the intended mode of operation.
Warning The salt option has been deprecated as of PHP 7.0.0. It is now
preferred to simply use the salt that is generated by default.
cost (integer) - which denotes the algorithmic cost that should be used. Examples of these values can be found on the crypt() page.
If omitted, a default value of 10 will be used. This is a good baseline cost, but you may want to consider increasing it depending on your hardware.
How Bcrypt encryption and decryption works:
Internally bcrypt() use uses PHP's built-in password_hash() function. password_hash() returns different values each time because it appends a random string (a "salt") to the password. The salt is actually contained in the output hash.
If the same password is hashed with the same salt, you will always get the same output. Therefore password_verify() looks at the stored hash, extracts the salt, and then hashes the given password with that same salt.
Related
I've been creating salted passwords in a ruby app what I thought was the standard way:
password_salt = BCrypt::Engine.generate_salt
password_hash = BCrypt::Engine.hash_secret(params[:pword], password_salt)
But on examining a test case, it looks like the salt is just being prepended to the hashed password:
Now, as I understand the point of salt, it's supposed to be concatenated onto the password BEFORE hashing, to push the password out of the size range that any pre-computed lookup-table, rainbow-table, etc.. could ever include. The point is, if someone gets your user database, they still can't crack the passwords using a lookup table. If the salt is prepended onto the password AFTER the hashing, and the hacker has downloaded the user table, it's not doing anything to secure the passwords. The hacker can just clip the salt off the front, get the original hash back, and then run a rainbow table on the hashes as if they were never salted.
Is this as much of a salt-fail as it appears to be? Is the problem in my code? Or is this Working As Expected And Secure for reasons I need to read up on? (Link, please.)
1) Salt is necessary for verification, and thus must be stored alongside the hashed cyphertext. Whether it's two fields in a database or one smushed-together string, is immaterial.
2) One salt = one rainbow table. Sure, attacker could generate a new rainbow table for your salt; however, since time to build a rainbow table is basically equivalent to time to try all passwords the rainbow table is to cover, it is not a weakness as long as you don't reuse salts.
The use case for rainbow tables is it allows you to compute it once, then quickly test multiple passwords. A rainbow table typically covers all the passwords up to certain length, or at least with some restriction (e.g. with certain alphabet, or using a certain vocab list). Let's say you have a rainbow table that covers all the passwords up to 8 characters. So if someone has password "password", rainbow table will know what its hashed form would be (e.g. "WASSPORD" - using caps for cyphertext and lowercase for plaintext for readability of the example), and you can look up "WASSPORD" in the rainbow table and see the password is "password" extremely quickly.
However, say you have salt "peanuts". The password becomes "peanutspassword", and if you then encrypt it, lets say you get "WASSUPMYCRACKER". Ruby would print "peanutsWASSUPMYCRACKER" as the salted hash. At verification time, you separate "peanutsWASSUPMYCRACKER" into "peanuts" (salt) and "WASSUPMYCRACKER" (hash); append "peanuts" to the user's input of "password" to form "peanutspassword", and encrypt it again - you get "WASSUPMYCRACKER", which is a match, and the user is logged in. However, note that "peanutspassword" is longer than 8 characters, and will not be in the up-to-8-characters rainbow table.
Now, you can generate a "peanuts" rainbow table, by taking the same dictionary as the original rainbow table, prepending "peanuts", and encrypting it, but it would typically take longer than just brute-forcing the password ("peanuts"+"a"? "peanuts"+"aardvark"?...) because, at least when you brute-force, you would stop when you find the correct password.
However, if you knew that a certain application always used "peanuts" as its salt, you could make a "peanuts" rainbow table, and that application is toast, and its owners in a real jam.
tl;dr: Salt can be public; it just can't be reused.
EDIT: You seem to be under the impression that Ruby just pastes salt onto the hash of the unsalted plaintext. If it did that, then one would expect that for the same plaintext, the result's hind end (the cyphertext) would be the same, no matter the salt. It is easy to see that's not how it works:
3.times { puts BCrypt::Engine.hash_secret("password", BCrypt::Engine.generate_salt) }
# $2a$10$jxUToaac5UUzVRH9SnllKe52W1JMLu5tm0LwyrZ4x4e75O1FCn9Ea
# $2a$10$oBs3TyhgR/r12.cz2kdzh.O9WHVZifDPqTEg0.hGOMn7Befv.8hSy
# $2a$10$8rfQA5nzCZ74DwNrmhAhdOmoQOVhJnBfh0ikiOB0W7ZptwsLPGUwi
As the salt changes, the cyphertext also changes. Thus, you can't "just clip the salt off the front, get the original hash back, and then run a rainbow table on the hashes as if they were never salted."
I had the same Problem in Python:
passw = "qay123"
salt = bcrypt.gensalt(14)
hashedpw = bcrypt.hashpw(passw, salt)
print salt
print hashedpw
Output:
$2b$14$fG3IoYLeIaf6gxZTHVR7eO <--- salt
$2b$14$fG3IoYLeIaf6gxZTHVR7eOVOC08a77IDOiu4At4FKKecw1xBYKXyG <-- salt + hashedpw
So, the hashpw-function just concatenates the salt value with the hash value which is insecure, because the hacker can split salt+hashpw at position 30
and so eliminates the salt.
For rainbow-tables the hacker must be able to read the hashes, so the cutting isn't a problem. The only problem he could have, would be when the length of the salt would vary.
My thought is that you follow your own thought and use bscrypt as seemingly not intended.
I am using the Laravel Hash Facade to generate a hash. This is then passed to a 3rd party service which uses the same hash in a callback. I use this to ensure that the request is "trusted". However, the Hash::make() creates a 60 character long string, but the 3rd party service only allows 32 characters.
If I apply md5() to the hash, I won't be able to use the Hash::check(). If i use substr(), then two - or more - hashes can result in the same string.
What is the best way to handle this scenario, in a secure way?
By default, Laravel Hash uses the password_hash() function with the BLOWFISH cypher, which generates the 60 character result. The 60 character result, however, is actually 28 characters of parameters, and the resulting 32 character hash.
The first 28 characters consists of the 4 character prefix ($2y$), the 2 digit cost (04 - 31), and the 22 character salt. If you store this first 28 characters in your application somewhere (ex. .env file), you can use it to check the 32 character hashes you generate and receive from the third party.
The password_hash() function is a built-in wrapper around the crypt() function, but it generates it's own salt dynamically. Since Laravel doesn't provide a way to provide the salt manually, you won't be able to use the Hash::make() method; you'll need to use the crypt() method directly, and pass in the proper data to trigger using the BLOWFISH cipher with your static salt. The generated results are still compatible with the password_verify() function, though, so you will still be able to use Hash::check() to verify the received hash (or just use password_verify() directly).
Below is hopefully a more helpful illustration with code and comments.
// This tells crypt() to use the BLOWFISH cypher
$prefix = '$2y$';
// This tells crypt() the number of rounds for the BLOWFISH algorithm to use.
// The higher the number, the longer it takes to generate a hash (good).
// Value must be two digits and between 04 and 31. 10 is default.
$cost = '10';
// This is the 22 character salt (including start and end dollar signs). This is
// the value normally dynamically generated by password_hash(), but you
// are storing a static value in your application.
$salt = '$thisisahardcodedsalt$';
// Concat the three parameters to generate the full 28 character BLOWFISH
// prefix. Instead of using the hardcoded variables above, you would
// probably just get the value out of the config (set by .env file).
$blowfishPrefix = $prefix.$cost.$salt;
// I don't know where your password is coming from, but this is the password
// that you were planning on using for your Hash::make() and Hash::check()
// calls.
$password = 'This is your password.';
// Hash the password to get your 60 character BLOWFISH cipher result.
$hash = crypt($password, $blowfishPrefix);
// The real hash is the last 32 characters. This is the value you pass to your
// third party service.
$hashToThirdParty = substr($hash, -32);
// Now we've generated a hash and sent it to the third party. Now we wait.
// ... at some point, the third party sends the hash back to you.
$hashFromThirdParty = $hashToThirdParty;
// Add your stored BLOWFISH prefix to the hash received from the third party,
// and pass the result into Hash::check() (along with your password).
$verified = Hash::check($password, $blowfishPrefix.$hashFromThirdParty);
// Since we're not using Hash::make() to generate the password, you may not care
// about using Hash::check() to check it. You can just use the underlying
// password_verify() function at this point, if you want.
$altVerified = password_verify($password, $blowfishPrefix.$hashFromThirdParty);
PHP function resources:
password_hash()
crypt()
password_verify()
Laravel code resources:
Hash::make() for the bcrypt hasher
Hash::check() for the bcrypt hasher
I have a external service which wishes to create user via a bespoke API that I have created in my Laravel application.
Rather than the remote end sending me the password in plain text I would like the remote end to hash the password first however I am unsure on how of the hashing using.
The remote end is using ASP.NET to make things slightly more complicated.
I am guessing Laravel is using CRYPT_BLOWFISH as that is the strongest available on the server but unsure how the salt works. Could anyone advise?
http://php.net/manual/en/function.crypt.php
CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail. Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to ยป this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
Example hash from Laravel:
$2y$10$RXyfF5/5qdBeGbwKgU5NR.p1OcgT5t3N.M5ql5PHm.UoxYGOogDWi
2y = blowfish prefix
10 = cost parameter
RXyfF5/5qdBeGbwKgU5NR. = 22 char salt
p1OcgT5t3N.M5ql5PHm.UoxYGOogDWi = bcrypt hash
Maybe this is a stupid question, but I wouldn't be shocked if some excellent brains come around with a proper solution or an idea: Is it possible to recalculate/transcode a salted sha512 string into a salted blowfish string ?
The (imo quite interesting) background is: I have a big database of SHA512+salt strings like that $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKREY4... (118 chars) and want to move to another hash/salt algorithm, generating strings like $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi (60 chars).
I'm intentionally NOT asking this on security.stackexchange.com as this is not a security question. It's about transcoding/recalculation.
Is it possible to recalculate/transcode a salted sha512 string into a salted blowfish string ?
Nope.
SHA2-512 is a cryptographic hash. Data goes in, but there's no way to get it back out. Do note that the thing you're using is a proposed but not standardized form of crypt that uses SHA2, and is not a raw SHA2 hash.
bcrypt (which is derived from, but is not Blowfish) is a key derivation function, which while a different thing than a cryptographic hash, still has the same result: data goes in, but there's no way to get it back out.
There is no way to simply convert one of these password hash types to another. This is true of almost every hash type. If you need to change the hash type, do so when the user next logs in.
I was reading a tutorial on how to salt a key to make your encryption secure, but couldn't make much of it. I don't know a lot about cryptography, and need some help. I am using commoncrypto to encrypt files, and am done, except for the fact that it isn't secure...
This is what I have:
- (NSData *)AES256EncryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
NSLog(#"You are encrypting something...");
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
If someone can help me out, and show me exactly how I would implement salt, that would be great! Thanks again!
dYhG9pQ1qyJfIxfs2guVoU7jr9oniR2GF8MbC9mi
Enciphering text
AKA jumbling it around, to try and make it indecipherable. This is the game you play in cryptography. To do this, you use deterministic functions.
Encrypting involves using a function which takes two parameters: usually a short, fixed length one, and an arbitrary length one. It produces output the same size as the second parameter.
We call the first parameter the key; the second, the plaintext; and the output, the ciphertext.
This will have an inverse function (which is sometimes the same one), which has the same signature, but given instead ciphertext will return the plaintext (when using the same key).
Obviously the property of a good encryption function is that the plaintext is not easily determinable from the ciphertext, without knowing the key. An even better one will produce ciphertext that is indistinguishable from random noise.
Hashing involves a function which takes one parameter, of arbitrary size, and returns an output of fixed size. Here, the goal is that given a particular output, it should be hard to find any input that will produce it. It is a one-way function, so it has no inverse. Again, it's awesome if the output looks completely random.
The problem with determinism
The above is all very well and good, but we have a problem with our ultimate goals of indecipherability when designing implementations of these functions: they're deterministic! That's no good for producing random output.
While we can design functions that still produce very random-looking output, thanks to confusion and diffusion, they're still going to give the same output given the same input. We both need this, and don't like it. We would never be able to decipher anything with a non-deterministic crypto system, but we don't like repeatable results! Repeatable means analysable... determinable (huh.). We don't want the enemy to see the same two ciphertexts and know that they came from the same input, that would be giving them information (and useful techniques for breaking crypto-systems, like rainbow tables). How do we solve this problem?
Enter: some random stuff inserted at the start.
That's how we defeat it! We prepend (or sometimes better, append), some unique random input with our actual input, everytime we use our functions. This makes our deterministic functions give different output even when we give the same input. We send the unique random input (when hashing, called a salt; when encrypting, called an Initialisation Vector, or IV) along with the ciphertext. It's not important whether the enemy sees this random input; our real input is already protected by our key (or the one-way hash). All that we were actually worried about is that our output is different all the time, so that it's non-analysable; and we've achieved this.
How do I apply this knowledge?
OK. So everybody has their app, and within it their cryptosystem protecting parts of the app.
Now we don't want to go reinventing the wheel with cryptosystems (Worst. Idea. Ever.), so some really knowledgable people have already come up with good components that can build any system (i.e, AES, RSA, SHA2, HMAC, PBKDF2). But if everyone is using the same components, then that still introduces some repeatability! Fortunately, if everyone uses different keys, and unique initial random inputs, in their own cryptosytem, they should be fine.
Enough already! Talk about implementation!
Let's talk about your example. You're wanting to do some simple encryption. What do we want for that? Well, A) we want a good random key, and B) we want a good random IV. This will make our ciphertext as secure as it can get. I can see you haven't supplied a random IV - it's better practice to do so. Get some bytes from a [secure/crypto]-random source, and chuck it in. You store/send those bytes along with the ciphertext. Yes, this does mean that the ciphertext is a constant length bigger than the plaintext, but it's a small price to pay.
Now what about that key? Sometimes we want a remember-able key (like.. a password), rather than a nice random one that computers like (if you have the option to just use a random key - do that instead). Can we get a compromise? Yes! Should we translate ASCII character passwords into bytes to make the key? HELL NO!
ASCII characters aren't very random at all (heck, they generally only use about 6-7 bits out of 8). If anything, what we want to do is make our key at least look random. How do we do this? Well, hashing happens to be good for this. What if we want to reuse our key? We'll get the same hash... repeatability again!
Luckily, we use the other form of unique random input - a salt. Make a unique random salt, and append that to your key. Then hash it. Then use the bytes to encrypt your data. Add the salt AND the IV along with your ciphertext when you send it, and you should be able to decrypt on the end.
Almost done? NO! You see the hashing solution I described in the paragraph above? Real cryptographers would call it amateurish. Would you trust a system which is amateurish? No! Am I going to discuss why it's amateurish? No, 'cus you don't need to know. Basically, it's just not REALLY-SUPER-SCRAMBLED enough for their liking.
What you need to know is that they've already devised a better system for this very problem. It's called PBKDF2. Find an implementation of it, and [learn to] use that instead.
Now all your data is secure.
Salting just involves adding a random string to the end of the input key.
So generate a random string of some length:
Generate a random alphanumeric string in cocoa
And then just append it to the key using:
NSString *saltedKey = [key stringByAppendingString:salt];
Unless salt is being used in a different way in the article you read this should be correct.
How a random salt is normally used:
#Ca1icoJack is completely correct in saying that all you have to do is generate some random data and append it to the end. The data is usually binary as opposed to alphanumeric though. The salt is then stored unencrypted alongside each hashed password, and gets concatenated with the user's plaintext password in order to check the hash every time the password gets entered.
What the is the point of a SALT if it's stored unencrypted next to the hashed password?
Suppose someone gets access to your hashed passwords. Human chosen passwords are fairly vulnerable to being discovered via rainbow tables. Adding a hash means the rainbow table needs to not only include the values having any possible combination of alphanumeric characters a person might use, but also the random binary salt, which is fairly impractical at this point in time. So, basically adding a salt means that a brute force attacker who has access to both the hashed password and the salt needs to both figure how how the salt was concatenated to the password (before or after, normally) and brute force each password individually, since readily available rainbow tables don't include any random binary data.
Edit: But I said encrypted, not hashed:
Okay, I didn't read very carefully, ignore me. Someone is going to have to brute-force the key whether it's salted or not with encryption. The only discernable benefit I can see would be as that article says to avoid having the same key (from the user's perspective) used to encrypt the same data produce the same result. That is useful in encryption for different reasons (encrypted messages tend to have repeating parts which could be used to help break the encryption more easily) but the commenters are correct in noting that it is normally not called an salt in this instance.
Regardless, the trick is to concatenate the salt, and store it alongside each bit of encrypted data.