User sets a password.
- A random piece of data, so called salt, is generated.
- The salt is appended to the password.
- The resulting text is hashed. This process is intentionally resource intensive, like hashing the resulting text 2^12 times.
- The parameters like salt, iteration number, parallelism and etc. are appended to the digest.
- The result is stored in a database.
User enters a password for login.
- The entry from database is retrieved.
- The digest, salt and parameters are parsed.
- The entered password is hashed according to the parsed salt and paramaters.
- Check is done by comparing the calculated digest and the parsed digest.
Default authentication method for systems using LDAP.
People tend to use the same password on different platforms.
Once you learn their password on a platform, you can try to login with that password on different platforms.
Therefore, passwords should be kept secret, as it should be, even from developers and admins.
Since, plain text passwords can be read easily.
If passwords are encrypted, it can be decrypted using keys.
If keys are note used, passwords cannot be validated agains ciphertexts.
We need a way to obfuscate passwords irreversibly.
That's why we use hash functions.
We can simply hash passwords using SHA256.
However, there is a catch.
Hash functions always produce the same output, so called digest, when fed with the same input.
That leads to users having same password, having same digest.
Which makes it easier to guess ones password.
Moreover, an attacker can pre-hash some common passwords and store them in a database,
when the attacker obtains a password digest, they can directly search it in the database to find corresponding password, which is called dictionary attack
.
We can use salt to create different digests and store salt appended to the password.
This way an attacker cannot use a dictionary database since the salt makes the difference.
However, hash functions like SHA256 are developed to be fast to do integrity check with big files.
Therefore, an attacker can focus on one single password digest,
hashes common passwords with the salt to find a digest match and is still fast enough to do it in a feasible time, which is called rainbow table attack
.
We need to slow down the attacker so much to make the process infeasible.
There comes the purposfuly slowed hash functions(bcrypt, scrypt, argon2id).
These hash functions create digests too slow for an attacker to do brute-force attack, since the attacker has to do a lot of guesses (O(n)).
It does not harm login process that much since it does it only once (O(1)).
If A sends public key to B and B wants to check if A has the corresponding private key
1. method
-
B generates some random data
-
and encrypt it with the public key
-
sends the ciphertext to A
-
A decrypts the ciphertext with the private key
-
and sends the plain data to B
-
B then checks if the generated and received data match
2. method
-
B generates some random data
-
sends it to A without encrypting
-
A encrypts the plain data with the private key
-
then sends the ciphertext to B
-
B decrypts the ciphertext with the public key
-
then checks if the data sent and decrypted match
3. method
-
B generates some random data
-
and encrypt it with the public key
-
sends the ciphertext to A
-
A decrypts the ciphertext with the private key
-
then encrypts it with the private key
-
then sends the ciphertext to B
-
B decrypts the ciphertext with the public key
-
then checks if the data generated and decrypted match
A chat app scenario:
- Clients have private key of their own and public key of anyone.
- A wants to send a message to B.
- A encyrpts message using the public key of B, so that only B can read the message.
- A also encrypts the message with the private key, so that B can verify the message has been sent from A.
Default authentication method for Certificate Based Authentication, FIDO / WebAuthN / Client to Authenticator Protocol.
When the communication between the client and the server is not encrypted, the system is vulnerable to MITM(man in the middle) attack. In order to mitigate password sniffing, password is not sent over the untrusted connection. (Zero Knowledge Proof?)
Here is how password authentication works, without passing password over the wire:
-
Client sends a username and a CLIENT nonce.
-
Server finds the password hash for the given username, then sends the salt, the iteration count and a SERVER nonce.
-
Client hashes the password with the salt, iteration count and the SERVER nonce, then sends the digest to server.
client_proof = hash(hash(pass, salt, iter), server_nonce)
-
Server hashes the stored password hash with the CLIENT nonce, then sends the digest to client.
server_proof = hash(password_hash, client_nonce)
-
Client hashes the password with the salt, iteration count and the CLIENT nonce, then checks if server has sent the correct digest.
expected_server_proof = hash(hash(pass, salt, iter), client_nonce)
-
Server hashes the stored password hash with the SERVER nonce, then checks if client has sent the correct digest.
expected_client_proof = hash(password_hash, server_nonce)
-
If the digests match, it mutually authenticate both parties.
Registration can be done with user hashing their own password and sending the digest and the parameters to the server.
- When a service requires an authenticator app, it generates a secret and a QR code to transfer the secret.
- An authenticator app scans the QR code and gets the secret.
- From this point on, they are able to create the same authentication code without even communicating anymore,
- using the secret and current time.
- The code may be valid for 30 or 60 second by a simple modulus operation on current time.
- Once a code is used, it is marked as used in the server.
Read (One Time Password - OTP - 2FA):
- A code is generated and stored in a cache or database.
- The code is sent through a channel like email, phone, or SMS.
- If user enters the same code, then it is proven that the user has read access to those.
Write:
- The user is asked to make a specific modification to some resource.
- The service then checks if the modification has been made to verify write access.
- Such as DNS/HTTP challenge to prove domain ownership.
Symmetric:
- The hash of a message (e.g., JSON data) is generated using a secret key.
- The generated hash is then compared with the provided hash to verify the message's integrity and authenticity. (HS256)
Asymmetric:
- The message's hash is created and then encrypted with a private key.
- The recipient decrypts the ciphertext using the corresponding public key and compares the decrypted hash with the calculated hash from the message.
- If they match, the message is authenticated. (RS256)
Users authenticate by inserting a smart card into a reader. The card contains a secure cryptographic key that is used to verify the user's identity. (YubiKey)
This method uses unique biological traits of the user, such as fingerprints, facial recognition, iris scans, or voice recognition, to authenticate them.
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) challenges the user with a task that is easy for humans but difficult for bots, like recognizing distorted text or identifying objects in images.
This method analyzes user behavior, such as typing speed, mouse movements, or browsing patterns, to authenticate users. It creates a unique profile for each user and checks for consistency during login.
Kerberos is a network authentication protocol designed to provide strong authentication for client-server applications using secret-key cryptography.
It works based on the concept of "tickets" to allow nodes to prove their identity in a secure manner.
When a user tries to authenticate, they first request a Ticket Granting Ticket (TGT) from the Key Distribution Center (KDC).
Once they have the TGT, they can use it to request service tickets for access to specific services.
The service tickets are used to authenticate the user to each service without needing to transmit passwords across the network.
When two parties need to communicate securly on an untrusted channel, they prefer to encrypt the dialog.
For this end, they will need to agree on a key so that both sides can understand eachother.
However, any session they start will be able to be observed.
Therefore, they cannot exchange keys on this untrusted channel.
They rather use this algorithm to obtain a shared secret key without sending the key itself.
They agree on some public values.
Let's say Alice and Bob want to obtain a shared secret.
Public values they agree on
p
: a big prime numberg
: a primitive root of p, in range [1,p)
Private key of Alice a
: a number in range [1,p)
Public key of Alice A
: g^a mod p
Private key of Bob b
: a number in range [1,p)
Public key of Bob B
: g^b mod p
They send their own public key to eachother.
Alice computes the shared key as B^a mod p
= (g^b mod p)^a mod p = g^ba mod p
Bob computes the shared key as A^b mod p
= (g^a mod p)^b mod p = g^ab mod p
Since g^ba = g^ab, they have the shared secret.
Transforming data into a specific format (e.g., base64). No secrets are used; it’s for data formatting or transmission.
Reversing the coding process to retrieve the original data. No secrets are involved.
Converting data into a secure format using an encryption algorithm, typically requiring a secret key or password. This ensures data confidentiality.
Reversing the encryption process to restore the original data. This also requires some keys.
Generating a fixed-size hash value from input data. It’s a one-way process, and no secrets are involved. Hashing is used for data integrity checks and securely storing passwords by comparing hashes.
Combines a cryptographic hash function with a secret key to ensure both data integrity and authenticity.
The secret key is used along with the hash function to create a MAC (Message Authentication Code).
The sender and receiver use the same secret key to validate that the message hasn’t been tampered with and is from a legitimate source.
hash(data + secret_salt) -> data + digest -> data can be trusted and processed
hash(secret_data + salt) -> salt + digest -> salt can be used to verify someone knows something
A kind of encryption that requires two different keys that are mathematically paired.
Both keys have the exact same functionalities like encryption and decryption, meaning that any of the pairs can encrypt and decrypt data.
Data that was encrypted by one of the pairs can only be decrypted the other pair.
It is not feasible to brute force or calculate one of the pair, if the other one is known.