Hashing & Digital Signatures
Understanding cryptographic hash functions, common algorithms, HMAC, digital signatures, and their real-world applications.
What is Hashing?
A one-way cryptographic function that transforms data into a fixed-size string
One-Way Function
You cannot reverse a hash to recover the original input. It's computationally infeasible to find the input given the hash output.
Fixed Output Size
Regardless of input size (a single character or a 10GB file), the hash output has a fixed length (e.g., 256 bits for SHA-256).
Avalanche Effect
A tiny change in input dramatically changes the output hash. Even changing one bit flips ~50% of the output bits, making hashes unpredictable.
Hash Visualization — SHA-256
00000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Notice how even a small difference in input completely changes the hash (avalanche effect).
Common Hashing Algorithms
| Algorithm | Output Bits | Collision Risk | Speed | Status |
|---|---|---|---|---|
| MD5 | 128 | High (collisions found) | Very Fast | Broken — not recommended |
| SHA-1 | 160 | Medium (theoretical attacks) | Fast | Deprecated — avoid |
| SHA-256 | 256 | Very Low | Moderate | Secure — widely used |
| SHA-512 | 512 | Negligible | Moderate | Secure — strongest in SHA-2 |
| bcrypt | 192 | Very Low | Slow (intentional) | Secure — ideal for passwords |
| Argon2 | Variable | Very Low | Configurable | Secure — password hashing winner |
HMAC (Hash-based Message Authentication Code)
A keyed hash function that provides both integrity and authenticity
How HMAC Works
- Combine the secret key with the message using a specific padding scheme
- Hash the result with the chosen hash function (e.g., SHA-256)
- Combine the key with the hash using a second padding scheme
- Hash again to produce the final HMAC output
The double-hashing approach prevents length-extension attacks on the underlying hash.
Use Cases
- API authentication (e.g., AWS Signature V4)
- TLS/SSL handshake message verification
- JWT token integrity
- Secure cookie signing
- VPN protocol authentication
Digital Signatures
Providing authenticity, integrity, and non-repudiation for digital data
Signing Process
- Hash the original message using a hash function
- Encrypt the hash with the sender's private key
- The encrypted hash is the digital signature
- Send the original message + signature to the recipient
Verification Process
- Decrypt the signature using the sender's public key
- Independently hash the received message
- Compare the decrypted hash with the computed hash
- If they match → authenticity and integrity confirmed
Certificates: A digital certificate binds a public key to an identity. Certificate Authorities (CAs) sign certificates to vouch for their authenticity. This creates the PKI (Public Key Infrastructure) trust chain.
Real-World Applications
Password Storage
Passwords are hashed (with salt) before storage. When a user logs in, the input is hashed and compared to the stored hash. If the database is breached, passwords remain protected.
Integrity Checking
Software downloads include checksums (SHA-256). After downloading, users verify the checksum matches to ensure the file wasn't tampered with during transfer.
Blockchain
Each block in a blockchain contains the hash of the previous block, creating an immutable chain. Altering any block would change all subsequent hashes, making tampering detectable.
Code Examples
import hashlib, hmac # SHA-256 hashing data = b"Hello, World!" hash_obj = hashlib.sha256(data) print(hash_obj.hexdigest()) # dffd6021... (64 chars) # HMAC key = b"secret-key" hmac_obj = hmac.new(key, data, hashlib.sha256) print(hmac_obj.hexdigest()) # bcrypt for passwords import bcrypt salt = bcrypt.gensalt() hashed = bcrypt.hashpw(b"password123", salt)
const crypto = require('crypto');
// SHA-256 hashing
const data = 'Hello, World!';
const hash = crypto
.createHash('sha256')
.update(data)
.digest('hex');
console.log(hash);
// dffd6021... (64 chars)
// HMAC
const key = 'secret-key';
const hmac = crypto
.createHmac('sha256', key)
.update(data)
.digest('hex');
console.log(hmac);
// SHA-512
const hash512 = crypto
.createHash('sha512')
.update(data)
.digest('hex');Interview Questions
Common hashing and digital signatures interview questions with answers