Cryptography rarely fails because an algorithm is broken. It fails because it is used badly. The same mistakes have recurred for years in applications, websites, devices and company procedures, often made in good faith by people who believe they have protected their data. Knowing them is the simplest way not to repeat them.
1. Confusing encoding with encryption
Base64, hexadecimal encoding or compression are not encryption. They turn data into another representation, but anyone can reverse them without a key. A password "hidden" in Base64 in a configuration file is, for all practical purposes, a plain-text password.
What to do: if data must stay confidential, use a real encryption algorithm, with a key stored separately.
2. Inventing your own algorithm
It is surprisingly common to find "home-made" encryption: XOR with a fixed word, character substitutions, creative combinations of known algorithms. They seem to work because the result is unreadable to the naked eye, but they rarely withstand serious analysis.
What to do: use standard algorithms (AES, ChaCha20, Ed25519, X25519) through mature, high-level libraries that offer functions along the lines of "encrypt this message" without forcing you to choose every detail.
3. Using ECB mode
Encrypting each block of data independently, as ECB mode does, lets the structure of the original show through: identical blocks produce identical ciphertext blocks. The classic example is an image encrypted in ECB in which the outline of the picture remains recognisable.
What to do: use modern authenticated modes such as AES-GCM or ChaCha20-Poly1305.
4. Encrypting without authenticating
Encryption without an integrity check prevents data from being read, but it does not prevent it from being modified. In some modes an attacker can flip specific bits of the ciphertext and obtain predictable changes in the decrypted text, or exploit the system's error messages to extract information.
What to do: prefer authenticated encryption. If you must combine separate encryption and authentication codes, encrypt first, then compute the authentication over the ciphertext, and verify it before decrypting.
5. Reusing a nonce
Many algorithms require a unique value for each operation, called a nonce or initialisation vector. With AES-GCM, reusing the same nonce with the same key reveals information about the messages and allows new ones to be forged. With ECDSA signatures, a repeated nonce reveals the private key.
What to do: generate nonces with a secure random generator or with correctly managed counters, and let the library handle it whenever possible.
6. Using weak random numbers
The general-purpose random functions in programming languages are designed for simulations and games, not for security: their values can be predicted. A historic case is a Linux distribution in which, in 2008, it was discovered that a change to the code of a cryptographic library had drastically reduced randomness: for about two years, keys generated on those systems belonged to a small, predictable set.
What to do: always use the cryptographic generator of the operating system or library.
7. Leaving keys next to the data
Keys written in source code, pushed to repositories, saved in the same folder as encrypted backups or sent in the same email as the protected file. In all these cases encryption is a mere formality.
What to do: always keep keys and data apart; use secret managers, system keychains or hardware modules.
8. Disabling certificate verification
During development, people sometimes disable TLS certificate checks to get a connection working. If that setting makes it into production, the connection remains encrypted but is no longer authenticated: anyone who steps in between can pose as the server.
What to do: never disable verification; if you use internal certificates, add your own authority to the list of trusted ones.
9. Protecting passwords with fast hashes
Storing passwords with MD5, SHA-1 or even plain SHA-256 lets whoever steals the database try huge numbers of combinations in a short time.
What to do: use functions designed for passwords, such as Argon2, scrypt or bcrypt, with a unique salt for each user.
10. Relying on the secrecy of the system
"Nobody knows how it works, so it is secure" is reasoning that the history of cryptography has disproved many times. Sooner or later the inner workings are discovered, for example by analysing the software or the device.
What to do: design so that security depends only on the key.
A summary table
| Mistake | Alternative |
|---|---|
| Base64 as protection | Real encryption with a separate key |
| Home-made algorithm | Standard high-level library |
| ECB, unauthenticated encryption | AES-GCM, ChaCha20-Poly1305 |
| Repeated nonces | Unique nonces handled by the library |
| Weak randomness | The system's cryptographic generator |
| Keys in code | Secret manager, HSM |
| TLS verification disabled | Verification always on |
| Fast hashes for passwords | Argon2, scrypt, bcrypt |
In short
- Most cryptographic failures come from misuse, not from broken algorithms.
- Encoding and obfuscation are not encryption; home-made algorithms should be avoided.
- Authenticated modes, unique nonces and cryptographic randomness are basic requirements.
- Keeping keys apart from data and always verifying certificates are non-negotiable.
- Passwords require slow, salted hashing functions.