Crypto-View

FiloSottile/age

Cryptographic posture

164 cryptographic locations: 1 already broken, 105 quantum-vulnerable, 6 reduced-margin, 5 undetermined, 47 quantum-safe

21 establish keys, so traffic protected by them and recorded today becomes readable once the algorithm falls. 1 imported cryptographic library is listed separately. 77 files analysed.

Quantum-vulnerable 105 Already broken 1 Reduced margin 6 Could not be determined 5 Quantum-safe 47
To address95
Key establishment21
Inventory only1
Total findings165
What was analysed
Branch main
Commit b74dce4cdbe35b5e5f66c06d9612b72f89028758 doc: regenerate groff and html man pages
Committed 2026-08-29 17:40 UTC
Scanned 2026-09-21 11:00 UTC 9 hours ago
Coverage 77 files, 47 go

List of cryptographic assets

RSA-10241024-bit Already broken Recorded traffic 1 place See details

RSA in the Go standard library

`rsa.GenerateKey()`, `rsa.SignPKCS1v15()`, `rsa.EncryptOAEP()` or an import of `crypto/rsa`.

This is already unsafe today, with no quantum computer involved. A modulus of 1024 bits or less is below the NIST SP 800-57 floor and is within reach of classical factorisation. Shor is not the nearest problem here.

What to do. ML-KEM-768 for encryption, ML-DSA-65 for signatures. Go 1.24 ships ML-KEM as `crypto/mlkem`.

  1. agessh/agessh_test.go:35 test path key, err := rsa.GenerateKey(rand.Reader, 1024)
go.rsa · CWE-327
Ed25519255-bitother/Ed25519 Quantum-vulnerable 26 places See details

SSH algorithms pinned in configuration

A `KexAlgorithms`, `HostKeyAlgorithms` or `Ciphers` directive in an SSH configuration. `KexAlgorithms` is the line that decides whether recorded sessions stay confidential.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Put `sntrup761x25519-sha512@openssh.com` first in `KexAlgorithms`. It is a hybrid, so it is no weaker than the classical exchange it replaces.

  1. README.md:192 or an SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
  2. README.md:284 As a convenience feature, age also supports encrypting to `ssh-rsa` and `ssh-ed25519` SSH public keys, and decrypting with the respective private key file. (`ssh-agent` is not supported.)
  3. SIGSUM.md:10 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM1WpnEswJLPzvXJDiswowy48U+G+G1kmgwUE2eaRHZG
  4. SIGSUM.md:11 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAz2WM5CyPLqiNjk7CLl4roDXwKhQ0QExXLebukZEZFS
  5. agessh/agessh.go:150 if pk.Type() != "ssh-ed25519" {
  6. agessh/agessh.go:183 case "ssh-ed25519":
  7. agessh/agessh.go:205 const ed25519Label = "age-encryption.org/v1/ssh-ed25519"
  8. agessh/agessh.go:223 tH := hkdf.New(sha256.New, nil, r.sshKey.Marshal(), []byte(ed25519Label))
  9. agessh/agessh.go:230 Type: "ssh-ed25519",
  10. agessh/agessh.go:238 h := hkdf.New(sha256.New, sharedSecret, salt, []byte(ed25519Label))
  11. agessh/agessh.go:311 if block.Type != "ssh-ed25519" {
  12. agessh/agessh.go:315 return nil, errors.New("invalid ssh-ed25519 recipient block")
  13. agessh/agessh.go:319 return nil, fmt.Errorf("failed to parse ssh-ed25519 recipient: %v", err)
  14. agessh/agessh.go:322 return nil, errors.New("invalid ssh-ed25519 recipient block")
  15. agessh/agessh.go:335 tH := hkdf.New(sha256.New, nil, i.sshKey.Marshal(), []byte(ed25519Label))
  16. agessh/agessh.go:344 h := hkdf.New(sha256.New, sharedSecret, salt, []byte(ed25519Label))
  17. agessh/encrypted_keys.go:50 case "ssh-ed25519":
  18. cmd/age/age.go:51 or an SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
  19. cmd/age/age_test.go:127 test path "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9pO5pz22JZEasoS2LEWWvJiUYI9M6l1uZc31FG",
  20. cmd/age/age_test.go:142 test path "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC",
  21. cmd/age/parse.go:138 case "ssh-ed25519":
  22. cmd/age/testdata/ed25519.txt:30 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9pO5pz22JZEasoS2LEWWvJiUYI9M6l1uZc31FGYMXa
  23. cmd/age/testdata/ed25519.txt:32 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFlMdZUMrWjJ3hh60MLALXSqUdAjBo/qEMJzvpekpoM
  24. cmd/age/testdata/encrypted_keys.txt:92 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaVctg4/hmFbfofTv+yrC2IweO/Dd2AVDijFpaMO9fm
  25. cmd/age/testdata/encrypted_keys.txt:94 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINbTd+xfSBYKR/1Hp7FsoxwQAdIOk1Khye6ALBj7e1CV
  26. internal/inspect/inspect.go:64 case "X25519", "ssh-rsa", "ssh-ed25519", "p256tag", "piv-p256":
config.ssh-algorithms · CWE-757
RSASSA-PKCS1v15 Quantum-vulnerable 21 places See details

SSH algorithms pinned in configuration

A `KexAlgorithms`, `HostKeyAlgorithms` or `Ciphers` directive in an SSH configuration. `KexAlgorithms` is the line that decides whether recorded sessions stay confidential.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer. The v1.5 signature scheme of RFC 8017 section 8.2 has no classical break of its own; RSA-PSS is preferred for new work, but the quantum exposure is the same for both.

What to do. Put `sntrup761x25519-sha512@openssh.com` first in `KexAlgorithms`. It is a hybrid, so it is no weaker than the classical exchange it replaces.

  1. README.md:192 or an SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
  2. README.md:284 As a convenience feature, age also supports encrypting to `ssh-rsa` and `ssh-ed25519` SSH public keys, and decrypting with the respective private key file. (`ssh-agent` is not supported.)
  3. agessh/agessh.go:40 const oaepLabel = "age-encryption.org/v1/ssh-rsa"
  4. agessh/agessh.go:50 if pk.Type() != "ssh-rsa" {
  5. agessh/agessh.go:77 Type: "ssh-rsa",
  6. agessh/agessh.go:82 r.pubKey, fileKey, []byte(oaepLabel))
  7. agessh/agessh.go:121 if block.Type != "ssh-rsa" {
  8. agessh/agessh.go:125 return nil, errors.New("invalid ssh-rsa recipient block")
  9. agessh/agessh.go:133 block.Body, []byte(oaepLabel))
  10. agessh/agessh.go:181 case "ssh-rsa":
  11. agessh/encrypted_keys.go:56 case "ssh-rsa":
  12. cmd/age/age.go:51 or an SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
  13. cmd/age/age_test.go:132 test path "ssh-rsa AAAAB3NzaC1yc2E=",
  14. cmd/age/age_test.go:137 test path "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCxlfoYpG04TTnmjocggQZI5l0fjvaUMky1ZD5zwktDKAgBj441OAtFj/3m7Gujpxx/8w3jjJoUXVtU+NFbcC972ROpPI4aPq3OR5SmuuR5bCr6efeZlyAEMY/DmbkeUe1TrvdU3VMDGJAvEEzT1wzokKt9PiwbV2jNkdPjaG5LDQ==",
  15. cmd/age/age_test.go:138 test path "ssh-rsa", true,
  16. cmd/age/parse.go:140 case "ssh-rsa":
  17. cmd/age/testdata/encrypted_keys.txt:139 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCky7Clp8I3LVoqZWtat+QR6KmM0evFilmFhwenINIBbb8eS3ftDSkQy2YRrlAvO3h4EZffOIxANGL/yKVlRCIzvjsphi+tTHscZsQhwMnLEmxEayTq20hZKcwNA8TQdh2TW/w0KZmNZcxlTn4IK8W16komHcoH/qrRiXq8z3ROcfnv3Q4Hll9MUCwBkfy2DdBpWUMidQ1d
  18. cmd/age/testdata/encrypted_keys.txt:141 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQiCWw2W++gX4wcwpDo6QIouwQ9PPwCVe7QPICzxztG27mzeKRM4xT2LURGSaQqg7OYIUTGrLqNsaLZW+FHHQlRAVv1LEbdEFa5JermBMJ5j/HxamE/7oV60gMRlgKW+4IZhVMPgRZaaXU0YPb9oACdMNM8kPkc5JaOJ8iO6B1RViybjLD+tsEEPXLp3Mrj+sJqs+IvNlJ
  19. cmd/age/testdata/rsa.txt:60 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDULTit0KUehbigbhsQaZo2oXLgMug8nTfnzDhcf5cEzdOJZyF6i5aRQbqbXIOYeTS3Shpp/iE6d60qi93JBBfveAZqr76tK7lVK8fstvAAGgbo9L9Ru5nhWX0HTlZUOodUT2E0rgAeoFzfvcZTaajzPmikrESmuaJLcdJ3crbCIyovkTxc85KbSn+Ky5grntdVR7GXve0H
  20. cmd/age/testdata/rsa.txt:62 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDF0OPu95EY25O5KmYFLIkiZZFKUlfvaRgmfIT6OcZvPRXBzo0MS/lcrYvAc0RsUVbZ1B3Y9oWmKt/IMXTztCXiza70rO1NI7ciayv5svY/wGMoveutddhA64IjrQKs4m+6Qmjs/dYTnfsk1BzmXrdRKUSqH6c4Id7pRLC1ySLu+4og3nTTpBRBpg+uSkc4Ua6ce6A6RX14
  21. internal/inspect/inspect.go:64 case "X25519", "ssh-rsa", "ssh-ed25519", "p256tag", "piv-p256":
config.ssh-algorithms · CWE-757
ECDH Quantum-vulnerable Recorded traffic 10 places See details

Key agreement in Go

`ecdh.P256()`, `ecdh.X25519()` or `curve25519.X25519()`. Key agreement is the highest priority: recorded traffic is decrypted retrospectively.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 (`crypto/mlkem` in Go 1.24), or a hybrid construction.

  1. agessh/agessh.go:212 ourPublicKey, err := curve25519.X25519(ephemeral, curve25519.Basepoint)
  2. agessh/agessh.go:217 sharedSecret, err := curve25519.X25519(ephemeral, r.theirPublicKey)
  3. agessh/agessh.go:227 sharedSecret, _ = curve25519.X25519(tweak, sharedSecret)
  4. agessh/agessh.go:269 i.ourPublicKey, _ = curve25519.X25519(i.secretKey, curve25519.Basepoint)
  5. agessh/agessh.go:329 sharedSecret, err := curve25519.X25519(i.secretKey, publicKey)
  6. agessh/agessh.go:339 sharedSecret, _ = curve25519.X25519(tweak, sharedSecret)
  7. x25519.go:70 ourPublicKey, err := curve25519.X25519(ephemeral, curve25519.Basepoint)
  8. x25519.go:75 sharedSecret, err := curve25519.X25519(ephemeral, r.theirPublicKey)
  9. x25519.go:127 i.ourPublicKey, _ = curve25519.X25519(i.secretKey, curve25519.Basepoint)
  10. x25519.go:176 sharedSecret, err := curve25519.X25519(i.secretKey, publicKey)
go.ecdh · CWE-327
Ed25519ed25519 Quantum-vulnerable 8 places See details

SSH public key

An `ssh-rsa`, `ecdsa-sha2-*`, `ssh-ed25519` or `ssh-dss` key. `ssh-dss` is disabled by default in current OpenSSH and is reported as broken.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Replace `ssh-dss` now. For the rest, enable the `sntrup761x25519-sha512` key exchange, which protects recorded sessions even while host keys stay classical.

  1. SIGSUM.md:10 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM1WpnEswJLPzvXJDiswowy48U+G+G1kmgwUE2eaRHZG
  2. SIGSUM.md:11 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAz2WM5CyPLqiNjk7CLl4roDXwKhQ0QExXLebukZEZFS
  3. cmd/age/age_test.go:127 test path "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9pO5pz22JZEasoS2LEWWvJiUYI9M6l1uZc31FG",
  4. cmd/age/age_test.go:142 test path "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
  5. cmd/age/testdata/ed25519.txt:30 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9pO5pz22JZEasoS2LEWWvJiUYI9M6l1uZc31FGYMXa
  6. cmd/age/testdata/ed25519.txt:32 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFlMdZUMrWjJ3hh60MLALXSqUdAjBo/qEMJzvpekpoM
  7. cmd/age/testdata/encrypted_keys.txt:92 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaVctg4/hmFbfofTv+yrC2IweO/Dd2AVDijFpaMO9fm
  8. cmd/age/testdata/encrypted_keys.txt:94 test path ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINbTd+xfSBYKR/1Hp7FsoxwQAdIOk1Khye6ALBj7e1CV
ssh.public-key · CWE-327
Ed25519255-bitother/Ed25519 Quantum-vulnerable 5 places See details

Ed25519 in the Go standard library

`ed25519.GenerateKey()` or `ed25519.Sign()`.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-DSA-65 (FIPS 204). Go 1.24 ships ML-DSA as `crypto/mldsa`.

  1. agessh/agessh_test.go:134 test path pub, priv, err := ed25519.GenerateKey(rand.Reader)
  2. agessh/agessh_test.go:177 test path _, targetKey, err := ed25519.GenerateKey(rand.Reader)
  3. agessh/agessh_test.go:186 test path _, otherKey, err := ed25519.GenerateKey(rand.Reader)
  4. agessh/agessh_test.go:219 test path announcedPub, _, err := ed25519.GenerateKey(rand.Reader)
  5. agessh/agessh_test.go:223 test path embeddedPub, embeddedPriv, err := ed25519.GenerateKey(rand.Reader)
go.ed25519 · CWE-327
RSA Quantum-vulnerable 5 places See details

SSH public key

An `ssh-rsa`, `ecdsa-sha2-*`, `ssh-ed25519` or `ssh-dss` key. `ssh-dss` is disabled by default in current OpenSSH and is reported as broken.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Replace `ssh-dss` now. For the rest, enable the `sntrup761x25519-sha512` key exchange, which protects recorded sessions even while host keys stay classical.

  1. cmd/age/age_test.go:137 test path "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCxlfoYpG04TTnmjocggQZI5l0fjvaUMky1ZD5zwkt
  2. cmd/age/testdata/encrypted_keys.txt:139 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCky7Clp8I3LVoqZWtat+QR6KmM0evFilmFhwenINIB
  3. cmd/age/testdata/encrypted_keys.txt:141 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQiCWw2W++gX4wcwpDo6QIouwQ9PPwCVe7QPICzxzt
  4. cmd/age/testdata/rsa.txt:60 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDULTit0KUehbigbhsQaZo2oXLgMug8nTfnzDhcf5cE
  5. cmd/age/testdata/rsa.txt:62 test path ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDF0OPu95EY25O5KmYFLIkiZZFKUlfvaRgmfIT6OcZv
ssh.public-key · CWE-327
RSA2048-bit Quantum-vulnerable Recorded traffic 3 places See details

RSA in the Go standard library

`rsa.GenerateKey()`, `rsa.SignPKCS1v15()`, `rsa.EncryptOAEP()` or an import of `crypto/rsa`.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 for encryption, ML-DSA-65 for signatures. Go 1.24 ships ML-KEM as `crypto/mlkem`.

  1. agessh/agessh_test.go:49 test path pk, err := rsa.GenerateKey(rand.Reader, 2048)
  2. agessh/agessh_test.go:92 test path targetKey, err := rsa.GenerateKey(rand.Reader, 2048)
  3. agessh/agessh_test.go:101 test path otherKey, err := rsa.GenerateKey(rand.Reader, 2048)
go.rsa · CWE-327
ECDH255-bitother/Curve25519 Quantum-vulnerable Recorded traffic 2 places See details

Key agreement in Go

`ecdh.P256()`, `ecdh.X25519()` or `curve25519.X25519()`. Key agreement is the highest priority: recorded traffic is decrypted retrospectively.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 (`crypto/mlkem` in Go 1.24), or a hybrid construction.

  1. plugin/encode.go:89 if pk.Curve() != ecdh.X25519() {
  2. plugin/encode.go:100 if t.Curve() != ecdh.X25519() {
go.ecdh · CWE-327
ECDH256-bitsecg/secp256r1 Quantum-vulnerable Recorded traffic 2 places See details

Key agreement in Go

`ecdh.P256()`, `ecdh.X25519()` or `curve25519.X25519()`. Key agreement is the highest priority: recorded traffic is decrypted retrospectively.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 (`crypto/mlkem` in Go 1.24), or a hybrid construction.

  1. tag/internal/tagtest/tagtest.go:26 k, err := hpke.DHKEM(ecdh.P256()).DeriveKeyPair([]byte(seed))
  2. tag/tag.go:78 k, err := hpke.DHKEM(ecdh.P256()).NewPublicKey(p.Bytes())
go.ecdh · CWE-327
ECDSA Quantum-vulnerable 2 places See details

SSH algorithms pinned in configuration

A `KexAlgorithms`, `HostKeyAlgorithms` or `Ciphers` directive in an SSH configuration. `KexAlgorithms` is the line that decides whether recorded sessions stay confidential.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Put `sntrup761x25519-sha512@openssh.com` first in `KexAlgorithms`. It is a hybrid, so it is no weaker than the classical exchange it replaces.

  1. cmd/age/age_test.go:152 test path "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOSh0Qo5zaBE33EiJnxwIBuZml9Nt9rCfvGi++FniWSk8X/10EO4E7KMgqGLlkCTDNIcbuKcsgfMw1/tifB8aTc=",
  2. cmd/age/age_test.go:153 test path "ecdsa-sha2-nistp256", true,
config.ssh-algorithms · CWE-757
RSA Quantum-vulnerable Recorded traffic 2 places See details

RSA in the Go standard library

`rsa.GenerateKey()`, `rsa.SignPKCS1v15()`, `rsa.EncryptOAEP()` or an import of `crypto/rsa`.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 for encryption, ML-DSA-65 for signatures. Go 1.24 ships ML-KEM as `crypto/mlkem`.

  1. agessh/agessh.go:81 wrappedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader,
  2. agessh/agessh.go:132 fileKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, i.k,
go.rsa · CWE-327
ECDSAsecp256r1 Quantum-vulnerable 1 place See details

SSH public key

An `ssh-rsa`, `ecdsa-sha2-*`, `ssh-ed25519` or `ssh-dss` key. `ssh-dss` is disabled by default in current OpenSSH and is reported as broken.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Replace `ssh-dss` now. For the rest, enable the `sntrup761x25519-sha512` key exchange, which protects recorded sessions even while host keys stay classical.

  1. cmd/age/age_test.go:152 test path "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOSh0Qo
ssh.public-key · CWE-327
Ed25519255-bitother/Ed25519 Quantum-vulnerable 1 place See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. cmd/age/testdata/pkcs8.txt:11 test path -----BEGIN PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
RSA Quantum-vulnerable Recorded traffic 1 place See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. cmd/age/testdata/encrypted_keys.txt:96 test path -----BEGIN RSA PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
unknown Could not be determined 3 places See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. cmd/age/testdata/ed25519.txt:22 test path -----BEGIN OPENSSH PRIVATE KEY-----
  2. cmd/age/testdata/encrypted_keys.txt:83 test path -----BEGIN OPENSSH PRIVATE KEY-----
  3. cmd/age/testdata/rsa.txt:21 test path -----BEGIN OPENSSH PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
unknown Could not be determined 2 places See details

SSH implementation in use

`golang.org/x/crypto/ssh`. Host keys are long-lived and awkward to rotate.

The algorithm could not be established from the source. Usually it is selected while the program runs, but it may equally be that the call gives no clue, or that it is decided somewhere this scan does not reach. Somebody has to check.

What to do. OpenSSH's `sntrup761x25519` hybrid key exchange addresses the recorded-traffic half; the host-key signature has no standardised replacement yet.

  1. agessh/agessh.go:99 s, err := ssh.NewSignerFromKey(key)
  2. agessh/agessh_test.go:25 test path pub, err := ssh.NewPublicKey(&rsa.PublicKey{N: n, E: 65537})
go.ssh · CWE-327
unknown Could not be determined 1 place See details

Cryptographic library in the dependency manifest

A dependency known to implement classical asymmetric cryptography. Its presence is inventory, not a finding about this codebase: the library may never be called with a quantum-vulnerable algorithm.

The project depends on a cryptography library. Listed so the inventory is complete; it is not by itself a problem.

What to do. Check the version. Several of these libraries have shipped ML-KEM and ML-DSA support since 2024, so the migration may need an upgrade rather than a replacement.

  1. go.mod:12 golang.org/x/crypto v0.55.0
dep.crypto-library
CSPRNG Quantum-safe 10 places See details

Random number generation

`crypto/rand`. Recorded so the inventory names its randomness source. `math/rand` reaching key material would be a present-day defect, and is a different thing entirely.

This is where the software gets its random numbers. Quantum computers do not weaken it.

What to do. No action.

  1. age.go:156 rand.Read(fileKey)
  2. agessh/agessh.go:209 if _, err := rand.Read(ephemeral); err != nil {
  3. agessh/agessh_test.go:73 test path if _, err := rand.Read(fileKey); err != nil {
  4. armor/armor_test.go:123 test path rand.Read(plain)
  5. cmd/age/wordlist.go:20 if _, err := rand.Read(buf); err != nil {
  6. internal/stream/stream_test.go:57 test path rand.Read(src)
  7. plugin/client.go:502 rand.Read(s.Body)
  8. recipients_test.go:35 test path if _, err := rand.Read(fileKey); err != nil {
  9. scrypt.go:66 if _, err := rand.Read(salt[:]); err != nil {
  10. x25519.go:67 if _, err := rand.Read(ephemeral); err != nil {
go.rng
HKDF Quantum-safe From a constant 4 places See details

Password hashing or key derivation

`golang.org/x/crypto/bcrypt`, `scrypt`, `argon2` or `pbkdf2`. Not a quantum exposure, and part of a complete inventory.

This is how passwords are stored. Quantum computers do not meaningfully weaken it.

What to do. Argon2id for new work.

  1. agessh/agessh.go:223 tH := hkdf.New(sha256.New, nil, r.sshKey.Marshal(), []byte(ed25519Label))
  2. primitives.go:53 h := hkdf.New(sha256.New, fileKey, nil, []byte("header"))
  3. testkit_test.go:409 test path h := hkdf.New(sha256.New, fileKey, nonce, []byte("payload"))
  4. x25519.go:88 h := hkdf.New(sha256.New, sharedSecret, salt, []byte(x25519Label))
go.kdf
HMAC Quantum-safe 2 places See details

Keyed hash in use

`hmac.New()`. Not broken by Shor and only marginally affected by Grover.

This is a fingerprint proving a message was not altered. Quantum computers do not break it.

What to do. No action, unless the digest is MD5 or SHA-1.

  1. age.go:371 } else if !hmac.Equal(mac, hdr.MAC) {
  2. primitives.go:58 hh := hmac.New(sha256.New, hmacKey)
go.hmac
ML-KEM-768 Quantum-safe 2 places See details

Post-quantum algorithm in use

`crypto/mlkem` or `crypto/mldsa`, added in Go 1.24. Recorded so the inventory shows completed migration work.

This is already a quantum-safe algorithm.

What to do. None. Confirm the parameter set matches the required NIST category.

  1. plugin/encode.go:99 func EncodeHybridRecipient(pq *mlkem.EncapsulationKey768, t *ecdh.PublicKey) (string, error) {
  2. tag/tag.go:114 tagRecipient = tagRecipient[mlkem.EncapsulationKeySize768:]
go.pqc
scrypt Quantum-safe 1 place See details

Password hashing or key derivation

`golang.org/x/crypto/bcrypt`, `scrypt`, `argon2` or `pbkdf2`. Not a quantum exposure, and part of a complete inventory.

This is how passwords are stored. Quantum computers do not meaningfully weaken it.

What to do. Argon2id for new work.

  1. scrypt.go:77 k, err := scrypt.Key(r.password, salt, 1<<logN, 8, 1, chacha20poly1305.KeySize)
go.kdf

Cryptographic assets

Algorithm Assessment What it means Occurrences
Ed25519 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 47
RSASSA-PKCS1v15 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. The v1.5 signature scheme of RFC 8017 section 8.2 has no classical break of its own; RSA-PSS is preferred for new work, but the quantum exposure is the same for both. 21
CSPRNG Quantum-safe A cryptographically secure random number generator provided by the platform. Not weakened by a quantum computer. 20
ECDH Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 17
RSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 15
HKDF Quantum-safe No known quantum algorithm changes the security margin. 8
ChaCha20-Poly1305 Quantum-safe No known quantum algorithm changes the security margin. 8
SHA-256 Reduced margin Pre-image resistance falls to about 128 bits of quantum work. Adequate for most uses; SHA-384 restores the full margin where a signature must last decades. 5
unknown Could not be determined The algorithm could not be established from the source - chosen at runtime, or decided somewhere this scan does not reach. 5
HMAC Quantum-safe A keyed MAC is not affected by Shor and only marginally by Grover. 4
ML-KEM-768 Quantum-safe No known quantum algorithm changes the security margin. 4
ECDSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 3
X25519 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 2
scrypt Quantum-safe No known quantum algorithm changes the security margin. 2
AES Reduced margin Grover's algorithm halves the effective strength; the parameter, not the design, is the problem. The key size was not visible at this call site, so the weaker case is assumed. 1
SHA-512 Quantum-safe No known quantum algorithm changes the security margin. 1
RSA-1024 Already broken A modulus of 1024 bits or less is below the NIST SP 800-57 floor and is within reach of classical factorisation. Shor is not the nearest problem here. 1

Imported cryptographic libraries

Library Files
crypto/ed25519 Edwards-curve signatures 4
crypto/rsa RSA key generation, signing and OAEP encryption 4
crypto/ecdh elliptic-curve key agreement 3
golang.org/x/crypto/curve25519 X25519 key agreement 2
crypto/sha256 the SHA-2 digests 5
crypto/cipher block-cipher modes 1
crypto/rand the platform random source 10
golang.org/x/crypto/chacha20poly1305 authenticated symmetric encryption 8
golang.org/x/crypto/hkdf key derivation from a shared secret 4
crypto/hmac keyed message authentication 2
crypto/mlkem ML-KEM (FIPS 203), added in Go 1.24 2
crypto/sha512 the SHA-2 digests 1
golang.org/x/crypto/scrypt password hashing 1