Skip to content

Encryption vs Cryptographic Hash

Encryption vs Cryptographic Hash#

What is the difference between encryption and a cryptographic hash?

Encryption#

Encryption turns plaintext into ciphertext using a key. It is designed to be reversed by someone who has the correct key.

Hashing#

Hashing is a process that cannot be undone. It always changes the same input into the same output. It is one way and usually creates output of a specific size, for example 256 bits. A hash is not decrypted, but weak or common inputs can still be guessed and checked against the hash.

Cryptographic hash functions do not automatically add random data. A plain hash, such as SHA-256, is deterministic: the same input produces the same hash every time.

A salt is random data included in the hashing process in some use cases, especially password storage. The salt makes identical passwords produce different stored hashes and makes precomputed lookup tables less useful.

For password storage, use a slow password-hashing algorithm such as Argon2id, bcrypt, scrypt, or PBKDF2. These algorithms combine the password, a salt, and a work factor.

Example Using Bcrypt#

Install bcrypt:

pip install flask-bcrypt

Import:

from flask_bcrypt import generate_password_hash

Generate the hash:

>>> generate_password_hash('secret')

Output:

b'$2b$12$w/x0Q9FnFydn/vZX26iz7eSNhJUavlm93SI.Kuv4uMATe031dKcpG'
  • b means byte-string
  • $2b tells you it is bcrypt
  • $12 is the cost factor
  • The rest contains the salt and the password hash

If you set the rounds really high, it takes longer:

>>> generate_password_hash('secret', 15)

Choose the cost factor based on how long your server can afford to spend checking a password. Do not increase the bcrypt cost factor after each failed login attempt. Use rate limiting, lockouts, or throttling to slow repeated failed login attempts.

Checking password#

How do you check it though?

>>> hashed_pw = generate_password_hash('secret', 12)
>>> hashed_pw
b'$2b$12$tE/SrlIDeO3Efs5lI77ZxeY3hzoAd1on2Lbx0SZnxBEARuSwBvEri'
>>> hashed_pw == generate_password_hash('secret', 12)
False

The above does not work. You have to check it with check_password_hash.

from flask_bcrypt import check_password_hash

then test it:

>>> check_password_hash(hashed_pw, 'secret')

Sources#