SD security
L20: Authentication¶
Security is about goals (policy) and assumptions (threat model).
Policy 1: provide authentication for users
1 | check_password(username, inputted_password): |
Threat model 1: adversary has access to the entire stored table.
Problem 1: An adversary (with access to the stored table) can just read the passwords directly.
Attempt 0: store plaintext passwords on server
Attempt 1: use hash function -> store hashes of passwords on the server.
- Hash function H(x): There is no secret hash function. Existing hash functions are well-known. H(x) takes inputs of arbitrary size and outputs a fixed-length string.
- Slow hash function H(x): it’s slow to compute H(x) given x. These function are technically called key derivation functions.
Problem 1.1 An adversary can still have access to password by pre-computing hashes for passwords.
Using slow hash function can’t prevent an adversary from building the same table as before. They can build but for fewer passwords because it takes much longer to calculate a single hash.
Attempt 2: add a random string
A random value is called a salt. These salts are stored in plaintext and not a secret. We concatenate the password and the salt and store the hash of that string to the table. The table can’t be pre-computed without knowing the salt.
Use cases: limit transmission of passwords via cookies. Transmitting a password repeatedly makes uses vulnerable to attacks.
cookie = {username, expiration, H(server_key | username | expiration)}
Threat model 1.1: An adversary can observe the cookie.
Challenge-response protocols: authenticate users without ever transmitting the password. Valid servers use salted hashes.
An adversary learns the salted hash by eavesdropping the cookie but can’t reverse-engineer the password.
Threat model 1.3: an adversary owns a server and is trying to convince the user to send their password directly to the adversary.
Many password alternatives have trade-offs on usability, complexity and security.