Practical Cryptography for Developers
master-zh
master-zh
  • Welcome
  • 前言
  • 密码学——概述
  • 哈希函数
    • 加密哈希和碰撞
    • 哈希函数:应用场景
    • 安全哈希算法
    • 哈希函数——示例
    • 练习:计算哈希值
    • 工作量证明(Proof-of-Work)哈希函数
  • MAC 和密钥派生
    • HMAC 与密钥派生
    • HMAC 计算——示例
    • 练习:计算 HMAC
    • KDF: Deriving Key from Password
    • PBKDF2
    • Modern Key Derivation Functions
    • Scrypt
    • Bcrypt
    • Linux crypt()
    • Argon2
    • Secure Password Storage
    • Exercises: Password Encryption
  • Secure Random Generators
    • Pseudo-Random Numbers - Examples
    • Secure Random Generators (CSPRNG)
    • Exercises: Pseudo-Random Generator
  • Key Exchange and DHKE
    • Diffie–Hellman Key Exchange
    • DHKE - Examples
    • Exercises: DHKE Key Exchange
  • Encryption: Symmetric and Asymmetric
  • Symmetric Key Ciphers
    • Cipher Block Modes
    • Popular Symmetric Algorithms
    • The AES Cipher - Concepts
    • AES Encrypt / Decrypt - Examples
    • Ethereum Wallet Encryption
    • Exercises: AES Encrypt / Decrypt
    • ChaCha20-Poly1305
    • Exercises: ChaCha20-Poly1305
  • Asymmetric Key Ciphers
    • The RSA Cryptosystem - Concepts
    • RSA Encrypt / Decrypt - Examples
    • Exercises: RSA Encrypt / Decrypt
    • Elliptic Curve Cryptography (ECC)
    • ECDH Key Exchange
    • ECDH Key Exchange - Examples
    • Exercises: ECDH Key Exchange
    • ECC Encryption / Decryption
    • ECIES Hybrid Encryption Scheme
    • ECIES Encryption - Example
    • Exercises: ECIES Encrypt / Decrypt
  • Digital Signatures
    • RSA Signatures
    • RSA: Sign / Verify - Examples
    • Exercises: RSA Sign and Verify
    • ECDSA: Elliptic Curve Signatures
    • ECDSA: Sign / Verify - Examples
    • Exercises: ECDSA Sign and Verify
    • EdDSA and Ed25519
    • EdDSA: Sign / Verify - Examples
    • Exercises: EdDSA Sign and Verify
  • Quantum-Safe Cryptography
    • Quantum-Safe Signatures - Example
    • Quantum-Safe Key Exchange - Example
    • Quantum-Safe Asymmetric Encryption - Example
  • More Cryptographic Concepts
    • Digital Certificates - Example
    • TLS - Example
    • One-Time Passwords (OTP) - Example
  • Crypto Libraries for Developers
    • JavaScript Crypto Libraries
    • Python Crypto Libraries
    • C# Crypto Libraries
    • Java Crypto Libraries
  • Conclusion
Powered by GitBook
On this page
  • Clear-Text Passwords - Never Do Anti-Pattern
  • Simple Password Hash - Highly Insecure
  • Salted Hashed Passwords - Secure, but Not Enough
  • Secure KDF-Based Password Hashing - Recommended
  • Password-Based Authentication

Was this helpful?

  1. MAC 和密钥派生

Secure Password Storage

PreviousArgon2NextExercises: Password Encryption

Last updated 5 years ago

Was this helpful?

In software development we constantly use password-based user authentication and we need to store user passwords securely in a way that users can sign-up, authenticate and change their password, but in the same time attackers cannot decrypt the stored passwords back to clear text values, even if they manage to get access to the database holding the user accounts.

If we develop a Web site or Web app, we typically have admin panel, accessible after login, based on username + password. It is similar for mobile apps, web services and other password-protected systems: all they need secure password storage (secure password management / strongly encrypted password storage).

Developers often store the user passwords for their sites, apps or other systems in a database, just like any other user data, but most systems apply some kind of hashing, encryption or password authentication scheme. There are many ways to implement the password storage for password-based authentication. The most popular of them are given in the table below:

Approach

Security

Comments

Clear-text passwords

Extremely low

Never do this: compromised server will render all passwords leaked

Simple password hash

Low

Vulnerable to dictionary attacks

Salted hashed passwords

Average

Vulnerable to GPU-based and ASIC-based password cracking

Secure KDF function (like Argon2)

High

Recommended, use strong KDF parameters

Let's review these password storage methods and discuss their level of security, their strong and weak sides.

Clear-Text Passwords - Never Do Anti-Pattern

The easiest and most highly insecure method for password storage and password-based authentication is to use written directly in the database.

  • In this scenario to check the password, developers just compare the password for checking with the password from the database.

  • Never do this!!! It is anti-pattern for software development. It is bad for many reasons.

    • Admins will be able to see user's passwords and this is really bad, because many users use the same password for several sites / apps, e.g. the same password for GMail, Facebook and Twitter.

    • Admins should never know user's passwords, but should be able to change them in case of emergency.

    • If someone hacks the server and gains access to the database, he will see all user's passwords in plaintext.

  • It is very bad practice to keep plaintext passwords in any information system / app in the world!

    • Just don't do it!

Simple Password Hash - Highly Insecure

A relatively easy and relatively insecure method for password storage and password-based authentication is to use simple password hash like SHA-256(password), written directly in the database.

  • In this scenario to check the password, developers just compare the hash(password for checking) with the password hash from the database.

  • Avoid this! It is highly insecure method.

    • Crackers who gain access to the database, can use a dictionary holding the hashes of the most commonly used 10-20 million passwords and most of the passwords will be decrypted.

    • The dictionary attack process is extremely fast, because it compares the hashes from the dictionary with the password hash (trivial string compare).

  • Cracked passwords, revealed as plaintext are a true disaster, because most users use the same password for several sites / apps.

Salted Hashed Passwords - Secure, but Not Enough

More complicated and relatively secure method for password storage and password-based authentication is to use salted hashed passwords, written in the database as pair { salt + hash(password + salt) }. The hash function can be any strong cryptographic hash like SHA-256.

  • The idea is to keep different random salt, along with different password hash, changed every time, when the password is written in the database. Thus the same password is encrypted every time as different ciphertext { salt + hash }.

  • To check the password, developers calculate the hash(password for checking) using the salt from the database and compare the calculated hash with the hash from the database.

  • This method works well to prevent dictionary attacks, but does not prevent GPU-based and ASIC-based brute force password cracking attacks.

  • Basically keeping salted hashed passwords is more secure than the previous methods, but still avoid it.

    • Use more attack-resistant password hashing function (which is unlikely to be brute-forced) instead of simple hash, e.g. Argon2 or Scrypt.

Secure KDF-Based Password Hashing - Recommended

The most complicated and most secure method for secure password storage and password-based authentication is to use secure KDF-based password hash, written in the database as pair { salt + KDF(password, salt) }. The key-derivation function (KDF) should be strong and secure, e.g. Scrypt or Argon2 with carefully selected parameters.

  • The idea is to keep different random salt for each encrypted password, along with the key derived by a secure KDF-function, such as Scrypt or Argon2 (with reasonable number of iterations and RAM consumption settings).

  • To check the password, take the salt from the database and derive a key from the password for checking, using the same KDF function and KDF parameters like when the password was stored in the database. Compare the derived key with the key from the database.

  • This method is resistant to most attacks and is considered as standard in the software industry.

    • It is as secure as the KDF function with the selected KDF parameters. For example, Argon2 taking 128 MB RAM, 4 threads and 200 ms computing time) may be appropriate for the average case.

    • Crackers cannot perform brute force attacks, because the password guessing will be too slow, even on a modern computer with good CPU and GPU or even using a specialized ASIC hardware.

Conclusion: use secure KDF functions like Argon2 and Scrypt to keep encrypted passwords in the database. Never use plain-text passwords!

Password-Based Authentication

Using a secure password storage is only one of the components of the process of secure password-based authentication for Web apps, mobile apps and Internet services. Systems, that use password-based-authentication are subject of many attacks:

  • Password guessing attack: attacker tries to guess / brute-force the user's password by attempting many logins in parallel.

    • Solved easily by adding increasing login delay (wait time before the login is available again) after each wrong login attempt or even temporary account locking. Delays / locking should be done by IP address + username, to avoid login problems for the legitimate users.

    • Secure KDF-based password storage delays the password guessing process, so it is highly recommended.

  • Denial of service attack: attacker may attempt to login too many times to overload the system or can try to lock some user account with too many invalid login attempts for the same user.

    • The protection from this attack is similar to the previous attack: use a CAPTCHA and delay the login process for certain IP address after each login attempt.

  • Intercept and replay attack: attacker may intercept the authentication communication (to sniff the login / password / auth ticket / other credentials) and use the intercepted credentials to login later.

  • Man-in-the-middle attack: attacker can intercept and modify the intercepted traffic between the server and the client to trick the user to reveal its login credentials.

    • In some scenarios (e.g. online banking) clients are also authenticated by a digital certificate or OTP (one-time password).

  • Compromised server attack: if the authentication server and its database is compromised (hacked) and all its authentication data is leaked, the attacker should be unable to reveal user's plaintext passwords.

    • First, it should be clear that if the authentication server is compromised, in all cases the attackers will get unauthorised access, because they will be able to intercept user's legitimate sessions (their login and communication after successful login) and use them to impersonate the user.

    • The backdoored server attack can be stopped like this: the client generates a random number r and sends as authentication HMAC(password, r); the server compares the HMAC with its stored password. This process may be combined with client-side Scrypt or Argon2 computation and securely stored password at the server side (Scrypt or Argon2 hashed). In this scenario, unless the client software is not compromised, attackers who gained access to the authentication server will not obtain user's passwords in plaintext.

    • In Web applications, if the server is compromised it can inject JavaScript code to compromise the client itself. In desktop and mobiles apps, the client is more safe in case of compromised server.

Conclusions about how to implement a secure password-based authentication for Web sites, apps and services:

  • Use secure password storage, such as Argon2 hash, with strong enough configuration settings.

  • Keep your authentication server as secure as possible. If it is compromised, the entire system will be compromised.

  • Use TLS or other secure communication channel between the authentication server and the client.

Why? Because hashes are vulnerable to .

Search in Internet for .

It has also the same security problems like using hash(key + msg) instead of HMAC(key, msg), e.g. .

Using a after a 2-3 unsuccessful login attempts provides quite good protection.

Most systems solve this problem by using (encrypted connection) to securely send the authentication credentials (password / authentication ticket) to the server.

Other solutions include based cryptographic authentication scheme, such as the scheme used in the protocol.

This is solved by using a secure connection with server certificate, which authenticates the server.

Using a strongly secure password storage mechanism mitigates the risk for users' passwords to be revealed as plaintext. Still, attackers who gain access to the authentication server may inject password interception and steal each user's plaintext credentials (username + password) during the login.

clear-text passwords
dictionary attacks
free dictionaries / wordlists for dictionary attack
length-extension attack
CAPTCHA
TLS
challenge-response
Kerberos
TLS
backdoor