Rolling Your Own Crypto
Rolling your own crypto means building custom encryption or hashing instead of using vetted libraries, producing schemes that look correct but fail silently to known attacks. Use standard authenticated encryption, proven password KDFs, and TLS instead.
Rolling your own crypto means writing bespoke encryption, hashing, signing, or key-exchange code rather than using established, peer-reviewed primitives and libraries. Cryptography is uniquely unforgiving: a scheme that looks correct and passes functional tests can still be trivially breakable, and the failure is silent.
Why It Happens
Developers underestimate the difficulty. Encryption looks like "scramble the bytes and unscramble them," so a clever XOR or a custom permutation seems sufficient. Sometimes there is a misguided belief that a secret, custom algorithm is safer than a public standard. Licensing fears, performance myths, or simply not knowing which standard library call to use also push teams toward homegrown code.
Why It Hurts
Secure cryptography requires getting an enormous number of details right: constant-time comparisons to resist timing attacks, correct initialization vectors and nonces (never reused), authenticated encryption to detect tampering, secure randomness, and sound key management. Each is a known pitfall that has broken real systems. Custom code almost never accounts for side channels, padding oracles, or chosen-ciphertext attacks. Worse, the breakage is invisible: the data still encrypts and decrypts, so tests pass while an attacker recovers plaintext or forges messages. There is no peer review, so flaws survive to production.
Warning Signs
- Code uses XOR, a custom S-box, or a hand-rolled "cipher" for confidentiality.
- Passwords are hashed with a fast or homemade function instead of a slow, salted KDF.
- IVs or nonces are constant, sequential, or derived from predictable values.
- Encryption is used without an authentication tag (no MAC, no AEAD).
- The team cannot name the standard their scheme corresponds to.
Better Alternatives
Use standard, well-maintained libraries: libsodium, the platform's native crypto (Web Crypto, Java JCA, .NET, Go crypto), or language wrappers around audited implementations. Prefer authenticated encryption (AES-GCM, ChaCha20-Poly1305) so tampering is detected automatically. Hash passwords with Argon2, scrypt, or bcrypt — never a raw SHA. Use TLS for data in transit rather than custom transport encryption. Let the library handle IV/nonce generation and key derivation through documented, high-level APIs.
How to Refactor Out of It
- Identify all custom cryptographic code, including "encoding" that is really meant to protect data.
- Map each use to a standard primitive: confidentiality → AEAD; integrity → HMAC or signatures; password storage → Argon2/bcrypt; transport → TLS.
- Replace homegrown code with high-level library calls; avoid even low-level standard primitives unless necessary.
- Treat any data protected by the old scheme as compromised and re-encrypt it; rotate keys.
- Have the new design reviewed by someone with cryptography experience, and document the chosen algorithms and key-management process.