Key Management
Key Generation & Storage
Creating keys correctly and keeping them out of code and repos.
A key is only as good as its birth and its resting place. A key generated from a weak random source is guessable no matter how strong the algorithm, and a perfectly generated key stored in plaintext in your repo is already public. This page covers both halves: making keys correctly, and keeping them out of code, images, and history.
Generating keys with the right tool and parameters
Use a vetted tool that draws from the operating system’s cryptographic RNG. Do not roll your own generation, and do not seed from timestamps, PIDs, or other predictable values. The right parameters depend on purpose:
mkdir -p ~/crypto-lab && cd ~/crypto-lab
# Signing key: Ed25519 (modern default)
openssl genpkey -algorithm ed25519 -out signing.pem
# Key exchange: X25519
openssl genpkey -algorithm x25519 -out exchange.pem
# NIST curve when required
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out p256.pem
# RSA only if a peer requires it: at least 3072 bits
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rsa.pem
Expected output:
(no output on success; four .pem files created)
| Purpose | Recommended | Avoid |
|---|---|---|
| Signatures | Ed25519 | RSA < 3072, DSA |
| Key exchange | X25519 | Static/reused DH |
| NIST-mandated | ECDSA/ECDH P-256 | Custom curves |
| Legacy interop | RSA >= 3072 | RSA 1024, textbook RSA |
See the sibling group Asymmetric Cryptography for why these choices win.
The leak hierarchy
Where you put a key determines how badly it leaks. From worst to best:
| Storage | Blast radius | Verdict |
|---|---|---|
| Hardcoded in source | Everyone with repo/history access | Never |
| Environment variable | Leaks via process listing, crash dumps, child processes | Weak |
| File on disk | Anyone with filesystem/backup access | Baseline, needs protection |
| Secret store (Vault, cloud secrets) | Access-controlled, audited, versioned | Good |
| HSM / KMS | Key never leaves the boundary | Best |
The jump that matters most is off the first two rungs. A hardcoded key lives forever in Git history even after you delete the line; an env var shows up in /proc, in crash reports, and inherits into every subprocess. Move keys into a secret store or KMS (see the sibling KMS & HSM) as early as you can.
Protecting keys at rest: passphrases and file permissions
When a key must live in a file, encrypt it with a passphrase and lock down its permissions.
cd ~/crypto-lab
# Wrap an existing private key with a passphrase (AES-256)
openssl pkey -in signing.pem -aes-256-cbc -out signing.enc.pem
# Lock permissions so only the owner can read it
chmod 600 signing.enc.pem
ls -l signing.enc.pem
Expected output:
Enter Encryption Password:
Verifying - Enter Encryption Password:
-rw------- 1 you staff 464 Jul 6 10:12 signing.enc.pem
The -rw------- (600) permission means only the owner can read the file; group and world have nothing. The passphrase adds a second layer so a stolen file is not immediately usable. For a friendlier experience, tools like age and gpg encrypt files to a key with sane defaults:
# age: encrypt a secret file to a recipient's public key
age-keygen -o age-key.txt
grep "public key" age-key.txt
echo -n "top secret" | age -r age1qp...recipient -o secret.age
Expected output:
# public key: age1qp...recipient
(secret.age written)
Practical Guidance
- Generate keys only with vetted tools backed by the OS CSPRNG. Never seed from predictable values or write your own generator.
- Match parameters to purpose: Ed25519 to sign, X25519 to exchange, RSA >= 3072 only for legacy interop.
- Get keys off the bottom of the leak hierarchy fast: no hardcoding, avoid env vars, move to a secret store or KMS.
- Encrypt private key files with a passphrase and set permissions to 600 so only the owner can read them.
- Scan repos and CI history for committed keys; if one is found, rotate it rather than just deleting the line.
- Back up keys encrypted and access-controlled, and store the backup separately from the systems that use the key.