Key generation must use cryptographically secure functions
Keys should be randomly generated using a cryptographically secure function. Keys must not be based on common words or phrases, or on 'random' characters generated by mashing the keyboard. Where multiple keys are used (such as separate data-encrypting and key-encrypting keys), they should be fully independent from each other.
Regulatory requirements for encryption algorithms
In some cases there may be regulatory requirements that limit the algorithms that can be used, such as FIPS 140-2 or PCI DSS. When considering alternative algorithms to AES or Curve25519, factors to consider include: key size, known attacks and weaknesses, algorithm maturity, approval by third parties such as NIST's algorithmic validation program, performance for both encryption and decryption, quality of available libraries, and portability/widespread support.
Never use custom encryption algorithms
Do not implement custom cryptographic algorithms. Always use established, well-tested algorithms like AES or Curve25519.
Recommended asymmetric encryption algorithms and key sizes
For asymmetric encryption, elliptical curve cryptography (ECC) with Curve25519 is the preferred algorithm. If ECC is not available and RSA must be used, the key must be at least 2048 bits.
AES symmetric encryption key size requirements
For symmetric encryption, AES should be used with a key that is at least 128 bits, ideally 256 bits, paired with a secure cipher mode.
Authenticated cipher modes preferred over unauthenticated
Authenticated cipher modes should always be used where available. GCM and CCM are the most commonly used authenticated modes and should be used as first preference. If GCM or CCM are not available, CTR mode or CBC mode should be used with separate authentication such as Encrypt-then-MAC technique. ECB mode should not be used outside of very specific circumstances.
RSA Random Padding (OAEP) required
For RSA encryption, Random Padding (also known as OAEP or Optimal Asymmetric Encryption Padding) is essential. PKCS#1 padding schema is typically used for this purpose. Random Padding protects against Known Plaintext Attacks by adding randomness at the beginning of the payload.
Cryptographically secure random number generators by language
Cryptographically Secure Pseudo-Random Number Generators (CSPRNG) must be used for all security-critical functionality. The recommended functions by language are: C: getrandom(2); Java: java.security.SecureRandom, java.util.UUID.randomUUID(); PHP: random_bytes(), Random\Engine\Secure (PHP 8), random_int() (PHP 7), openssl_random_pseudo_bytes() (PHP 5); .NET/C#: RandomNumberGenerator; Objective-C: SecRandomCopyBytes; Python: secrets(); Ruby: SecureRandom; Go: crypto.rand package; Rust: rand::prng::chacha::ChaChaRng and CSPRNGs from rand library; Node.js: crypto.randomBytes(), crypto.randomInt(), crypto.randomUUID().
Unsafe random functions to avoid
The following functions must NOT be used for security-critical functionality: C: random(), rand(); Java: Math.random(), StrictMath.random(), java.util.Random, java.util.SplittableRandom, java.util.concurrent.ThreadLocalRandom; PHP: array_rand(), lcg_value(), mt_rand(), rand(), uniqid(); .NET/C#: Random(); Objective-C: arc4random()/arc4random_uniform() (Uses RC4 Cipher), subclasses of GKRandomSource, rand(), random(); Python: random(); Ruby: rand(), Random; Go: rand using math/rand package; Rust: rand::prng::XorShiftRng; Node.js: Math.random().
UUID versions and randomness reliability
Version 1 UUIDs are comprised of a high precision timestamp and the MAC address of the system that generated them, so are not random. Type 4 UUIDs are randomly generated, but whether this is done using a CSPRNG depends on the implementation. Unless known to be secure in the specific language or framework, the randomness of UUIDs should not be relied upon for security purposes.
Encryption key rotation criteria
Encryption keys should be rotated based on: (1) if the previous key is known or suspected to be compromised, or if someone with access to the key left the organization; (2) after a specified period of time has elapsed (cryptoperiod), considering factors like key size, data sensitivity, and threat model per NIST SP 800-57; (3) after the key has encrypted a specific amount of data (typically 2^35 bytes (~34GB) for 64-bit keys and 2^68 bytes (~295 exabytes) for 128-bit block size); (4) if there is significant change to algorithm security, such as a new attack being announced.
Key rotation implementation before compromise
The code and processes required to rotate a key must be in place before they are required, so that keys can be quickly rotated in the event of a compromise. Processes should also be implemented to allow the encryption algorithm or library to be changed in case a new vulnerability is found.
Two approaches for handling data encrypted with rotated keys
When a key must be rotated, there are two main approaches for handling existing data encrypted with the old key: (1) Decrypting it and re-encrypting it with the new key, which should generally be preferred as it simplifies application code and key management; (2) Marking each item with the ID of the key used to encrypt it and storing multiple keys to allow old data to be decrypted. Old keys should generally be stored for a certain period after retirement in case old backups need decryption.
Key derivation function for generating KEK from passphrase
A key derivation function (KDF) can be used to generate a KEK from user-supplied input such as a passphrase, which then encrypts a randomly generated DEK. This allows the KEK to be easily changed when the user changes their passphrase without needing to re-encrypt the data, as the DEK remains the same.
Encryption at multiple application stack levels
Encryption can be performed at multiple levels in the application stack: at the application level, at the database level (e.g., SQL Server TDE), at the filesystem level (e.g., BitLocker or LUKS), or at the hardware level (e.g., encrypted RAID cards or SSDs). The appropriate layer(s) depend on the threat model. For example, hardware-level encryption protects against physical theft but provides no protection if an attacker remotely compromises the server.
Minimize storage of sensitive information
The best way to protect sensitive information is to not store it in the first place. This is most often applicable to credit card details, which are highly desirable to attackers and subject to stringent PCI DSS storage requirements. Storage of sensitive information should be avoided wherever possible.
Defense in depth for encrypted data
Applications should be designed to remain secure even if cryptographic controls fail. Information stored in encrypted form should be protected by additional layers of security. Applications should not rely on the security of encrypted URL parameters and should enforce strong access control to prevent unauthorized access to information.
Mobile data encryption at rest and in transit
Encrypt sensitive data both at rest and in transit in mobile applications.
Mobile platform API encryption requirement
Use platform APIs for encryption in mobile applications. Do not attempt to implement your own encryption algorithms.
Mobile hardware-based security features leverage
Leverage hardware-based security features when available: Secure Enclave on iOS and Strongbox on Android for key storage and cryptographic operations.
Android secure cryptographic key storage with StrongBox
Store cryptographic keys in Android Keystore with hardware backing using StrongBox when available. Generate keys by setting `.setIsStrongBoxBacked(true)` in `KeyGenParameterSpec.Builder` (available on Android 9+). Verify hardware-backed storage with `KeyInfo.isInsideSecureHardware()`. Fall back to regular hardware-backed keystore if StrongBox is unavailable. Configure key usage restrictions with `.setUserAuthenticationRequired(true)` for sensitive operations.
iOS Secure Enclave for cryptographic key storage
Use Apple's Secure Enclave for secure cryptographic key storage and sensitive operations. Create keys using `SecKeyCreateRandomKey` with `kSecAttrTokenID` set to `kSecAttrTokenIDSecureEnclave`. Keys created in the Secure Enclave never leave the secure hardware; only operations using those keys are performed there. For biometric operations, use `LAContext` with `evaluatePolicy` to perform authentication directly through the Secure Enclave without exposing biometric data to the application. Consider access control options like `kSecAccessControlBiometryAny` or `kSecAccessControlUserPresence` to require user authentication before key usage.
Mobile additional data encryption over SSL
Encrypt data even if sent over SSL in mobile applications, in case of future SSL vulnerabilities.
Secure coding basics: Cryptography
Use cryptographic functions and protocols to protect data in transit and at rest, such as HTTPS and encryption. Expected levels for a given Product Security Level can be found by reviewing Golden Path/Paved Road documentation.
C8 Protect Data Everywhere controls
C8 Protect Data Everywhere includes: Cryptographic Storage Cheat Sheet, DotNet Security Cheat Sheet (Encryption and A6 Sensitive data exposure), Transport Layer Security Cheat Sheet, Key Management Cheat Sheet, HTTP Strict Transport Security Cheat Sheet, Pinning Cheat Sheet, REST Security Cheat Sheet (HTTPS), Ruby on Rails Cheat Sheet (Encryption), and User Privacy Protection Cheat Sheet.
OWASP Cryptographic Storage and Password Storage Cheat Sheets available
The following OWASP Cheat Sheets are available:
1. Cryptographic Storage Cheat Sheet - covers cryptographic controls for data storage
2. Password Storage Cheat Sheet - covers password hashing and storage controls