Keying Hashes/Login Security? - security

I am going to use hashing function, with salt:
$stored_pass = md5(md5($salt).md5($plain_pass)); **
/// I am wanting to know an efficient way to key/authenticate that hash.
I read up a bit about keying hashes, and MAC's, but didn't quite grasp HMAC's; so just figured that wrapping the hash in an encryption function, like aes, would work. ///
EG
$stored_pass = aes(md5(md5($salt).md5($plain_pass))); **
I would like to know the following:
Why key hashes for login? (Examples would be nice)
Methods for keying hashes? (Specifically for use in loign)
Disadvantages?
Are there still ways our hashing/password validation system could be more secure? (After we factor in hash, salted, keyed)
** What is the most "secure hashing algorithm?
" Secure by hardest to crack.
/// I read that sha-512 was one of the most secure; but then read contradicting articles stating, sha in any form should not be used, and something like bcrypt/scrypt should be used or PBKDF2. Then I read that bcrypt shouldn't be used, and has limitations. So I'm a bit confused. ///
When providing hash algorithms, I'd like to know the following:
What are the limitations of the hash algorithm?
Upsides?
Downsides?
/// My main concern is user security, so if that means less 'speed' I'm not bothered. In my eyes the login function's purpose is user security, so reducing the credibility of that security for a few milliseconds seems silly to me. (Just personal opinion). ///
Also I'd appreciate comments on my function:
$stored_pass = aes(md5(md5($salt).md5($plain_pass))); **
And any alternatives would be appreciated.
Note: I know some suggest using some sort of api for this, with functions already written, but that's not really what I'm looking for. I'd prefer to learn more about it myself.

I am going to use hashing function, with salt:
$stored_pass = md5(md5($salt).md5($plain_pass));
Don't use MD5. Learn how to safely store passwords instead. That page might very well answer all of your questions.
/// I am wanting to know an efficient way to key/authenticate that hash.
I read up a bit about keying hashes, and MAC's, but didn't quite grasp HMAC's; so just figured that wrapping the hash in an encryption function, like aes, would work. ///
MACs aren't the proper tool for the job here either, even if it seems tempting to use them. Maybe this primer on cryptography concepts will help illuminate the difference, but basically:
MAC - Provide tamper-resistance for a message.
Password hash - Slow, salted hashing algorithm.
They're totally different use-cases. (Although, PBKDF2 uses a MAC algorithm internally, so I can understand if you were confused by that.)
Encrypting a hash isn't what a MAC does, either. HMAC in particular is basically:
Hash your message (with a minor transformation).
Hash the key and output of step 1 (with another minor transformation).
/// I read that sha-512 was one of the most secure; but then read contradicting articles stating, sha in any form should not be used, and something like bcrypt/scrypt should be used or PBKDF2. Then I read that bcrypt shouldn't be used, and has limitations. So I'm a bit confused. ///
Easy answer:
Use password_hash() to create password hashes.
Use password_verify() to authenticate passwords against hashes.
Stop worrying about it.
The limitations of bcrypt (truncating after 72 characters OR the first NUL byte -- which are mentioned in the first article I linked to) aren't a practical concern, and rolling your own crypto is definitely less secure than using bcrypt.
If you are absolutely concerned about the bcrypt limitations, do this:
function bcrypt_sha384_hash($password, $cost = 10)
{
$fasthash = base64_encode(
hash('sha384', $password, true)
);
return password_hash($fasthash, PASSWORD_BCRYPT, ['cost' => $cost]);
}
function bcrypt_sha384_verify($password, $storedHash)
{
$fasthash = base64_encode(
hash('sha384', $password, true)
);
return password_verify($fasthash, $storedHash);
}

Related

return original value of sha256 [duplicate]

This question already has answers here:
How to decrypt a SHA-256 encrypted string?
(4 answers)
Closed 1 year ago.
I have a table called user in my database and I save the passwords in sha256. And I am wondering if I can now get the original value from the sha256, to display it on the user profile frontend.
Example
use sha2::{Digest, Sha256};
fn test() {
let password = "secret value";
let password_sh256 = Sha256::digest(password.as_bytes());
let encrypted_password = format!("{:x}", password_sh256);
println!("result: {:?}", encrypted_password);
// result: "c3a57afaa51d985ac0b4117f509e2ce6dd94d520e441778736a945b4cb941755"
}
Now how could you have the original value of the variable named password making use of the variable named encrypted_password?
I appreciate any help.
SHA-256 is designed to be computationally infeasible (in simpler terms: practically impossible) to invert like you want to do. In fact, it is provably the case that there are multiple inputs that hash to the same value (although it is also currently computationally infeasible to find them) so at best, you would be able to find some input that hashed to the same value. However, as mentioned, it is very unlikely that anyone can presently do so.
Additionally, there are some things to mention. First, you should never show the user their plaintext password. You don't know if the user is in a coffee shop, library, or other public place where others might be shoulder-surfing, so you wouldn't want to expose this. In addition, you don't want to be able to invert the password for security reasons (because that means anyone else can), so there's no way to actually show it.
Furthermore, you don't want to use plain SHA-256 for password hashing. The reason is that if people pick bad passwords, like “password123,” then all the users with the bad password will have the same password hash, and it's also easy to make a giant list of passwords that are known to be compromised and look them up in the list. What you want to do is use a password hashing function like Argon2 or bcrypt that (a) uses a unique salt (random data) for each password and (b) iterates the operation multiple times so that it's slow and guessing many passwords takes a long time. Fortunately, there are libraries in Rust for doing just this, and the argon2 crate has great documentation explaining how to do just this.

What hashing algorithm does express-session use for session id cookie?

Title says it all, I am just interested in what algorithm is used to hash these cookies, and I need help, because i couldn't find out it myself by looking at the sources.
Thanks in advance.
It doesn't use a hashing algorithm. It uses uid(24) instead. uid(n) generates random, unpredicable, values:
generateSessionId is here: https://github.com/expressjs/session/blob/2d54f0dca1506883bebc634fcb7135c2f02c47cd/index.js#L507
...which calls uid(24)
...which is in the uid-safe library: https://www.npmjs.com/package/uid-safe
...which generates cryptographically safe random numbers. Session-identifiers must be unpredictable.
Session identifiers (in any context, really) should not be based on a hash of anything anyway because:
Session content tends to be mutable, not immutable, so using a hash of a session's state or content would make it impossible to retrieve it after it's been changed.
If two users coincidentally have the same session-state content then they'd have the same session-id value, which isn’t what you want either.

Proper way to use salt along with hashing

During a discussion with a couple of other people, I read the argument that
sha512(salt + username + password) is bad,
sha512(username + password) is worse and
sha512(password) is plain idiotic.
While I partly agree, what's really the best security? Is there anything safer than using an user unique salt along with a slow hashing method such as SHA512? What's the real way to go? Argue on!
Please edit the title if you find it bad.
Generate random salt for each password.
Avoid MD5, and even SHA-1.
Use a slow hashing algorithm; SHA-256 seems to be a good choice for now.
Password storage is one of those rare occasions where there is some benefit to having your own (overall) algorithm. Consider an attacker with a rainbow table; if your password storage algorithm varies from the one used to generate their rainbow table enough to change the generated values, that rainbow table is of no use. The attacker would need to know your algorithm, then generate a new table. If you choose a slow hashing algorithm, generating a new table is very expensive.
By "overall" algorithm, I mean the complete definition of how you transform the plaintext password into the stored value. E.g. SHA-256("mypassword" + "[[" + 40-char-random-alphanum-salt + "]]"). If you change that to use angle brackets instead of square brackets, you've changed the rainbow table necessary to exploit your stored passwords. Note that I'm not advocating writing your own hash algorithm; you should still choose a cryptographically secure hash algorithm.
See this article by the author of MD5. He makes the two main points I repeated above: 1) if you use a fast hashing algorithm, you're missing the point, and 2) reuse of overall algorithms allows re-use of rainbow tables.
When discussing the recent LinkedIn leak, somebody brought up this link about bcrypt. I think I agree... we should be using functions that increase the calculation time exponentially according to a factor. That's the only way we can beat people trying to use clusters or GPUs to do their hashing calculations.
My understanding is, that repeated hashing (for computational cost) & a good random salt, should defeat all but seriously determined cryptographic attackers.
Hashing passwords in the database, and over the network, avoids plaintext being recoverable (and usable elsewhere) by a snooper or attacker who does get in.
Basically this is more or less the scheme, used by the Wordpress authentication:
var SALT = 64 random characters;
var NUM_HASHES = about 1000; // can be randomized
var hashedResult = inputPassword;
for (int i = 0; i < NUM_HASHES; i++) {
var dataToHash = SALT + hashedResult;
hashedResult = secureHash( dataToHash);
}
//... can now store or send.
This use of a random salt, and looping hash, defeats any rainbow tables or single-level 'hash collision', 'hash weakness' attack. Only brute-forcing the complete keyspace, each key through 1000 iterations of the hash function, is believed to defeat it :)

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.

Random access encryption with AES In Counter mode using Fortuna PRNG:

I'm building file-encryption based on AES that have to be able to work in random-access mode (accesing any part of the file). AES in Counter for example can be used, but it is well known that we need an unique sequence never used twice.
Is it ok to use a simplified Fortuna PRNG in this case (encrypting a counter with a randomly chosen unique key specific to the particular file)? Are there weak points in this approach?
So encryption/decryption can look like this
Encryption of a block at Offset:
rndsubseq = AESEnc(Offset, FileUniqueKey)
xoredplaintext = plaintext xor rndsubseq
ciphertext = AESEnc(xoredplaintext, PasswordBasedKey)
Decryption of a block at Offset:
rndsubseq = AESEnc(Offset, FileUniqueKey)
xoredplaintext = AESDec(ciphertext, PasswordBasedKey)
plaintext = xoredplaintext xor rndsubseq
One observation. I came to the idea used in Fortuna by myself and surely discovered later that it is already invented. But as I read everywhere the key point about it is security, but there's another good point: it is a great random-access pseudo random numbers generator so to speak (in simplified form). So the PRNG that not only produces very good sequence (I tested it with Ent and Die Hard) but also allow to access any sub-sequence if you know the step number. So is it generally ok to use Fortuna as a "Random-access" PRNG in security applications?
EDIT:
In other words, what I suggest is to use Fortuna PRNG as a tweak to form a tweakable AES Cipher with random-access ability. I read the work of Liskov, Rivest and Wagner, but could not understand what was the main difference between a cipher in a mode of operation and a tweakable cipher. They said they suggested to bring this approach from high level inside the cipher itself, but for example in my case xoring the plain text with the tweak, is this a tweak or not?
I think you may want to look up how "tweakable block ciphers" work and have a look at how the problem of disc encryption is solved: Disk encryption theory. Encrypting the whole disk is similar to your problem: encryption of each sector must be done independently (you want independent encryption of data at different offsets) and yet the whole thing must be secure. There is a lot of work done on that. Wikipedia seems to give a good overview.
EDITED to add:
Re your edit: Yes, you are trying to make a tweakable block cipher out of AES by XORing the tweak with the plaintext. More concretely, you have Enc(T,K,M) = AES (K, f(T) xor M) where AES(K,...) means AES encryption with the key K and f(T) is some function of the tweak (in your case I guess it's Fortuna). I had a brief look at the paper you mentioned and as far as I can see it's possible to show that this method does not produce a secure tweakable block cipher.
The idea (based on definitions from section 2 of the Liskov, Rivest, Wagner paper) is as follows. We have access to either the encryption oracle or a random permutation and we want to tell which one we are interacting with. We can set the tweak T and the plaintext M and we get back the corresponding ciphertext but we don't know the key which is used. Here is how to figure out if we use the construction AES(K, f(T) xor M).
Pick any two different values T, T', compute f(T), f(T'). Pick any message M and then compute the second message as M' = M xor f(T) xor f(T'). Now ask the encrypting oracle to encrypt M using tweak T and M' using tweak T'. If we deal with the considered construction, the outputs will be identical. If we deal with random permutations, the outputs will be almost certainly (with probability 1-2^-128) different. That is because both inputs to the AES encryptions will be the same, so the ciphertexts will be also identical. This would not be the case when we use random permutations, because the probability that the two outputs are identical is 2^-128. The bottom line is that xoring tweak to the input is probably not a secure method.
The paper gives some examples of what they can prove to be a secure construction. The simplest one seems to be Enc(T,K,M) = AES(K, T xor AES(K, M)). You need two encryptions per block, but they prove the security of this construction. They also mention faster variants, but they require additional primitive (almost-xor-universal function families).
Even though I think your approach is secure enough, I don't see any benefits over CTR. You have the exact same problem, which is you don't inject true randomness to the ciphertext. The offset is a known systematic input. Even though it's encrypted with a key, it's still not random.
Another issue is how do you keep the FileUniqueKey secure? Encrypted with password? A whole bunch issues are introduced when you use multiple keys.
Counter mode is accepted practice to encrypt random access files. Even though it has all kinds of vulnerabilities, it's all well studied so the risk is measurable.

Resources