bcrypt number of possibile password combination - security

I'm trying to understand how bcrypt works under the hood. For example, if i create a hash a password, for example "hello", i receive:
$2y$12$wsoPmf7KXqGPWke9io0YbOf2Vln61awWwpCS./kGH5.rVE8Trbc6q
So, every time i hash another "hello", i receive another crypt password, i think the number of possible password combination in bcrypt depend to the number of round, for example 12 (in my case).
With a round of 12, how many combination of "hello" exist exactly? And how i can calculate that?

Bcrypt includes a 128-bit (16 byte) salt, encoded in modular crypt format as the first 22 characters of the hash. In your example, the salt is wsoPmf7KXqGPWke9io0YbO.
There is a different password -> hash for each salt, so there are 2^128 or approximately 10^38 possible hashes per password for a given cost parameter. If you change the cost parameter, that will generate a different set of 10^38 possible hashes (but the size of the cost parameter doesn't increase or decrease the number of possible hashes).

Related

I got an asignment to decrypt Password hash?

I am new to Security and was trying to learn how can I crack my own user's databases. I have user's salt, password hashes and username. The SHA-256 password hash is computed from the concatenation of 3 strings i.e. one constant string potPlantSalt, the password, and the
salt. SHA-256 output has been converted into the hexadecimal format and truncated
to 32 characters before storing into the database as a string.
truncate ( hexstring ( SHA256 ( " potPlantSalt " + password + salt ) ) )
I have data like:
username: max
password hash: 2b1ac087bd54ea9dcbfba2c3e63b2335
salt: 5aa8698c4022fe1d
How can I know above user decoded password?
SHA256 is a one way function, this means that given the output of SHA256, it is very, very difficult and time consuming to compute an input. So time consuming that it is impractical on current hardware.
So instead you have to use a brute force attack: hash millions of potential passwords until you find one that produces the same hash as stored in the database. Note that this must not necessarily be the original password (hash collision).
If we assume that the user did not use a combination of random characters, the search space can be reduced by using a Dictionary attack.
You can reduce computation time by using more storage space with Rainbow tables.

hashing passwords with pbkdf2 crypto does not work correctly

Password security is not my strong suit. Please help me out.
I use node.js 4.2.3 express 4.13.3. I found some examples to hash and salt passwords with crypto's pbkdf2.
Here is my code.
var salt = crypto.randomBytes(10).toString('base64');
console.log("salt > "+salt);
crypto.pbkdf2(pass, salt , 10000, 150, 'sha512',function(err, derivedKey) {
pass = derivedKey.toString('hex');
});
The final derivedKey does not include the salt. What am I missing? Should I join the two strings manually before saving?
Why some examples use base64 and others hex? To get different string lenghts? What is the default, so I can use it?
Why not to use basic64 in both salt and hashed password?
Is the final derivedKey string UTF8? Or this has to do only with the database it gets saved? My database is in UTF8.
Thanks
Yes, store the salt yourself, separately, unencrypted. Make sure it's randomly generated.
More importantly, you're crippling your PBKDF2 encryption by asking for 150 bytes (bytes per nodejs.org) of key length - SHA512 is a fantastic choice, but it only provides 64 bytes of native output. To get 10,000 iterations of 150 bytes of output, PBKDF2/RFC2898 is going to execute 30,000 times, while an offline attacker will only need to run 10,000 iterations and match the first 64 bytes (if the first 64 match, then the rest will too); you gave them a 3:1 advantage for free!
Instead, if you're happy with the work factor, you should use 30,000 iterations of 64 bytes of output - you'll spend the same amount of time, no difference, but the attacker now has to do 30,000 iterations too, so you took away their 3:1 advantage!
When you pass the salt to the PBKDF2 function, if you can, just pass in the pure binary. Also, the node.js docs say - reasonably "It is recommended that the salts are random and their lengths are greater than 16 bytes." This means binary 16 bytes, before the base64 or hex or whatever conversion if you want one.
You can save both salt and derivedkey as BINARY of the correct length for the most efficient storage (then you don't have to worry about UTF-x vs. ASCII), or you can convert one or both to BASE64 or hexadecimal, and then convert back to binary as required. Base64 vs hex vs binary is irrelevant as long as the conversions are reconverted as needed.
I'd also make the number of iterations a stored field, so you can easily increase it in the years to come, and include a field for the "version" of password hashing used, so you can easily change your algorithm in the years to come if need be as well.
Encryption works with data, not strings, this includes the encryption key. PBKDF2 produces a data key, which can be easily converted to a string, this conversion is necessary because many data bytes have no corresponding print character or unicode code point. Many scripting languages do not handle data well so the data is many times converted to Base64 or hexadecimal (hex).
You can use Base64 or hexadecimal for the salt and hashed password, just be consistent on all uses.
The salt and iteration count need to be the same for creating an checking, you will need to combine them or save them separately.
Your code is converting the derived key to hexadecimal, that is fine and base64 would also be fine. Again this is necessary because not all data bytes are UTF-8.

Does a Good Password Salt Need to Include Both Numbers and Letters?

I am salting newly created passwords before hashing them with an encryption algorithm. I generate my salts using a random number function.
Are you compromising security if your salts are only comprised of numbers (with no letters) or does this make no difference at all?
A salt should be unique (ideally for every password in the world), and unpredictable. The best you can do with a deterministic computer is, to get a random number, and hope that the returned value is nearly unique. So the more possible combinations you have, the bigger is the chance that the salt is unique.
Some hash algorithms define a number and an alphabet of accepted characters. PHP's BCrypt for example, expects a salt containing 22 characters from this alphabet:
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
You get the most possible combinations, using all characters of the alphabet, and not only the characters 0-9. Of course a longer salt with a small alphabet (0-9) can have as much combinations, as a shorter salt with a big alphabet (0-9,a-z,...).
To make it short, use all possible characters, and as many characters as your hash algorithm expects.
P.S: If you use a key-derivation function like BCrypt (and you really should), then you cannot salt the password befor hashing, instead you have to pass the salt to the hash function.

How safe is this procedure?

I'm going to use this kind of approach to store my password:
User enters password
Application salts password with random number
Then with salted password encrypt with some encryption algorithm randomly selected array of data (consisting from predefined table of chars/bytes)
for simplicity it can be used just table of digits, so in case of digits random array would be simply be long enough integer/biginteger.
Then I store in DB salt (modified value) and encrypted array
To check password validity:
Getting given password
Read salt from DB and calculate decrypt key
Try to decrypt encrypted array
If successfull (in mathematical mean) compare decrypted value byte by byte
does it contains only chars/bytes from known table. For instance is it integer/biginteger? If so - password counts as valid
What do you think about this procedure?
In a few words, it's a kind of alternative to using hash functions...
In this approach encryption algorithm is about to be used for calculation of non-inversible value.
EDIT
# Encrypt/decrypt function that works like this:
KEY=HASH(PASSWORD)
CYPHERTEXT = ENCRYPT(PLAINTEXT, KEY)
PLAINTEXT = DECRYPT(CYPHERTEXT, KEY)
# Encrypting the password when entered
KEY=HASH(PASSWORD)+SALT or HASH(PASSWORD+SALT)
ARRAY={A1, A2,... AI}
SOME_TABLE=RANDOM({ARRAY})
ENCRYPTED_TABLE = ENCRYPT(SOME_TABLE, KEY + SALT)
# Checking validity
DECRYPT(ENCRYPTED_TABLE, PASSWORD + SALT) == SOME_TABLE
if(SOME_TABLE contains only {ARRAY} elements) = VALID
else INVALID
From what you write I assume you want to do the following:
# You have some encryption function that works like this
CYPHERTEXT = ENCRYPT(PLAINTEXT, KEY)
PLAINTEXT = DECRYPT(CYPHERTEXT, KEY)
# Encrypting the password when entered
ENCRYPTED_TABLE = ENCRYPT(SOME_TABLE, PASSWORD + SALT)
# Checking validity
DECRYPT(ENCRYPTED_TABLE, PASSWORD + SALT) == SOME_TABLE
First off: No sane person would use such a homemade scheme in a production system. So if you were thinking about actually implementing this in the real world, please go back. Don't even try to write the code yourself, use a proven software library that implements widely accepted algorithms.
Now, if you want to think about it as a mental exercise, you could start off like this:
If you should assume that an attacker will know all the parts of the equation, except the actual password. The attacker, who wants to retrieve the password, will therefore already know the encrypted text, the plaintext AND part of the password.
The chance of success will depend on the actual encryption scheme, and maybe the chaining mode.
I'm not a cryptanalyst myself, but without thinking about it too much I have the feeling that there could be a number of angles of attack.
The proposed scheme is, at best, slightly less secure than simply storing the hash of the password and salt.
This is because the encryption step simply adds a small constant amount of time to checking if each hash value is correct; but at the same time it also introduces classes of equivalent hashes, since there are multiple possible permutations of ARRAY that will be recognised as valid.
You would have to brute force the encryption on every password every time someone logs in.
Read salt from DB and calculate decrypt key
This can't be done unless you know what the password is before hand.
Just salt (And multiple hash) the password.

Password salts: prepending vs. appending

I just looked at the implementation of password hashing in Django and noticed that it prepends the salt, so the hash is created like sha1(salt + password), for example.
In my opinion, salts are good for two purposes
Preventing rainbow table lookups
Alright, prepending/appending the salt doesn't really make a difference for rainbow tables.
Hardening against brute-force/dictionary attacks
This is what my question is about. If someone wants to attack a single password from a stolen password database, he needs to try a lot of passwords (e.g. dictionary words or [A-Za-z0-9] permutations).
Let's assume my password is "abcdef", the salt is "salt" and the attacker tries all [a-z]{6} passwords.
With a prepended salt, one must calculate hash("salt"), store the hash algorithm's state and then go on from that point for each permutation. That is, going through all permutations would take 26^6 copy-hash-algorithm's-state-struct operations and 26^6 hash(permutation of [a-z]{6}) operations. As copying the hash algorithm's state is freakin fast, the salt hardly adds any complexity here, no matter how long it is.
But, with an appended salt, the attacker must calculate hash(permutation of [a-z]{6} + salt) for each permutation, leading to 26^10 hash operations. So obviously, appending salts adds complexity depending on the salt length.
I don't believe this is for historical reasons because Django is rather new. So what's the sense in prepending salts?
Do neither, use a standard Key derivation function like PBKDF2. Never roll your own crypto. It's much too easy to get it wrong. PBKDF2 uses many iterations to protect against bruteforce which is a much bigger improvement than the simple ordering.
And your trick pre-calculating the internal state of the hash-function after processing the salt probably isn't that easy to pull off unless the length of the salt corresponds to the block-length of the underlying block-cypher.
If salt is prepended, attacker can make hash state database for salts (assuming salt is long enough to make a hashing step) and then run dictionary attack.
But if salt is appended, attacker can make such database for password dictionary and additionally compute only salt's hash. Given that salt is usually shorter than password (like 4 chars salt and 8 char password), it will be faster attack.
You are making a valid point, of course; but , really, if you want to increase time it takes to calculate hash, just use longer hash. SHA256 instead of SHA1, for example.

Resources