RSA Key Generation
RSA is the oldest widely used public-key system: a key pair derived from the product of two large primes, with the security resting on the difficulty of factoring that product. You generate a private key (both primes plus derived exponents) and export its public half (modulus and public exponent). Key size is the security dial: 2048 bits is the current minimum, 3072+ for long-lived keys.
Generating a Key Pair
from cryptography.hazmat.primitives.asymmetric import rsa
private_key = rsa.generate_private_key(
public_exponent=65537, # standard Fermat prime; fast public ops
key_size=2048, # 2048 minimum; 3072 for the long term
)
public_key = private_key.public_key()
print(private_key.key_size) # 2048
print(public_key.public_numbers().e) # 65537
Generation takes a noticeable second or more for 2048 bits because it must find two safe primes - generate keys once and store them, not per request.
Serializing Keys
Keys are objects; to store or send them you serialize. Two encodings exist: DER (binary) and PEM (base64 text with headers), and two structures: PKCS#8 for private keys and SubjectPublicKeyInfo for public keys.
from cryptography.hazmat.primitives import serialization
pem_private = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
print(pem_private[:30]) # b'-----BEGIN PRIVATE KEY-----\nM...'
pem_public = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
# load them back
loaded = serialization.load_pem_private_key(pem_private, password=None)
Protecting the Private Key
from cryptography.hazmat.primitives.ciphers import AES
# encrypt the PEM with a passphrase (PBES2 + AES)
protected = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(
b"change-me-in-a-secret-manager"),
)
# load with the passphrase
key = serialization.load_pem_private_key(protected, password=b"change-me-in-a-secret-manager")
In practice the passphrase is a secret from your key store, and the file permissions on the key file should be 0600. The private key is the entire identity of the RSA pair - losing it loses every signature and decryption it performed.
Key Size Guidance
| Size | Security | Use |
|---|---|---|
| 2048 | ~112 bits | minimum for new keys |
| 3072 | ~128 bits | long-lived certificates, signatures |
| 4096 | ~140+ bits | very long-lived or high-value keys |
Summary
Generate 2048-bit (or larger) RSA keys with the standard 65537 exponent, export them as PKCS#8/SPKI in PEM, protect private keys with a secret-store passphrase and tight permissions, and size keys to how long they must stay secret.