Skip to content

FIPS-Compliant SSH RSA Keys (Air-Gapped)

Generate strong RSA SSH keys that meet FIPS requirements (NIST SP 800-131A: modulus ≥ 2048 bits) while remaining compatible with older non-FIPS / legacy systems.

All commands below run fully offline and are suitable for air-gapped environments.


Size Security Strength Recommendation
2048 ~112-bit Minimum for FIPS. Best legacy compatibility.
3072 ~128-bit Preferred balance of strength and broad support.
4096 higher Strong, but slower; may be rejected by very old systems.

Avoid keys smaller than 2048 bits — they are disallowed for signature generation under current FIPS guidance.


Generating Classic PEM (PKCS#1) Keys

Use ssh-keygen with -m PEM to produce the traditional format (-----BEGIN RSA PRIVATE KEY-----) that many older tools and systems expect.

2048-bit (maximum legacy compatibility)

ssh-keygen -t rsa -b 2048 -m PEM -f id_rsa_fips_legacy -C "fips-rsa-2048-airgap"

3072-bit (stronger, still widely supported)

ssh-keygen -t rsa -b 3072 -m PEM -f id_rsa_fips_3072 -C "fips-rsa-3072-airgap"
  • Omit -N "" (or supply a passphrase) if you want the private key encrypted.
  • The corresponding .pub file is created automatically and is in standard OpenSSH public-key format.

Generating PKCS#8 Keys

PKCS#8 uses the modern container format (-----BEGIN PRIVATE KEY----- or -----BEGIN ENCRYPTED PRIVATE KEY-----).

Unencrypted PKCS#8 (2048-bit)

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
  -out id_rsa_pkcs8.pem

Encrypted PKCS#8 (2048-bit)

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
  -aes-256-cbc -out id_rsa_pkcs8_encrypted.pem

For a 3072-bit key, replace rsa_keygen_bits:2048 with rsa_keygen_bits:3072.

Extract the public key

# From unencrypted key
openssl rsa -in id_rsa_pkcs8.pem -pubout -out id_rsa_pkcs8.pub

# From encrypted key (will prompt for passphrase)
openssl rsa -in id_rsa_pkcs8_encrypted.pem -pubout -out id_rsa_pkcs8.pub

You can also convert an existing PEM key to PKCS#8:

openssl pkcs8 -topk8 -inform PEM -outform PEM \
  -in id_rsa_fips_legacy -out id_rsa_pkcs8.pem -nocrypt

Printing Key Fingerprints

# SHA256 fingerprint (recommended)
ssh-keygen -l -f id_rsa_fips_legacy.pub

# With randomart
ssh-keygen -l -v -f id_rsa_fips_legacy.pub

# MD5 fingerprint (legacy style)
ssh-keygen -l -E md5 -f id_rsa_fips_legacy.pub

# Works on private keys as well
ssh-keygen -l -f id_rsa_pkcs8.pem

The fingerprint is always derived from the public key material, so private and public files for the same key produce identical results.


Quick Verification (Air-Gapped)

# Integrity check
openssl rsa -in id_rsa_pkcs8.pem -check -noout
# Expected: RSA key ok

# Confirm modulus size and structure
openssl rsa -in id_rsa_pkcs8.pem -text -noout | head -5

# Confirm format
head -1 id_rsa_pkcs8.pem
# Expected: -----BEGIN PRIVATE KEY-----  (or ENCRYPTED PRIVATE KEY)

For classic PEM keys generated by ssh-keygen -m PEM:

openssl rsa -in id_rsa_fips_legacy -check -noout
ssh-keygen -l -f id_rsa_fips_legacy

File Permissions

chmod 600 id_rsa_*          # private keys
chmod 644 *.pub             # public keys

Compatibility Notes

  • FIPS systems: Prefer rsa-sha2-256 and rsa-sha2-512 signature algorithms. 2048-bit and larger RSA keys are acceptable.
  • Legacy systems: Many older implementations only understand the traditional ssh-rsa (SHA-1) signature and the PKCS#1 private-key format. Keep a -m PEM copy if you must interoperate with them. You may need to explicitly enable ssh-rsa in PubkeyAcceptedAlgorithms / HostKeyAlgorithms on the FIPS side (note that this can affect FIPS mode status on some platforms).
  • Private-key formats:
  • PKCS#1 (BEGIN RSA PRIVATE KEY) — best for very old tools.
  • PKCS#8 (BEGIN PRIVATE KEY) — preferred by modern OpenSSL, Java, and most contemporary software.
  • OpenSSH native format (BEGIN OPENSSH PRIVATE KEY) — requires OpenSSH ≥ 7.8.

Air-Gapped Best Practices

  1. Generate keys on the air-gapped system itself whenever possible (especially if it is running in FIPS mode so the validated RNG is used).
  2. Transfer public keys and, when necessary, private keys only via secure physical media.
  3. Never expose private keys over a network.
  4. Document the fingerprint of every deployed key for verification.
  5. Prefer 3072-bit keys unless you have a concrete legacy-system constraint that requires 2048-bit.

Summary of Common Commands

Goal Command
2048-bit PEM key ssh-keygen -t rsa -b 2048 -m PEM -f keyname
3072-bit PEM key ssh-keygen -t rsa -b 3072 -m PEM -f keyname
Unencrypted PKCS#8 openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out key.pem
Encrypted PKCS#8 openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-256-cbc -out key.pem
Extract public key openssl rsa -in private.pem -pubout -out public.pub
Show fingerprint ssh-keygen -l -f key.pub
Verify key openssl rsa -in private.pem -check -noout

All key material should be treated as sensitive. Regenerate keys on your own systems for production use.