Search

Why You Should Never Roll Your Own Crypto

The short answer

Quick answer: "Don't roll your own crypto" means: do not invent your own encryption algorithms, do not design your own security protocols, and do not write your own implementations of existing ones for real use. Cryptography fails silently. Broken code still encrypts and decrypts correctly, passes every test, and gives no sign that an attacker can read the data. The flaws are subtle and often invisible even to experienced programmers. Use well-reviewed, widely deployed libraries at the highest level of abstraction available, and leave the design to specialists whose work has survived years of public attack.

Schneier's Law

Security expert Bruce Schneier put the core problem this way, in what became known as Schneier's Law:

Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break.

Being unable to break your own design proves nothing, because you only tested it against the attacks you know. What matters is whether it survives attack by many skilled people, over a long time. Real algorithms earn trust this way: AES was chosen after a multi-year public competition in which the world's cryptanalysts tried to break the candidates.

Why this is different from ordinary code

  • Failure is invisible. A bug in a sorting function produces wrong output. A flaw in encryption produces output that looks perfectly random and decrypts correctly. Nothing fails.
  • The adversary is intelligent. Normal testing asks "does it work with expected input?" Security asks "does it hold against someone actively looking for the one input that breaks it?"
  • You only need to be wrong once. One weakness can expose everything.
  • Tests cannot prove security. You can test that something works. You cannot test that no attack exists.
  • The details are unintuitive. Small, reasonable-looking choices have catastrophic consequences.

Three levels of "rolling your own"

LevelExampleRisk
Inventing an algorithmA home-made cipherExtreme; almost certain to be broken
Implementing a known algorithm yourselfWriting your own AES or RSA codeHigh: side channels, edge cases
Combining standard pieces yourself"AES plus a hash" assembled by handHigh, and by far the most common

Most developers know not to do the first. The third is where real-world failures come from.

How things go wrong

Encryption without authentication

Encryption hides data. It does not, on its own, stop an attacker from modifying it. With unauthenticated encryption, an attacker who cannot read a message can still flip bits in it and observe how the system reacts. A whole family of attacks recovers plaintext this way, by using the server's error responses as a guide.

The fix is authenticated encryption (AEAD), which detects any change and refuses to decrypt. Modes such as AES-GCM and ChaCha20-Poly1305 do both together.

ECB mode

The simplest way to use a block cipher encrypts each block separately. Identical blocks of input give identical blocks of output, so patterns in the data remain visible. The well-known demonstration is an encrypted image of a penguin in which the penguin is still clearly recognisable.

Reusing a nonce

Many modes need a nonce: a number that must never repeat with the same key. Reuse it once and the consequences range from leaking the relationship between two messages to revealing the authentication key. A games console's code-signing key was famously recovered because the signing process reused a value that should have been random each time.

Weak randomness

Keys, nonces and tokens need unpredictable random numbers. General-purpose functions such as Math.random() or rand() are predictable by design. Always use the operating system's cryptographic random source, through functions like secrets in Python or crypto.getRandomValues in JavaScript.

Timing leaks

Comparing a secret value with ordinary == typically stops at the first byte that differs. The time taken reveals how many leading bytes were correct, and an attacker can recover the secret one byte at a time. Secret comparisons must run in constant time. More generally, any way a computation's time, power use or cache behaviour depends on a secret is a side channel.

Misusing hashes

  • Using a fast hash such as MD5 or SHA-256 for passwords. See how passwords should be stored.
  • Building a message authentication code as hash(secret + message), which is open to a length-extension attack with common hash functions. The correct construction is HMAC.

Textbook RSA

RSA as described in a maths textbook, without padding, is insecure in several ways. Safe use needs carefully designed padding schemes, and flawed padding handling has caused repeated real-world breaks.

Not checking who you are talking to

Disabling certificate verification "to make the error go away" turns encryption into theatre. The connection is encrypted, but possibly to an attacker. See how HTTPS works.

Keys in the wrong place

Hard-coded keys in source code, keys in a repository, one key for every customer, no plan to rotate. The algorithm can be perfect and the system still broken.

Accepting the attacker's choice of algorithm

Some JWT libraries once accepted a token that declared its own algorithm as "none". See JWT vs sessions.

"But nobody knows how my scheme works"

Keeping the design secret does not make it secure. Kerckhoffs's principle, from the nineteenth century, states that a system should remain secure even if everything about it is public except the key.

Secret designs get reverse-engineered, leaked or guessed. Open designs get examined by people who know how to find flaws. Every algorithm you should be using is fully public.

What to do instead

Use the highest-level tool that fits

You needUse
Data protected in transitTLS, with your platform's standard library and default settings
Passwords storedArgon2id or bcrypt through a maintained library
Data encrypted with a keyA library's authenticated encryption function
A message authenticatedHMAC, or the library's signing function
Random tokensThe operating system's secure random generator
Data encrypted at restYour database's or cloud provider's built-in encryption and key management
Keys storedA key management service or secrets manager

Prefer misuse-resistant libraries

Good modern libraries give you a small number of safe operations and make the decisions for you: which algorithm, which mode, how to generate the nonce.

  • libsodium offers simple functions such as "secret box" and "sealed box" with safe defaults, and has bindings for most languages.
  • Tink from Google takes a similar approach.
  • Your platform's own cryptography API for standard tasks.

Avoid APIs that make you choose a cipher, a mode, a padding scheme and an initialisation vector yourself. Every choice is an opportunity for error.

Keep it boring

  • Stick to defaults.
  • Keep dependencies updated; cryptographic libraries get security fixes.
  • Have security-sensitive code reviewed by someone with relevant expertise.
  • Plan for change: keys need rotating, and algorithms eventually need replacing. The move to post-quantum algorithms is under way now; see how public key cryptography works.

When it is fine to write crypto

  • To learn. Implementing AES or RSA yourself is an excellent way to understand them. Solving published cryptography challenges teaches you how attacks work. Just do not deploy the result.
  • If it is your profession, and the work will go through public review before anyone relies on it.

Even experts follow the rule in practice: they publish designs, invite attack, and wait years before recommending use.

Frequently asked questions

What does "roll your own crypto" mean?

Designing your own cryptographic algorithm or protocol, or writing your own implementation of one, instead of using established, reviewed libraries.

Is it acceptable to use AES directly?

AES is sound, but using it correctly requires choosing a mode, managing nonces and adding authentication. Use a library function that provides authenticated encryption as a single operation.

Is hiding my algorithm more secure?

No. Security should rest on the secrecy of the key alone. Hidden designs avoid scrutiny, which usually means their flaws go unfound until an attacker finds them.

Which library should I use?

A widely used, actively maintained one that offers high-level operations: libsodium, Tink, or the standard cryptography API of your platform.

Conclusion

Cryptography is the one area of programming where "it works" tells you nothing about whether it is right. The safe path is deliberately dull: public algorithms, vetted libraries, default settings, and as few decisions of your own as possible. Save the creativity for the rest of the system.

Related articles

Sources and further reading

Usama Muneer

Usama Muneer

Coder, Blogger, Tech Speaker & Web Technologies Enthusiast. Passionate about working on open-source Programming languages & Tools while utilizing my Product Development skills.

Your experience on this site will be improved by allowing cookies Cookie Policy