Table of Contents
Introduction to Cryptography Symmetric Encryption (AES, ChaCha20) Asymmetric Encryption (RSA, ECC) Cryptographic Hashing Digital Signatures Public Key Infrastructure (PKI) Cryptographic Protocols (TLS, SSH) Post-Quantum CryptographyIntroduction to Cryptography
Cryptography is the practice and study of techniques for secure communication in the presence of adversaries. It forms the foundation of modern security—protecting data confidentiality, integrity, authentication, and non-repudiation.
Core Cryptographic Goals
- Confidentiality: Only authorized parties can read the data
- Integrity: Data has not been modified in transit
- Authentication: Verify the identity of the communicating parties
- Non-repudiation: Sender cannot deny sending the message
Symmetric Encryption
Symmetric encryption uses the same key for both encryption and decryption. It's fast and efficient but requires secure key distribution.
AES (Advanced Encryption Standard)
AES is the gold standard for symmetric encryption, approved by NIST and used worldwide.
| Key Size | Rounds | Security Level |
|---|---|---|
| 128-bit | 10 | Standard security |
| 192-bit | 12 | High security |
| 256-bit | 14 | Top Secret (NSA approved) |
# Python - AES-256-GCM encryption
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
# Generate random key and nonce
key = AESGCM.generate_key(bit_length=256)
nonce = os.urandom(12) # 96-bit nonce for GCM
# Encrypt
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), associated_data=None)
# Decrypt
plaintext = aesgcm.decrypt(nonce, ciphertext, associated_data=None)
Common Mistakes
- Using ECB mode (reveals patterns in encrypted data)
- Reusing IVs/nonces with the same key
- Not using authenticated encryption (use GCM or ChaCha20-Poly1305)
Asymmetric Encryption
Asymmetric encryption uses a key pair: a public key for encryption and a private key for decryption. Slower than symmetric but solves the key distribution problem.
RSA (Rivest-Shamir-Adleman)
# Python - RSA key generation and encryption
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Generate 4096-bit key pair
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096
)
public_key = private_key.public_key()
# Encrypt with public key
ciphertext = public_key.encrypt(
plaintext.encode(),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrypt with private key
plaintext = private_key.decrypt(ciphertext, padding.OAEP(...))
Elliptic Curve Cryptography (ECC)
ECC provides equivalent security to RSA with much smaller key sizes, making it ideal for mobile and IoT devices.
| RSA Key Size | ECC Key Size | Security Bits |
|---|---|---|
| 2048 | 224 | 112 |
| 3072 | 256 | 128 |
| 7680 | 384 | 192 |
| 15360 | 521 | 256 |
Cryptographic Hashing
Hash functions create a fixed-size "fingerprint" of data. Any change to the input produces a completely different hash.
Hash Function Properties
- Deterministic: Same input always produces same output
- Fast computation: Quick to compute for any input size
- Preimage resistance: Cannot reverse hash to find input
- Collision resistance: Impossible to find two inputs with same hash
- Avalanche effect: Small change in input = huge change in hash
# Python - Secure hashing
import hashlib
# SHA-256 (recommended)
hash_sha256 = hashlib.sha256(data.encode()).hexdigest()
# SHA-3 (latest standard)
hash_sha3 = hashlib.sha3_256(data.encode()).hexdigest()
# BLAKE2 (faster, secure)
hash_blake2 = hashlib.blake2b(data.encode()).hexdigest()
# DO NOT USE: MD5, SHA-1 (broken!)
Digital Signatures
Digital signatures provide authentication, integrity, and non-repudiation. The sender signs with their private key; anyone can verify with the public key.
# Python - Digital signature with RSA
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# Sign message with private key
signature = private_key.sign(
message.encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# Verify with public key
try:
public_key.verify(signature, message.encode(), padding.PSS(...), hashes.SHA256())
print("Signature valid!")
except InvalidSignature:
print("Signature INVALID - tampering detected!")
Public Key Infrastructure (PKI)
PKI is the framework for managing digital certificates and public-key encryption. It enables trusted communication over untrusted networks.
Certificate Chain
- Root CA: Self-signed, trusted by OS/browser vendors
- Intermediate CA: Signed by Root, signs end-entity certs
- End-Entity Certificate: Your website's certificate
Cryptographic Protocols
TLS 1.3
TLS 1.3 is the latest version, removing legacy algorithms and reducing handshake latency.
# Strong TLS 1.3 cipher suites
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
Post-Quantum Cryptography
Quantum computers threaten current cryptography. NIST is standardizing post-quantum algorithms:
- CRYSTALS-Kyber: Key encapsulation
- CRYSTALS-Dilithium: Digital signatures
- SPHINCS+: Hash-based signatures
Last updated: December 2024