TL;DR
Yes, ciphers can be deliberately designed to be slow. This isn’t usually about breaking security, but rather creating a system where the computational cost is part of the design – often for things like password hashing or key derivation. We’ll look at examples and why you might use them.
1. Why Slow Down Encryption?
Standard encryption aims for speed. But sometimes, you *want* it to be slow. Here’s why:
- Password Hashing: Making password hashing slow is a key cyber security measure. It makes brute-force attacks much harder because an attacker needs significant computing power and time to crack passwords.
- Key Derivation Functions (KDFs): Similar to password hashing, KDFs create keys from secrets (like passwords) slowly to resist online attacks.
- Watermarking: In some niche applications, a slow cipher can be used as part of a digital watermarking scheme.
2. Examples of Slow Ciphers & Functions
These aren’t traditional encryption algorithms like AES or RSA, but functions built to be computationally expensive.
a) bcrypt
bcrypt is a password hashing function specifically designed to be slow and adaptable. It uses a ‘work factor’ which controls the computational cost. Higher work factors mean more time to hash (and crack).
- How it works: bcrypt repeatedly hashes the password with a randomly generated salt, increasing the difficulty each time.
- Example (Python):
import bcrypt
password = b"mysecretpassword"
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password, salt)
print(hashed)
b) scrypt
scrypt is another password hashing function that’s even more memory-intensive than bcrypt, making it harder to accelerate with custom hardware (like ASICs). It also uses a work factor.
- How it works: scrypt requires large amounts of RAM during the hashing process.
- Example (Python – using a library like pycryptodome):
from passlib.hash import scrypt
hashed = scrypt.hash("mysecretpassword")
print(hashed)
c) Argon2
Argon2 is a modern KDF that’s considered the state-of-the-art for password hashing. It offers different variants (Argon2d, Argon2i, Argon2id) optimised for different attack scenarios.
- How it works: Argon2 uses multiple passes through the data and is highly configurable to adjust memory usage, iterations, and parallelism.
- Example (Python – using a library like passlib):
from passlib.hash import argon2
hashed = argon2.hash("mysecretpassword")
print(hashed)
d) PBKDF2
Password-Based Key Derivation Function 2 is a widely used KDF that uses a pseudorandom function (like HMAC-SHA256) to derive keys from passwords. It also relies on iterations.
- How it works: PBKDF2 repeatedly applies the PRF to the password and salt, increasing the computational cost with each iteration.
- Example (Python – using hashlib):
import hashlib
import os
password = b"mysecretpassword"
salt = os.urandom(16)
dk = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
print(dk)
3. Implementing Slow Ciphers – Important Considerations
- Work Factor/Iterations: Carefully choose the work factor or number of iterations. Too low, and it’s easily cracked; too high, and you impact user experience (login times).
- Salting: Always use a unique, randomly generated salt for each password. This prevents rainbow table attacks.
- Library Choice: Use well-vetted cryptography libraries like bcrypt, scrypt, Argon2 or passlib in Python. Avoid implementing these functions yourself unless you are an expert.
- Regular Updates: Keep your cryptography libraries up to date to benefit from security improvements and bug fixes.
4. When *Not* To Use Slow Ciphers
Don’t use slow ciphers for general encryption of data at rest or in transit. They are specifically designed for password hashing and key derivation, not bulk data protection.