How To, and How Not to Hash Passwords
CS 463
Lecture, Dr. Lawlor
Bad
How not to hash passwords: LM_hash
LMhash = concat(
hex(DESencrypt("KGS!@#$%",uppercase(password.substr(0,7)))),
hex(DESencrypt("KGS!@#$%",uppercase(password.substr(7,7))))
);
Mistakes:
- Use an obsolete cipher (DES)
- Remove entropy before hashing (uppercase all passwords)
- Limit password length by truncation (14 bytes)
- Hash the password in brute forceable chunks (7 bytes)
- Combine the per-chunk hashes by concatenating them. This
allows you to trivially extract each half.
- Don't use a salt/nonce, so the hash is a perfectly
deterministic function of the input, allowing attackers to look
up the hash in a Rainbow
Table.
- Hand out this hash over the network to anyone! As of
Windows Vista, this network hole is now plugged by
default. Hashed passwords are still stored in
C:\Windows\System32\config\SAM,
although now that file is locked by the kernel, and encrypted.
Still, it could be worse:
- At least they used DES, which is still relatively
secure. They could have rolled their own encryption, which
would almost certainly have been worthless.
- Flipping the order of the DESencrypt parameters (encrypt
password using fixed key) would have allowed anybody to
DESdecrypt the exact password.
One annoying thing about bad network protocols: they're almost
impossible to kill. The problem is that *every* client needs
to be upgraded before the server can stop using the old protocol
(even the ancient Windows 98 machine in the back, running the
plotter).
Good
How to hash passwords well: HTTP
Digest_access_authentication
HA1 = MD5(username + realm + password);
HA2 = MD5(method + digestURI);
response = MD5(HA1 + nonce + HA2);
Good Features:
- The server can precompute HA1, and only store the hash for
each user, not the raw password.
- The server gets to choose a "nonce" (random number) to prevent
a bad client from just repeating the response of a good client
(a "replay attack").
It'd still be possible to improve this, though:
- If HA1 included a server_nonce, the server could protect
itself against stolen hashes.
- The client should get to choose a nonce, too.
These improvements were implemented in RFC2617.