Summary
Essential cryptography and encryption concepts for security interviews, covering symmetric/asymmetric encryption, hashing algorithms, digital signatures, and PKI. This guide provides practical examples, security best practices, and key management strategies for implementing encryption in real-world applications. Critical knowledge for security engineers, cryptography specialists, and anyone working with data protection and secure communications.
Core Concepts
What is Encryption?
- Definition: Process of converting plaintext into ciphertext using an algorithm and key
- Purpose: Confidentiality, Integrity, Authentication, Non-repudiation
Encryption vs Encoding vs Hashing
| Type | Reversible | Key Required | Purpose | Example |
|---|---|---|---|---|
| Encoding | Yes | No | Data representation | Base64, URL encoding |
| Encryption | Yes | Yes | Confidentiality | AES, RSA |
| Hashing | No | No | Integrity/Verification | SHA-256, MD5 |
Types of Encryption
1. Symmetric Encryption
- Same key for encryption and decryption
- Fast but key distribution is challenging
- Use cases: Bulk data encryption, session keys
Common Algorithms:
- AES (Advanced Encryption Standard): 128/192/256-bit keys
- DES/3DES: Deprecated, 56-bit/168-bit keys
- ChaCha20: Stream cipher, mobile-friendly
# AES Example (Python)
from cryptography.fernet import Fernet
# Generate key
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt
plaintext = b"Secret message"
ciphertext = cipher.encrypt(plaintext)
# Decrypt
decrypted = cipher.decrypt(ciphertext)
2. Asymmetric Encryption
- Public key for encryption, private key for decryption
- Slower but solves key distribution problem
- Use cases: Key exchange, digital signatures, certificates
Common Algorithms:
- RSA: 2048/4096-bit keys, based on factoring large primes
- ECC (Elliptic Curve): Smaller keys, same security
- Diffie-Hellman: Key exchange protocol
# RSA Example (Python)
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Generate keys
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# Encrypt with public key
message = b"Secret message"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrypt with private key
plaintext = private_key.decrypt(ciphertext, padding.OAEP(...))
Hashing Algorithms
Properties of Good Hash Functions:
- Deterministic: Same input → same output
- Fixed size: Any input size → fixed output size
- Avalanche effect: Small change → completely different hash
- One-way: Cannot reverse to get original input
- Collision resistant: Hard to find two inputs with same hash
Common Hash Functions:
| Algorithm | Output Size | Status | Use Case |
|---|---|---|---|
| MD5 | 128 bits | Broken | Never use |
| SHA-1 | 160 bits | Deprecated | Legacy only |
| SHA-256 | 256 bits | Secure | General purpose |
| SHA-3 | Variable | Secure | Future-proof |
| bcrypt | Variable | Secure | Password hashing |
| Argon2 | Variable | Most Secure | Password hashing (recommended) |
# Hashing Example
import hashlib
import bcrypt
# SHA-256
data = "password123"
sha_hash = hashlib.sha256(data.encode()).hexdigest()
# bcrypt for passwords (includes salt)
password = b"password123"
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password, salt)
# Verify password
bcrypt.checkpw(password, hashed) # Returns True/False
Security Protocols & Standards
TLS/SSL
- TLS 1.3: Current standard (2018)
- Handshake: Certificate exchange, cipher negotiation
- Perfect Forward Secrecy: New keys for each session
Common Cipher Suites:
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
Digital Certificates:
- X.509: Standard format
- Certificate Chain: Root CA → Intermediate CA → End Entity
- Validation: Domain, Organization, Extended Validation
Modes of Operation (Block Ciphers)
| Mode | Full Name | IV Required | Parallel | Use Case |
|---|---|---|---|---|
| ECB | Electronic Codebook | No | Yes | Never use (patterns visible) |
| CBC | Cipher Block Chaining | Yes | Decrypt only | Legacy systems |
| CTR | Counter | Yes | Yes | Stream-like operation |
| GCM | Galois/Counter Mode | Yes | Yes | Recommended (authenticated) |
| CCM | Counter with CBC-MAC | Yes | No | IoT/embedded devices |
Key Management Best Practices
- Key Generation: Use cryptographically secure random number generators
- Key Storage: HSM, Key vaults, Environment variables (never hardcode)
- Key Rotation: Regular schedule, maintain old keys for decryption
- Key Derivation: PBKDF2, scrypt, Argon2 for password-based keys
# Key Derivation Example
import os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
password = b"password"
salt = os.urandom(16) # Store this with the encrypted data
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = kdf.derive(password)
Common Attack Vectors
1. Cryptographic Attacks
- Brute Force: Try all possible keys
- Dictionary Attack: Common passwords
- Rainbow Tables: Precomputed hashes
- Side-Channel: Timing, power consumption
- Man-in-the-Middle: Intercept communication
2. Implementation Vulnerabilities
- Padding Oracle: CBC mode vulnerability
- Weak Random Numbers: Predictable keys
- Key Reuse: Nonce/IV reuse in CTR/GCM
- Downgrade Attacks: Force weaker algorithms
Interview Quick Tips
Common Questions:
"Explain the difference between symmetric and asymmetric encryption"
- Symmetric: Fast, same key, bulk data
- Asymmetric: Slow, key pairs, key exchange
"How does HTTPS work?"
- Client hello → Server certificate → Key exchange → Symmetric encryption
"How would you store passwords?"
- Hash with bcrypt/Argon2 + unique salt per password
- Never store plaintext or reversible encryption
"What's the difference between hashing and encryption?"
- Hashing: One-way, fixed size, integrity
- Encryption: Two-way, confidentiality
Red Flags in Code Reviews:
# BAD - Common mistakes in interviews
password = "admin123" # Hardcoded credential
md5_hash = hashlib.md5(password) # Broken algorithm
encrypted = base64.b64encode(data) # Encoding != Encryption!
# GOOD - Best practices
password = os.environ.get('PASSWORD') # Environment variable
salt = bcrypt.gensalt() # Unique salt per password
hashed = bcrypt.hashpw(password.encode(), salt) # Proper hashing
Advanced Topics
Zero-Knowledge Proofs
- Prove knowledge without revealing the secret
- Applications: Authentication, blockchain
Homomorphic Encryption
- Compute on encrypted data without decrypting
- Use cases: Cloud computing, privacy-preserving ML
Post-Quantum Cryptography
- Algorithms resistant to quantum computers
- NIST candidates: CRYSTALS-Kyber, CRYSTALS-Dilithium
Secure Multi-party Computation
- Multiple parties compute jointly without revealing inputs
- Example: Private set intersection
Quick Reference Card
Encryption Choice Guide:
Need to encrypt data?
├── In transit? → TLS 1.3
├── At rest?
│ ├── Large files? → AES-256-GCM
│ └── Database? → Transparent encryption
├── Passwords? → Argon2/bcrypt (hash, not encrypt!)
└── Key exchange? → ECDH or RSA-OAEP
Security Checklist:
- Use established algorithms (no custom crypto)
- Generate keys with secure randomness
- Store keys separately from data
- Use authenticated encryption (GCM mode)
- Implement proper key rotation
- Hash passwords with salt
- Validate certificates properly
- Keep libraries updated
Remember for Interviews
- Never roll your own crypto - Use established libraries
- Defense in depth - Multiple layers of security
- Principle of least privilege - Minimize access
- Assume breach - Plan for key compromise
- Compliance matters - Know PCI-DSS, GDPR, HIPAA basics
Pro tip: Always explain the trade-offs (security vs performance vs usability) when discussing encryption choices in interviews!