Crypto usage
Cryptography fails quietly: code that encrypts and decrypts correctly in a
test can still leak plaintext through a reused nonce, a padding oracle, or a
homegrown construction. The rule is to never design your own scheme and
never call a low-level primitive directly. Pick a vetted library, use its
authenticated high-level interface, and store keys somewhere other than the
code.
Method
- Call a high-level library, not raw primitives. Use libsodium
(PyNaCl), Google Tink, or the language's maintained
cryptography
package instead of bare OpenSSL AES calls. These pick safe modes, key
sizes, and padding so you cannot assemble an insecure combination by
accident.
- Default to AEAD for encryption. Use an authenticated cipher such as
AES-256-GCM, ChaCha20-Poly1305, or
crypto_secretbox so decryption
verifies integrity and rejects tampered ciphertext. Unauthenticated CBC
or ECB invites padding-oracle and bit-flipping attacks; do not use them.
- Never reuse a nonce with a key. Generate a fresh random nonce per
message for GCM, or use a library that manages nonces for you. A repeated
nonce under one key breaks GCM catastrophically, exposing plaintext and
the authentication key.
- Derive keys from passwords with a KDF. For passwords use Argon2id or
bcrypt (see password-storage); to turn a passphrase into a key use Argon2
or scrypt. Never key a cipher directly from a raw SHA-256 of a password.
- Keep keys out of source and in a KMS. Generate and store keys in AWS
KMS, GCP KMS, or an HSM, and encrypt data keys under a master key with
envelope encryption. The application handles ciphertext and a wrapped
key, never the raw master.
- Compare secrets in constant time. Check MACs and tokens with
hmac.compare_digest or the library equivalent, not ==. A byte-by-byte
== leaks match position through timing.
Signals
- Does every ciphertext carry an authentication tag, with zero ECB or
unauthenticated CBC in the codebase?
- Is there any hand-rolled cipher, custom padding, or "encryption" that is
really XOR or base64?
- Are keys generated and stored in a KMS or HSM, never hardcoded or
committed?
- Do secret comparisons use a constant-time function?
Boundaries
This is about using cryptography correctly, not designing protocols or
vetting a novel scheme, which needs a cryptographer. Password hashing has
its own skill (password-storage), as does transport encryption
(tls-configuration). Regulatory algorithm mandates such as FIPS override
these defaults where they apply.
1---2name: crypto-usage3description: Use cryptography by calling vetted libraries with authenticated defaults and storing keys in a KMS, never by designing a scheme. Use when adding encryption, choosing a cipher or mode, or reviewing code that handles keys or ciphertext.4---56# Crypto usage78Cryptography fails quietly: code that encrypts and decrypts correctly in a9test can still leak plaintext through a reused nonce, a padding oracle, or a10homegrown construction. The rule is to never design your own scheme and11never call a low-level primitive directly. Pick a vetted library, use its12authenticated high-level interface, and store keys somewhere other than the13code.1415## Method16171. **Call a high-level library, not raw primitives.** Use libsodium18 (PyNaCl), Google Tink, or the language's maintained `cryptography`19 package instead of bare OpenSSL AES calls. These pick safe modes, key20 sizes, and padding so you cannot assemble an insecure combination by21 accident.222. **Default to AEAD for encryption.** Use an authenticated cipher such as23 AES-256-GCM, ChaCha20-Poly1305, or `crypto_secretbox` so decryption24 verifies integrity and rejects tampered ciphertext. Unauthenticated CBC25 or ECB invites padding-oracle and bit-flipping attacks; do not use them.263. **Never reuse a nonce with a key.** Generate a fresh random nonce per27 message for GCM, or use a library that manages nonces for you. A repeated28 nonce under one key breaks GCM catastrophically, exposing plaintext and29 the authentication key.304. **Derive keys from passwords with a KDF.** For passwords use Argon2id or31 bcrypt (see password-storage); to turn a passphrase into a key use Argon232 or scrypt. Never key a cipher directly from a raw SHA-256 of a password.335. **Keep keys out of source and in a KMS.** Generate and store keys in AWS34 KMS, GCP KMS, or an HSM, and encrypt data keys under a master key with35 envelope encryption. The application handles ciphertext and a wrapped36 key, never the raw master.376. **Compare secrets in constant time.** Check MACs and tokens with38 `hmac.compare_digest` or the library equivalent, not `==`. A byte-by-byte39 `==` leaks match position through timing.4041## Signals4243- Does every ciphertext carry an authentication tag, with zero ECB or44 unauthenticated CBC in the codebase?45- Is there any hand-rolled cipher, custom padding, or "encryption" that is46 really XOR or base64?47- Are keys generated and stored in a KMS or HSM, never hardcoded or48 committed?49- Do secret comparisons use a constant-time function?5051## Boundaries5253This is about using cryptography correctly, not designing protocols or54vetting a novel scheme, which needs a cryptographer. Password hashing has55its own skill (password-storage), as does transport encryption56(tls-configuration). Regulatory algorithm mandates such as FIPS override57these defaults where they apply.