Skip to content

Latest commit

 

History

History
169 lines (122 loc) · 7.32 KB

File metadata and controls

169 lines (122 loc) · 7.32 KB

Cryptography

The modern, audited Python cryptography library (cryptography) providing symmetric/asymmetric encryption, hashing, key derivation, and X.509 handling behind a safe high-level API.

Overview

The cryptography package exposes a "recipes" layer (like Fernet) for foolproof symmetric encryption plus a "hazmat" layer for lower-level primitives (AES, RSA, ECDSA, HMAC, PBKDF2). It is the recommended library for any real crypto in Python — replacing home-grown or deprecated PyCrypto code. Security professionals use it to protect tooling data, hash and derive keys, and analyze certificates during assessments.

Installation

pip install cryptography

Basic Usage

from cryptography.fernet import Fernet

key = Fernet.generate_key()            # store this securely - losing it loses the data
cipher = Fernet(key)

token = cipher.encrypt(b"lab notes - not real data")
print(token[:24], "...")

print(cipher.decrypt(token))

Fernet is the recipes layer: authenticated symmetric encryption with sensible defaults and no options to get wrong. Prefer it over assembling primitives yourself.

Important APIs

API Purpose
fernet.Fernet.generate_key() Generate a symmetric key
Fernet(key).encrypt/decrypt(data) Authenticated symmetric encryption
fernet.MultiFernet([...]) Key rotation
hazmat.primitives.hashes.SHA256() Hash algorithm objects
hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC Derive a key from a password
hazmat.primitives.asymmetric.rsa/ec Key generation and signing
hazmat.primitives.serialization Load and write PEM/DER keys
x509.load_pem_x509_certificate(data) Parse a certificate
cert.subject, cert.issuer, cert.not_valid_after_utc Certificate fields
x509.CertificateBuilder() Build a certificate (lab CAs, self-signed)

Note

Anything under hazmat is "hazardous materials" — the library's own name for its low-level primitives. Reach for it only when the recipes layer genuinely cannot do the job. Note also that some certificate properties gained _utc variants in recent releases; check the version you have installed.

Example

Authenticated symmetric encryption with Fernet (safe default):

from cryptography.fernet import Fernet

key = Fernet.generate_key()          # store this securely
f = Fernet(key)

token = f.encrypt(b"loot: internal-admin:S3cret!")
print("ciphertext:", token[:24], b"...")
print("decrypted :", f.decrypt(token).decode())

Output

ciphertext: b'gAAAAABl...' b'...'
decrypted : loot: internal-admin:S3cret!

Password-based key derivation with PBKDF2 (never store raw passwords):

import os
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes

salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480000)
derived = kdf.derive(b"correct horse battery staple")

print("salt:", salt.hex())
print("key :", derived.hex()[:32], "...")

Output

salt: 9f3c1a...e2
key : 4b7d9f0c2a18e5...  ...

Parse an X.509 certificate and read its fields (TLS assessment):

from cryptography import x509
from cryptography.hazmat.primitives import hashes

with open("server.crt", "rb") as fh:
    cert = x509.load_pem_x509_certificate(fh.read())

print("subject :", cert.subject.rfc4514_string())
print("issuer  :", cert.issuer.rfc4514_string())
print("expires :", cert.not_valid_after_utc)
print("sha256  :", cert.fingerprint(hashes.SHA256()).hex()[:32], "...")

Output

subject : CN=example.com
issuer  : CN=Example CA
expires : 2026-11-01 00:00:00+00:00
sha256  : 3a1f8c9b2e...  ...

Security Use Cases

  • Encryption / decryption — protect credentials, loot, and config in your own tooling with Fernet or AES-GCM.
  • Password hashing & KDFs — derive keys and store password verifiers with PBKDF2/scrypt instead of raw hashes.
  • Integrity & signing — compute HMACs and verify ECDSA/RSA signatures for tamper detection.
  • Certificate analysis — parse X.509 certs to check expiry, weak keys, and misissued SANs during TLS reviews.
  • Secure random generation — produce cryptographically strong tokens and salts (os.urandom, secrets).

Important

Do not roll your own crypto or use deprecated ciphers (MD5, DES, ECB). Prefer the high-level Fernet recipe unless you have a specific reason to touch hazmat.

Common Mistakes

  • Building your own construction from hazmat primitives when Fernet would do — this is how nonce reuse and unauthenticated encryption creep in.
  • Encrypting without authentication. Raw AES-CBC has no integrity protection and is vulnerable to padding-oracle attacks; use Fernet or AES-GCM.
  • Reusing a nonce or IV with the same key — catastrophic for GCM and CTR modes.
  • Hardcoding keys in source or committing them to a repository.
  • Deriving a key from a password without a KDF — use PBKDF2HMAC or scrypt with a random salt and a high iteration count.
  • Comparing MACs with == rather than a constant-time comparison.
  • Confusing encryption with hashing — encryption is reversible by design, hashing is not.
  • Installing crypto or pycrypto — the maintained package is cryptography; pycrypto is unmaintained and has known vulnerabilities.

Security Considerations

[!warning] Do not design your own cryptography Use the recipes layer. Novel constructions built from primitives are where real systems break.

  • Key management is the hard part. Generating a key is trivial; storing, rotating, and revoking it safely is the actual problem. Use a secrets manager, a KMS, or the OS keyring — never a file beside the ciphertext, and never source control.
  • Always use authenticated encryption. Without it, an attacker can modify ciphertext undetected. Fernet and AES-GCM authenticate; CBC alone does not.
  • Passwords need a slow KDF, not a hash. PBKDF2HMAC and scrypt are here for that; see also [[Hashlib-Module|hashlib]].
  • Randomness must be cryptographic. Use the library's generators or [[Secrets-Module|secrets]], never random.
  • Keep the library current. cryptography ships security fixes and bundles OpenSSL; an old version is a real exposure.
  • Certificate validation is not optional. Parsing a certificate is not the same as verifying its chain, hostname, and validity dates.
  • Never use real production keys or data in course exercises.

Best Practices

  • Use Fernet or AES-GCM for authenticated encryption; avoid unauthenticated modes.
  • Use a unique random salt/nonce per message and never reuse a nonce with the same key.
  • Pick a high PBKDF2 iteration count (hundreds of thousands) or prefer scrypt/argon2 for passwords.
  • Keep keys out of source control — load them from a secrets manager or environment.
  • Track library updates; crypto bugs get patched and algorithms get deprecated.

References

Related Topics

  • [[pyOpenSSL]] — OpenSSL-backed TLS and certificate operations
  • [[requests]] — consume the TLS endpoints whose certs you analyze here
  • [[Readme|Python for Security Professionals]] — course home