Back to blog
cryptographytechniquesensitive data

Cryptography in practice: mistakes that make your encryption useless

Published on 2026-04-127 min readFlorian

Cryptography is easy to use, hard to use well

Modern cryptographic libraries are accessible to any developer. But choosing the right algorithm, the right mode, generating keys properly, and storing them securely requires expertise most teams lack. The result: encryption that provides a false sense of security.

Mistake 1: obsolete algorithms

MD5 and SHA1 for password hashing

MD5 and SHA1 are fast hash functions designed for data integrity, not passwords. A modern GPU computes billions of MD5 hashes per second. The rainbow table for MD5 is publicly available.

Fix: use bcrypt, scrypt, or Argon2id for passwords. These functions are intentionally slow and include a unique salt per password.

DES and 3DES for encryption

DES uses a 56-bit key, breakable in hours. 3DES is technically safer but vulnerable to the Sweet32 attack on 64-bit blocks.

Fix: AES-256-GCM is the current standard. No reason to use anything else in 2026.

Mistake 2: ECB mode

Electronic Codebook (ECB) mode encrypts each block independently. Identical plaintext blocks produce identical ciphertext blocks. The data's structure is preserved in the ciphertext. The Linux penguin image encrypted in ECB is the classic illustration of this problem.

Fix: use GCM (Galois/Counter Mode) which provides both encryption and authentication. Or CBC with a separate HMAC if GCM isn't available.

Mistake 3: reused IV/nonce

A reused initialization vector (IV) or nonce with the same key completely compromises confidentiality. In GCM mode, nonce reuse allows recovery of the authentication key and message forgery.

Fix: generate a random IV for each encryption operation. For AES-GCM, the 96-bit nonce must be unique for every message encrypted with the same key.

Mistake 4: hardcoded keys

Encryption keys in source code, in committed configuration files, or in shared environment variables. The key is the same in development, staging, and production.

Fix: use a cloud KMS (Key Management Service) or HSM. Keys should never appear in plaintext in code or configuration files. Implement key rotation.

Mistake 5: encryption without authentication

Encrypting with AES-CBC without HMAC allows an attacker to modify the ciphertext without detection. Padding oracle attacks exploit this weakness to decrypt the message without knowing the key.

Fix: use an authenticated mode (AES-GCM, ChaCha20-Poly1305) or apply Encrypt-then-MAC with a separate HMAC.

Mistake 6: non-cryptographic random number generation

Using Math.random() in JavaScript or rand() in PHP to generate tokens, keys, or salts. These functions are not cryptographically secure and their outputs are predictable.

Fix: use crypto.getRandomValues() in JavaScript, random_bytes() in PHP, secrets in Python, SecureRandom in Java.

Mistake 7: certificate validation disabled

verify=False in Python requests, rejectUnauthorized: false in Node.js, curl -k in production. Disabling TLS verification to fix a certificate problem makes the entire communication vulnerable to man-in-the-middle attacks.

What we check

At CleanIssue, we analyze your applications' cryptographic choices: algorithms used, key management, encryption modes, randomness quality. Request your audit call to identify the cryptographic weaknesses in your application.

Related articles

Three adjacent analyses to keep exploring the same attack surface.

Sources

Written by Florian
Reviewed on 2026-04-12

Editorial analysis based on official vendor, project, and regulator documentation.

Related services

If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.

Need an external review of your HR SaaS?

Share your product, stack, and client context. We will come back with the right review scope.

Discuss your audit