Algorithm selection β€” the short answer

Algorithm reference β€” 2026text
Use case                    Recommended              Avoid
────────────────────────────────────────────────────────────────────
Symmetric encryption        AES-256-GCM              DES, 3DES, RC4, AES-ECB
Asymmetric encryption       RSA-2048+ / ECC P-256    RSA-1024, DSA-1024
Key exchange                ECDHE, X25519            Static RSA key exchange
Digital signatures          Ed25519, ECDSA P-256     RSA-PKCS1v1.5
Password hashing            Argon2id, bcrypt         MD5, SHA1, SHA256 (raw)
General hashing             SHA-256, SHA-3           MD5, SHA1
TLS                         TLS 1.3 / TLS 1.2+       TLS 1.0, TLS 1.1, SSLv3
MAC / AEAD                  HMAC-SHA256, AES-GCM     HMAC-MD5, unauthenticated modes

Rule #1: Do not invent your own cryptography. Do not implement algorithms from scratch. Use well-audited, actively maintained libraries. The list of teams that have successfully invented new cryptographic primitives is very short and does not include your engineering team.

Symmetric encryption β€” AES

AES (Advanced Encryption Standard) is the industry standard for symmetric encryption. It is fast, hardware-accelerated on modern CPUs, and cryptographically sound. The choice of mode and key length determines actual security.

Key length

  • AES-256: The standard for sensitive data. The 256-bit key provides a 128-bit security level against quantum attacks (Grover's algorithm halves the effective key length).
  • AES-128: Acceptable for non-quantum-sensitive data today. 128-bit key provides 64-bit security against quantum adversaries β€” adequate for most current use cases but not future-proof.

Mode of operation

  • AES-GCM (Galois/Counter Mode): The recommended mode. Provides both encryption and authentication (AEAD β€” Authenticated Encryption with Associated Data). If ciphertext is tampered with, decryption fails and the tampering is detected.
  • AES-CBC: Acceptable if combined with a separate HMAC for authentication (Encrypt-then-MAC pattern). Never use CBC without authentication β€” vulnerable to padding oracle attacks.
  • AES-ECB: Never use. ECB mode encrypts identical plaintext blocks to identical ciphertext blocks, leaking data structure (the "ECB penguin" problem).
aes_gcm_example.pyPython
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

# Generate a random 256-bit key
key = os.urandom(32)  # 32 bytes = 256 bits

# Generate a random 96-bit nonce (12 bytes β€” standard for GCM)
nonce = os.urandom(12)

aesgcm = AESGCM(key)

# Encrypt with optional associated data (authenticated but not encrypted)
plaintext = b"sensitive data"
associated_data = b"header metadata"
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)

# Decrypt β€” raises InvalidTag if tampered
plaintext = aesgcm.decrypt(nonce, ciphertext, associated_data)

Never reuse a nonce with the same key in GCM. Nonce reuse in GCM completely compromises the encryption β€” both the key and all messages encrypted with that key can be recovered. Generate a new random nonce for every encryption operation.

Asymmetric encryption β€” RSA and ECC

Asymmetric cryptography uses a key pair: a public key for encryption/verification and a private key for decryption/signing. It is slower than symmetric encryption and unsuitable for encrypting large data volumes directly β€” it is typically used for key exchange or signatures.

RSA

  • Minimum key length: 2048 bits. RSA-1024 is broken β€” do not use it.
  • Recommended: RSA-4096 for long-lived keys protecting high-value data. RSA-2048 remains acceptable for most use cases in 2026.
  • Use OAEP padding for encryption. RSA-PKCS1v1.5 encryption padding is vulnerable to Bleichenbacher attacks. Use RSAES-OAEP.
  • Use PSS padding for signatures. RSA-PKCS1v1.5 signatures are generally safe but PSS (Probabilistic Signature Scheme) is preferred.

Elliptic Curve Cryptography (ECC)

ECC provides equivalent security to RSA at much smaller key sizes, making it faster and preferred for new systems.

  • P-256 (NIST curve): Widely supported, equivalent to RSA-3072 security. Standard choice for TLS and JWT (ES256).
  • Ed25519 (Edwards curve): Preferred for digital signatures. Faster than ECDSA, immune to weak random number generation affecting ECDSA signing, and simpler to implement correctly.
  • X25519: Preferred for key exchange (Diffie-Hellman). Used in modern TLS 1.3.

Password hashing β€” not just any hash

General-purpose hash functions (SHA-256, SHA-512) are designed to be fast β€” which makes them terrible for password storage. An attacker with GPU hardware can compute billions of SHA-256 hashes per second. Password hashing algorithms are specifically designed to be slow and memory-intensive.

  • Argon2id: The current recommendation. Winner of the Password Hashing Competition (2015). Resistant to both GPU and side-channel attacks. Configure: minimum 64 MB memory, 3 iterations, 4 parallelism for interactive logins.
  • bcrypt: The widely supported fallback. Use a work factor of 12 or higher (2026). Limit input to 72 bytes β€” longer passwords are silently truncated by most bcrypt implementations.
  • scrypt: Memory-hard algorithm. Good choice if Argon2 is unavailable. N=32768, r=8, p=1 as minimum parameters.
  • MD5, SHA1, SHA256 for passwords: Never. These are wrong for this use case regardless of salting.
password_hash.pyPython
from argon2 import PasswordHasher

ph = PasswordHasher(
    time_cost=3,        # iterations
    memory_cost=65536,  # 64 MB
    parallelism=4,
)

# Hash a password
hash = ph.hash("user_password")

# Verify β€” raises exceptions on wrong password or outdated params
try:
    ph.verify(hash, "user_password")
    if ph.check_needs_rehash(hash):
        hash = ph.hash("user_password")  # rehash with updated params
except Exception:
    # Verification failed
    pass

TLS configuration

  • Minimum: TLS 1.2. Preferred: TLS 1.3. TLS 1.0 and 1.1 are deprecated by all major browser vendors and IETF (RFC 8996). SSLv3 and earlier are critically broken.
  • Enable forward secrecy. Use ECDHE or DHE cipher suites so that a future compromise of the server's private key does not decrypt past sessions.
  • TLS 1.3 cipher suites are fixed and strong. TLS 1.3 removed the cipher negotiation complexity β€” there are only five cipher suites, all AEAD and all providing forward secrecy.
  • Disable weak cipher suites. RC4, DES, 3DES, EXPORT, NULL, and anonymous cipher suites must be explicitly disabled.
  • Set HSTS with a long max-age. HTTP Strict Transport Security prevents protocol downgrade attacks. Minimum max-age: 31536000 (one year). Include includeSubDomains and preload when ready.

Encryption key management

  • Generate keys with a cryptographically secure random number generator. Never derive keys from predictable values (timestamps, process IDs, sequential numbers).
  • Store encryption keys separately from encrypted data. A key stored alongside the data it protects provides no security.
  • Use a KMS for key storage. AWS KMS, GCP Cloud KMS, Azure Key Vault, and HashiCorp Vault are designed for secure key storage with audit logging and access control.
  • Rotate keys on a schedule. Use envelope encryption: encrypt data with a data encryption key (DEK), encrypt the DEK with a key encryption key (KEK). Rotating the KEK re-wraps all DEKs without re-encrypting all data.
  • Never log or expose keys. Treat encryption keys like passwords β€” they should never appear in logs, error messages, or API responses.

Common cryptographic mistakes

  • Using ECB mode: Leaks data structure. Always use GCM or CBC+HMAC.
  • Hardcoding encryption keys: A key in source code is not a key β€” it is a constant. Anyone with repo access has the "key".
  • Reusing IVs/nonces: Catastrophic for GCM. Use a random nonce for every encryption operation.
  • Rolling your own crypto: Implementing AES from scratch, designing custom protocols, or modifying standard algorithms. Use established libraries.
  • Encrypting without authenticating: Unauthenticated ciphertext can be modified without detection. Use AEAD modes or add a MAC.
  • Using MD5 or SHA1 for anything security-relevant: MD5 is broken for collision resistance. SHA1 is deprecated. Use SHA-256 minimum.
  • Comparing secrets with ==: Timing attacks allow an attacker to determine how many bytes matched. Use constant-time comparison for any secret comparison.

Cryptographic failures are OWASP A02:2021. They moved up from third to second in the 2021 OWASP Top 10. The most common failure mode is not weak encryption β€” it is skipping encryption entirely, or using the right algorithm incorrectly.

Recommended cryptographic libraries

Library recommendations by languagetext
Language    Library                   Notes
──────────────────────────────────────────────────────────────────
Python      cryptography (pyca)       Full-featured, actively audited
Python      argon2-cffi               Argon2 password hashing
Node.js     built-in crypto module    For standard ops; libsodium for modern crypto
Node.js     libsodium-wrappers        Recommended for new projects
Go          stdlib crypto/*           Well-audited, use golang.org/x/crypto for extras
Java        Bouncy Castle / JCA       Prefer JCA + provider; avoid raw Bouncy Castle
Rust        RustCrypto / ring         ring preferred for audited primitives
.NET        System.Security.Cryptography  Built-in, well-maintained

The libsodium rule: If you are starting a new project and do not have specific interoperability requirements, libsodium (or its language bindings) makes strong defaults the only option. It picks the algorithms for you β€” all of which are modern and secure.

Detect weak cryptography in your codebase

AquilaX SAST identifies use of MD5, SHA1, DES, ECB mode, hardcoded keys, and other cryptographic weaknesses β€” across every file in your repository.

Scan for cryptographic flaws β†’