Developers working with this cryptographic library must assume responsibility for strict API contracts, key lifecycle management, and secure parameter selection across all sensitive boundaries. The library provides robust cryptographic primitives and AEAD wrappers by default, but it does not protect against nonce reuse, weak random sources, insecure asymmetric parameters, or timing side-channel leaks. All verification failures, parsing exceptions, and authentication errors must fail closed to prevent invalid states from bypassing security controls.
Essential implementation rules
Adhere to strict API contract and buffer size requirements
Provide positive byte lengths when calling int.to_bytes() and allocate exact payload and tag dimensions for in-place operations like encrypt_into or decrypt_into. Supply matching key types, distinct key halves for cipher suites, and ensure elliptic curve public numbers and ML-KEM payload lengths are validated prior to execution.
Authenticate passwords and verify credentials securely
Use verify_phc_encoded() or verify() to authenticate passwords against Argon2id digests, and explicitly catch cryptography.exceptions.InvalidKey to handle invalid credentials or malformed hash strings securely.
Generate cryptographic keys with secure random generators
Use cryptographically secure functions such as os.urandom or primitive-specific methods like AESGCM.generate_key() to create high-entropy keys, nonces, and salts. Avoid predictable, sequential, or hardcoded values.
Hash passwords and derive keys using memory-hard KDFs
Derive cryptographic keys and store passwords using memory-hard functions such as Argon2id, PBKDF2HMAC, or Scrypt paired with a unique random salt of at least 16 bytes and sufficiently high iteration counts. Explicitly encode passwords and salts to byte sequences using UTF-8.
Use authenticated encryption with unique nonces
Always prefer authenticated encryption recipes such as Fernet or AEAD primitives like AESGCM and ChaCha20Poly1305. Ensure every nonce or initialization vector is unique for a given secret key and generated using a cryptographically secure random source.
Select strong asymmetric key sizes and robust padding mechanisms
Generate RSA keys of at least 2048 bits with public exponent 65537. Use padding.PSS combined with secure hash algorithms like SHA256 for digital signatures and padding.OAEP for asymmetric encryption.
Perform constant-time verification for signatures and MACs
Use built-in verification methods such as verify() on HMAC or KDF instances to compare derived secrets and authentication codes. Avoid manual comparisons using standard equality operators to prevent timing side-channel attacks.
Prevent bypassing RSA private key validation during deserialization
Always keep RSA private key validation enabled by leaving unsafe_skip_rsa_key_validation=False when loading PEM private keys to ensure OpenSSL thoroughly checks key structures and mathematical relationships.
Validate cryptographic input parameters, ranges, and structures
Enforce strict parameter bounds, power-of-2 constraints for Scrypt/Argon2, length limits of 255 bytes for ML-DSA context strings, 32-byte key lengths for Ed25519, and matching digest byte lengths for OCSP identifiers.
Catch parsing exceptions when decoding untrusted keys and payloads
Wrap deserialization functions for keys, certificates, CRLs, OCSP requests, and signatures in try...except blocks capturing ValueError, TypeError, or UnsupportedAlgorithm to safely reject malformed structures.
Pass immutable bytes-like objects to prevent concurrent mutation
Pass immutable bytes objects rather than mutable buffers like bytearray to cryptographic APIs to prevent memory corruption and data races from concurrent thread modifications.
Enforce input size limits on AEAD and Fernet payloads
Restrict individual AEAD encryption and decryption payload sizes below two gigabytes to prevent OverflowError exceptions. Use Fernet exclusively for small payloads like tokens or cookies rather than large files to avoid memory exhaustion.
Encrypt private keys and symmetric secrets during storage
When serializing private keys using private_bytes(), always supply a secure encryption algorithm such as serialization.BestAvailableEncryption with a strong, non-empty passphrase. Avoid exporting unencrypted keys into persistent storage.
Handle verification and authentication errors explicitly to fail closed
Explicitly wrap token verification, AEAD decryption, and X.509 certificate chain validation calls in try...except blocks capturing exceptions such as InvalidToken, InvalidTag, or VerificationError. Treat these as failures to fail closed.
Specify an explicit ttl parameter during Fernet token decryption
Pass an explicit ttl parameter in seconds to Fernet.decrypt() whenever tokens represent time-sensitive session data to prevent intercepted tokens from remaining valid indefinitely.
cryptography: All Security Cards
Approximately 4,747 tokens
On this card
Category: api contract misuse
Adhere to Strict API Contract and Buffer Size Requirements
Use when
When calling cryptographic primitives, encryption/decryption methods, key serialization, or integer-to-bytes conversions that require exact parameter types, correct argument counts, matching buffer sizes, and proper lifecycle calls.
Secure rules
Rule 1: Provide positive byte lengths and validate output buffer dimensions when serializing integers or calling AEAD in-place methods
Ensure that the length argument passed to int.to_bytes() is a positive integer greater than zero. When using in-place operations like encrypt_into or decrypt_into, allocate buffers matching the exact required payload and tag dimensions to prevent runtime errors.
Rule 2: Supply matching key types and distinct key halves for cipher and KEM suites.
When configuring cipher modes like AES-XTS or HPKE suites, supply distinct key halves and matching key types as required by the API contract. Ensure tag lengths and input block sizes conform strictly to algorithm requirements.
Rule 3: Instantiate a fresh KDF object for each derivation or verification call.
Key Derivation Function classes enforce a single-use lifecycle state contract. Always instantiate a new KDF instance for every individual derivation or verification operation to avoid AlreadyFinalized exceptions.
Rule 4: Validate elliptic curve public numbers and ML-KEM payload lengths before cryptographic operations.
Ensure that raw public numbers or untrusted ciphertext buffers are properly validated for correct length and valid curve points before passing them into cryptographic routines.
from cryptography.hazmat.primitives.asymmetric import mlkemdef safe_decapsulate_768(private_key: mlkem.MLKEM768PrivateKey, ciphertext: bytes) -> bytes: if len(ciphertext) != 1088: raise ValueError("Invalid ciphertext length for ML-KEM-768") try: return private_key.decapsulate(ciphertext) except ValueError: raise ValueError("Decapsulation failed due to malformed ciphertext")
Category: authentication
Authenticate passwords and verify credentials securely
Use when
Verifying user passwords or credentials using password hashing and verification verifiers.
Secure rules
Rule 1: Authenticate passwords using Argon2id verification methods and handle invalid credentials securely.
Use verify_phc_encoded() or verify() to authenticate passwords against encoded Argon2 digests, and catch cryptography.exceptions.InvalidKey to detect incorrect credentials or malformed hash strings.
Generate Cryptographic Keys with Secure Random Generators
Use when
Generating secure cryptographic keys, salts, and nonces for encryption, MACs, or key derivation.
Secure rules
Rule 1: Generate cryptographic keys with the library’s cryptographically secure random generator.
Use cryptographically secure functions like os.urandom or key generation methods provided by primitives to generate high-entropy keys, nonces, and salts. Avoid predictable or sequential values.
Deriving cryptographic keys from passwords or hashing passwords for secure storage.
Secure rules
Rule 1: Derive cryptographic keys and store passwords using memory-hard KDFs with secure random salts.
When deriving keys or hashing passwords, use modern key derivation functions such as Argon2id, PBKDF2HMAC, or Scrypt paired with a unique cryptographically random salt of at least 16 bytes. Ensure iteration counts and memory parameters are sufficiently high to resist brute-force attacks.
Encrypting sensitive data and payloads using symmetric ciphers or AEAD primitives.
Secure rules
Rule 1: Use authenticated encryption with a unique nonce for every encryption operation.
Always prefer authenticated encryption recipes such as Fernet or AEAD primitives like AESGCM and ChaCha20Poly1305 to provide confidentiality and integrity. Ensure that every nonce or initialization vector is unique for a given secret key and generated using a cryptographically secure random source such as os.urandom.
Generating asymmetric key pairs and performing public-key encryption or digital signatures.
Secure rules
Rule 1: Select secure key sizes and robust padding mechanisms for asymmetric operations.
When generating RSA keys, select a key size of at least 2048 bits and set the public exponent to 65537. Use padding.PSS for signatures and padding.OAEP for encryption, combined with secure hash algorithms like SHA256.
Verify Signatures and MACs Using Constant-Time Methods
Use when
Verifying digital signatures, message authentication codes (MACs), or derived key values.
Secure rules
Rule 1: Perform constant-time verification using library verification methods rather than standard equality operators
Always use built-in verification methods such as verify() on HMAC instances to check authentication codes, or .verify() on KDF instances to compare derived secrets (KDFs raise InvalidKey, not InvalidSignature, on mismatch). Avoid manual comparisons with standard equality operators to prevent timing side-channel attacks.
from cryptography.exceptions import InvalidSignaturefrom cryptography.hazmat.primitives import hashes, hmach = hmac.HMAC(key, hashes.SHA256())h.update(b"message to authenticate")try: h.verify(signature_to_check)except InvalidSignature: pass
Category: escape hatch
Prevent bypassing RSA private key validation during deserialization
Use when
Deserializing RSA private keys from user-supplied or untrusted input sources using serialization functions.
Secure rules
Rule 1: Always keep RSA private key validation enabled by leaving unsafe_skip_rsa_key_validation set to False
When loading PEM private keys, avoid setting unsafe_skip_rsa_key_validation=True. Leaving validation enabled ensures that OpenSSL thoroughly checks key structures and mathematical relationships, preventing malformed keys from triggering crashes, hangs, or memory safety issues.
from cryptography.hazmat.primitives.serialization import load_pem_private_keykey = load_pem_private_key( pem_data, password=b"secret", unsafe_skip_rsa_key_validation=False)
Category: input contract definition
Validate cryptographic input parameters, ranges, and structures before processing
Use when
When constructing cryptographic primitives, key derivation functions, certificates, and tokens that require strict input validation, parameter bounds checking, type validation, and allowed value constraints.
Secure rules
Rule 1: Validate BasicConstraints path length and ca flag settings
Set path_length to None whenever ca is set to False when constructing an x509.BasicConstraints extension. Setting a path length on a non-CA certificate violates certificate profile rules and raises a ValueError.
from cryptography import x509end_entity_bc = x509.BasicConstraints(ca=False, path_length=None)ca_bc = x509.BasicConstraints(ca=True, path_length=1)
Rule 2: Ensure valid combinations of PKCS7 options and encoding formats
Pass valid combinations of PKCS7Options and Encoding when signing or encrypting PKCS7 data to prevent conflicting option errors and runtime ValueError exceptions.
Rule 3: Validate KDF cost parameters and handle backend restrictions
Enforce strict parameter bounds and power-of-2 requirements for key derivation functions like Scrypt and Argon2 before derivation, and handle potential UnsupportedAlgorithm exceptions in restricted environments.
from cryptography.exceptions import UnsupportedAlgorithmfrom cryptography.hazmat.primitives.kdf.scrypt import Scryptimport ostry: salt = os.urandom(16) kdf = Scrypt(salt=salt, length=32, n=16384, r=8, p=1) key = kdf.derive(b"user_secret")except UnsupportedAlgorithm: raise RuntimeError("Scrypt is not supported under the active cryptographic backend")
Rule 4: Enforce length limits on domain separation context strings
Ensure that context strings supplied to ML-DSA signing or verification functions (e.g., MLDSA44PrivateKey.sign()) do not exceed the maximum allowed length of 255 bytes to prevent ValueError exceptions.
Rule 5: Enforce strict key lengths and serialization formats for Ed25519
Validate raw Ed25519 key inputs to ensure they are exactly 32 bytes and match the expected serialization format options to prevent ValueError exceptions during key loading.
from cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.primitives.asymmetric import ed25519def load_raw_private_key(key_bytes: bytes) -> ed25519.Ed25519PrivateKey: if len(key_bytes) != 32: raise ValueError("Ed25519 private key must be exactly 32 bytes") return ed25519.Ed25519PrivateKey.from_private_bytes(key_bytes)
Rule 6: Match hash digest lengths when constructing OCSP identifiers by hash
Ensure that issuer name and key hashes match the exact digest byte length of the supplied algorithm and that an accepted algorithm is used when constructing OCSP requests or responses by hash.
Rule 7: Select key wrap functions based on key alignment constraints
Ensure wrapping keys are 16, 24, or 32 bytes and use aes_key_wrap_with_padding for keys of arbitrary or unaligned lengths to satisfy block alignment rules and avoid ValueError exceptions.
Rule 8: Explicitly encode passwords and salts to byte sequences
Ensure passwords and salts passed to KDF functions are explicitly encoded to bytes using a fixed encoding scheme such as UTF-8 to prevent TypeError exceptions.
Validate and handle parsing exceptions when decoding cryptographic keys and payloads
Use when
When loading untrusted asymmetric keys, signatures, certificates, CRLs, OCSP requests, or encoded points from external sources.
Secure rules
Rule 1: Catch parsing exceptions when decoding untrusted keys, certificates, CRLs, OCSP requests, or signatures.
Always wrap deserialization functions like load_pem_private_key, load_der_x509_crl, load_ssh_public_key, ocsp.load_der_ocsp_request, and decode_dss_signature in try-except blocks catching ValueError, TypeError, or UnsupportedAlgorithm to safely reject malformed structures, mismatched algorithms, or invalid parameters.
from cryptography.exceptions import UnsupportedAlgorithmfrom cryptography.hazmat.primitives.serialization import load_pem_private_keytry: key = load_pem_private_key(untrusted_pem_bytes, password=password_bytes)except ValueError: raise ValueError("Key material is invalid or corrupted")except UnsupportedAlgorithm: raise ValueError("Key algorithm or cipher is not supported")
Rule 2: Perform explicit type and bounds verification on loaded cryptographic objects and components.
Verify that deserialized keys match the expected class instance using isinstance() and validate elliptic curve point prefixes and numeric bounds when constructing keys from raw components to prevent bypasses or unexpected runtime errors.
from cryptography.hazmat.primitives.asymmetric import rsafrom cryptography.hazmat.primitives.serialization import load_pem_private_keykey = load_pem_private_key(pem_data, password=None)if not isinstance(key, rsa.RSAPrivateKey): raise TypeError("Expected an RSA private key")
Category: memory safety
Prevent Concurrent Buffer Mutation During Cryptographic Operations
Use when
Passing data buffers to cryptography methods where memory safety and data integrity must be maintained against concurrent modifications.
Secure rules
Rule 1: Pass immutable bytes-like objects to cryptographic APIs to prevent memory corruption and data races from concurrent buffer mutation.
Do not pass mutable bytes-like objects such as bytearray or custom buffer objects to cryptography methods if those buffers may be mutated concurrently by other execution threads or tasks. Instead, pass immutable bytes objects or strictly isolate mutable buffer instances so they cannot be altered during execution.
Enforce input size limits on AEAD and Fernet payloads to prevent memory exhaustion
Use when
Encrypting or decrypting large data streams, files, or buffers using AEAD or Fernet primitives.
Secure rules
Rule 1: Validate and restrict individual encryption and decryption payload sizes below two gigabytes when using the AEAD backend.
Ensure input buffer sizes or break large streams into smaller framed chunks prior to calling AEAD encrypt or decrypt methods to prevent unhandled OverflowError exceptions and denial of service.
Rule 2: Avoid processing extremely large files or streams using Fernet to prevent out-of-memory errors.
Use Fernet for small payloads like tokens or cookies rather than large files, because Fernet enforces integrity verification before exposing plaintext and requires holding the complete message payload in memory at once.
Encrypt Private Keys and Symmetric Secrets During Storage and Serialization
Use when
Serializing private keys, certificates, or handling sensitive secrets in storage or configuration.
Secure rules
Rule 1: Protect serialized private keys using password encryption.
When serializing private keys using private_bytes(), always supply a secure key serialization encryption algorithm such as serialization.BestAvailableEncryption with a strong, non-empty passphrase. Avoid exporting unencrypted keys or seeds into persistent storage or configuration.
from cryptography.hazmat.primitives import serializationpem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption(b'strong_password'))
Rule 2: Generate cryptographically secure keys and passwords for secret storage.
Ensure secret keys and symmetric credentials are generated using cryptographically secure random sources or dedicated generation methods like generate_key() rather than hardcoded values.
from cryptography.fernet import Fernetkey = Fernet.generate_key()f = Fernet(key)token = f.encrypt(b"my deep dark secret")plaintext = f.decrypt(token)
Category: security control integrity
Handle Verification and Authentication Errors Explicitly to Fail Closed
Use when
Implementing error handling for cryptographic verification functions such as token verification or AEAD decryption where failures must fail closed.
Secure rules
Rule 1: Catch authentication and verification exceptions explicitly and fail closed when verification fails.
When validating tokens or decrypting payloads using primitives that raise verification errors, explicitly wrap the calls in try...except blocks capturing exceptions such as InvalidToken or InvalidTag. Treat these caught exceptions as authentication or verification failures to prevent invalid states from bypassing security checks.
Rule 2: Handle verification errors during X.509 certificate chain validation to ensure proper control flow.
Always wrap certificate validation operations in explicit error handling catching VerificationError to securely reject untrusted or malformed chains without crashing or bypassing verification paths.
Enforce Session Token Expiration with Fernet Decryption
Use when
When validating time-sensitive session state or transient session tokens using Fernet symmetric encryption.
Secure rules
Rule 1: Specify an explicit ttl parameter during token decryption to enforce session expiration.
Pass an explicit ttl parameter in seconds to Fernet.decrypt() whenever tokens represent time-sensitive session data. Omitting ttl or setting it to None causes tokens to remain valid indefinitely as long as the key is recognized, allowing intercepted tokens to be replayed.
from cryptography.fernet import Fernet, InvalidTokenf = Fernet(key)try: data = f.decrypt(token, ttl=300)except InvalidToken: pass
Adhere to Strict API Contract and Buffer Size Requirements
Approximately 719 tokens
Use when
When calling cryptographic primitives, encryption/decryption methods, key serialization, or integer-to-bytes conversions that require exact parameter types, correct argument counts, matching buffer sizes, and proper lifecycle calls.
Secure rules
Rule 1: Provide positive byte lengths and validate output buffer dimensions when serializing integers or calling AEAD in-place methods
Ensure that the length argument passed to int.to_bytes() is a positive integer greater than zero. When using in-place operations like encrypt_into or decrypt_into, allocate buffers matching the exact required payload and tag dimensions to prevent runtime errors.
Rule 2: Supply matching key types and distinct key halves for cipher and KEM suites.
When configuring cipher modes like AES-XTS or HPKE suites, supply distinct key halves and matching key types as required by the API contract. Ensure tag lengths and input block sizes conform strictly to algorithm requirements.
Rule 3: Instantiate a fresh KDF object for each derivation or verification call.
Key Derivation Function classes enforce a single-use lifecycle state contract. Always instantiate a new KDF instance for every individual derivation or verification operation to avoid AlreadyFinalized exceptions.
Rule 4: Validate elliptic curve public numbers and ML-KEM payload lengths before cryptographic operations.
Ensure that raw public numbers or untrusted ciphertext buffers are properly validated for correct length and valid curve points before passing them into cryptographic routines.
from cryptography.hazmat.primitives.asymmetric import mlkemdef safe_decapsulate_768(private_key: mlkem.MLKEM768PrivateKey, ciphertext: bytes) -> bytes: if len(ciphertext) != 1088: raise ValueError("Invalid ciphertext length for ML-KEM-768") try: return private_key.decapsulate(ciphertext) except ValueError: raise ValueError("Decapsulation failed due to malformed ciphertext")
Authenticate passwords and verify credentials securely
Approximately 202 tokens
Use when
Verifying user passwords or credentials using password hashing and verification verifiers.
Secure rules
Rule 1: Authenticate passwords using Argon2id verification methods and handle invalid credentials securely.
Use verify_phc_encoded() or verify() to authenticate passwords against encoded Argon2 digests, and catch cryptography.exceptions.InvalidKey to detect incorrect credentials or malformed hash strings.
Generate Cryptographic Keys with Secure Random Generators
Approximately 978 tokens
On this card
Use when
Generating secure cryptographic keys, salts, and nonces for encryption, MACs, or key derivation.
Secure rules
Rule 1: Generate cryptographic keys with the library’s cryptographically secure random generator.
Use cryptographically secure functions like os.urandom or key generation methods provided by primitives to generate high-entropy keys, nonces, and salts. Avoid predictable or sequential values.
Deriving cryptographic keys from passwords or hashing passwords for secure storage.
Secure rules
Rule 1: Derive cryptographic keys and store passwords using memory-hard KDFs with secure random salts.
When deriving keys or hashing passwords, use modern key derivation functions such as Argon2id, PBKDF2HMAC, or Scrypt paired with a unique cryptographically random salt of at least 16 bytes. Ensure iteration counts and memory parameters are sufficiently high to resist brute-force attacks.
Encrypting sensitive data and payloads using symmetric ciphers or AEAD primitives.
Secure rules
Rule 1: Use authenticated encryption with a unique nonce for every encryption operation.
Always prefer authenticated encryption recipes such as Fernet or AEAD primitives like AESGCM and ChaCha20Poly1305 to provide confidentiality and integrity. Ensure that every nonce or initialization vector is unique for a given secret key and generated using a cryptographically secure random source such as os.urandom.
Generating asymmetric key pairs and performing public-key encryption or digital signatures.
Secure rules
Rule 1: Select secure key sizes and robust padding mechanisms for asymmetric operations.
When generating RSA keys, select a key size of at least 2048 bits and set the public exponent to 65537. Use padding.PSS for signatures and padding.OAEP for encryption, combined with secure hash algorithms like SHA256.
Verify Signatures and MACs Using Constant-Time Methods
Use when
Verifying digital signatures, message authentication codes (MACs), or derived key values.
Secure rules
Rule 1: Perform constant-time verification using library verification methods rather than standard equality operators
Always use built-in verification methods such as verify() on HMAC instances to check authentication codes, or .verify() on KDF instances to compare derived secrets (KDFs raise InvalidKey, not InvalidSignature, on mismatch). Avoid manual comparisons with standard equality operators to prevent timing side-channel attacks.
from cryptography.exceptions import InvalidSignaturefrom cryptography.hazmat.primitives import hashes, hmach = hmac.HMAC(key, hashes.SHA256())h.update(b"message to authenticate")try: h.verify(signature_to_check)except InvalidSignature: pass
Prevent bypassing RSA private key validation during deserialization
Approximately 192 tokens
Use when
Deserializing RSA private keys from user-supplied or untrusted input sources using serialization functions.
Secure rules
Rule 1: Always keep RSA private key validation enabled by leaving unsafe_skip_rsa_key_validation set to False
When loading PEM private keys, avoid setting unsafe_skip_rsa_key_validation=True. Leaving validation enabled ensures that OpenSSL thoroughly checks key structures and mathematical relationships, preventing malformed keys from triggering crashes, hangs, or memory safety issues.
from cryptography.hazmat.primitives.serialization import load_pem_private_keykey = load_pem_private_key( pem_data, password=b"secret", unsafe_skip_rsa_key_validation=False)
Validate cryptographic input parameters, ranges, and structures before processing
Approximately 1,198 tokens
Use when
When constructing cryptographic primitives, key derivation functions, certificates, and tokens that require strict input validation, parameter bounds checking, type validation, and allowed value constraints.
Secure rules
Rule 1: Validate BasicConstraints path length and ca flag settings
Set path_length to None whenever ca is set to False when constructing an x509.BasicConstraints extension. Setting a path length on a non-CA certificate violates certificate profile rules and raises a ValueError.
from cryptography import x509end_entity_bc = x509.BasicConstraints(ca=False, path_length=None)ca_bc = x509.BasicConstraints(ca=True, path_length=1)
Rule 2: Ensure valid combinations of PKCS7 options and encoding formats
Pass valid combinations of PKCS7Options and Encoding when signing or encrypting PKCS7 data to prevent conflicting option errors and runtime ValueError exceptions.
Rule 3: Validate KDF cost parameters and handle backend restrictions
Enforce strict parameter bounds and power-of-2 requirements for key derivation functions like Scrypt and Argon2 before derivation, and handle potential UnsupportedAlgorithm exceptions in restricted environments.
from cryptography.exceptions import UnsupportedAlgorithmfrom cryptography.hazmat.primitives.kdf.scrypt import Scryptimport ostry: salt = os.urandom(16) kdf = Scrypt(salt=salt, length=32, n=16384, r=8, p=1) key = kdf.derive(b"user_secret")except UnsupportedAlgorithm: raise RuntimeError("Scrypt is not supported under the active cryptographic backend")
Rule 4: Enforce length limits on domain separation context strings
Ensure that context strings supplied to ML-DSA signing or verification functions (e.g., MLDSA44PrivateKey.sign()) do not exceed the maximum allowed length of 255 bytes to prevent ValueError exceptions.
Rule 5: Enforce strict key lengths and serialization formats for Ed25519
Validate raw Ed25519 key inputs to ensure they are exactly 32 bytes and match the expected serialization format options to prevent ValueError exceptions during key loading.
from cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.primitives.asymmetric import ed25519def load_raw_private_key(key_bytes: bytes) -> ed25519.Ed25519PrivateKey: if len(key_bytes) != 32: raise ValueError("Ed25519 private key must be exactly 32 bytes") return ed25519.Ed25519PrivateKey.from_private_bytes(key_bytes)
Rule 6: Match hash digest lengths when constructing OCSP identifiers by hash
Ensure that issuer name and key hashes match the exact digest byte length of the supplied algorithm and that an accepted algorithm is used when constructing OCSP requests or responses by hash.
Rule 7: Select key wrap functions based on key alignment constraints
Ensure wrapping keys are 16, 24, or 32 bytes and use aes_key_wrap_with_padding for keys of arbitrary or unaligned lengths to satisfy block alignment rules and avoid ValueError exceptions.
Rule 8: Explicitly encode passwords and salts to byte sequences
Ensure passwords and salts passed to KDF functions are explicitly encoded to bytes using a fixed encoding scheme such as UTF-8 to prevent TypeError exceptions.
Validate and handle parsing exceptions when decoding cryptographic keys and payloads
Approximately 400 tokens
Use when
When loading untrusted asymmetric keys, signatures, certificates, CRLs, OCSP requests, or encoded points from external sources.
Secure rules
Rule 1: Catch parsing exceptions when decoding untrusted keys, certificates, CRLs, OCSP requests, or signatures.
Always wrap deserialization functions like load_pem_private_key, load_der_x509_crl, load_ssh_public_key, ocsp.load_der_ocsp_request, and decode_dss_signature in try-except blocks catching ValueError, TypeError, or UnsupportedAlgorithm to safely reject malformed structures, mismatched algorithms, or invalid parameters.
from cryptography.exceptions import UnsupportedAlgorithmfrom cryptography.hazmat.primitives.serialization import load_pem_private_keytry: key = load_pem_private_key(untrusted_pem_bytes, password=password_bytes)except ValueError: raise ValueError("Key material is invalid or corrupted")except UnsupportedAlgorithm: raise ValueError("Key algorithm or cipher is not supported")
Rule 2: Perform explicit type and bounds verification on loaded cryptographic objects and components.
Verify that deserialized keys match the expected class instance using isinstance() and validate elliptic curve point prefixes and numeric bounds when constructing keys from raw components to prevent bypasses or unexpected runtime errors.
from cryptography.hazmat.primitives.asymmetric import rsafrom cryptography.hazmat.primitives.serialization import load_pem_private_keykey = load_pem_private_key(pem_data, password=None)if not isinstance(key, rsa.RSAPrivateKey): raise TypeError("Expected an RSA private key")
Prevent Concurrent Buffer Mutation During Cryptographic Operations
Approximately 183 tokens
Use when
Passing data buffers to cryptography methods where memory safety and data integrity must be maintained against concurrent modifications.
Secure rules
Rule 1: Pass immutable bytes-like objects to cryptographic APIs to prevent memory corruption and data races from concurrent buffer mutation.
Do not pass mutable bytes-like objects such as bytearray or custom buffer objects to cryptography methods if those buffers may be mutated concurrently by other execution threads or tasks. Instead, pass immutable bytes objects or strictly isolate mutable buffer instances so they cannot be altered during execution.
Enforce input size limits on AEAD and Fernet payloads to prevent memory exhaustion
Approximately 255 tokens
Use when
Encrypting or decrypting large data streams, files, or buffers using AEAD or Fernet primitives.
Secure rules
Rule 1: Validate and restrict individual encryption and decryption payload sizes below two gigabytes when using the AEAD backend.
Ensure input buffer sizes or break large streams into smaller framed chunks prior to calling AEAD encrypt or decrypt methods to prevent unhandled OverflowError exceptions and denial of service.
Rule 2: Avoid processing extremely large files or streams using Fernet to prevent out-of-memory errors.
Use Fernet for small payloads like tokens or cookies rather than large files, because Fernet enforces integrity verification before exposing plaintext and requires holding the complete message payload in memory at once.
Encrypt Private Keys and Symmetric Secrets During Storage and Serialization
Approximately 283 tokens
Use when
Serializing private keys, certificates, or handling sensitive secrets in storage or configuration.
Secure rules
Rule 1: Protect serialized private keys using password encryption.
When serializing private keys using private_bytes(), always supply a secure key serialization encryption algorithm such as serialization.BestAvailableEncryption with a strong, non-empty passphrase. Avoid exporting unencrypted keys or seeds into persistent storage or configuration.
from cryptography.hazmat.primitives import serializationpem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption(b'strong_password'))
Rule 2: Generate cryptographically secure keys and passwords for secret storage.
Ensure secret keys and symmetric credentials are generated using cryptographically secure random sources or dedicated generation methods like generate_key() rather than hardcoded values.
from cryptography.fernet import Fernetkey = Fernet.generate_key()f = Fernet(key)token = f.encrypt(b"my deep dark secret")plaintext = f.decrypt(token)
Handle Verification and Authentication Errors Explicitly to Fail Closed
Approximately 422 tokens
Use when
Implementing error handling for cryptographic verification functions such as token verification or AEAD decryption where failures must fail closed.
Secure rules
Rule 1: Catch authentication and verification exceptions explicitly and fail closed when verification fails.
When validating tokens or decrypting payloads using primitives that raise verification errors, explicitly wrap the calls in try...except blocks capturing exceptions such as InvalidToken or InvalidTag. Treat these caught exceptions as authentication or verification failures to prevent invalid states from bypassing security checks.
Rule 2: Handle verification errors during X.509 certificate chain validation to ensure proper control flow.
Always wrap certificate validation operations in explicit error handling catching VerificationError to securely reject untrusted or malformed chains without crashing or bypassing verification paths.
Enforce Session Token Expiration with Fernet Decryption
Approximately 191 tokens
Use when
When validating time-sensitive session state or transient session tokens using Fernet symmetric encryption.
Secure rules
Rule 1: Specify an explicit ttl parameter during token decryption to enforce session expiration.
Pass an explicit ttl parameter in seconds to Fernet.decrypt() whenever tokens represent time-sensitive session data. Omitting ttl or setting it to None causes tokens to remain valid indefinitely as long as the key is recognized, allowing intercepted tokens to be replayed.
from cryptography.fernet import Fernet, InvalidTokenf = Fernet(key)try: data = f.decrypt(token, ttl=300)except InvalidToken: pass