Crypto-View

keycloak/keycloak

Readiness score
0 of 100
How this is calculated · previous scan 0
Cryptographic posture
Quantum-vulnerable 279 Already broken 6 Reduced margin 75 Could not be determined 501 Quantum-safe 62
To address270
Key establishment109
Inventory only13
Total findings936
What was analysed
Branch Not at a branch head The commit was given directly and is not the tip of any branch in the repository.
Commit 13f76e36015411e8c5f319b96bd181e70c627ff4 SSF: Revise SSF event structure (#50792) (#50793)
Committed 2026-08-06 18:51 UTC
Scanned 2026-09-10 07:45 UTC 19 hours ago
Coverage 10502 files, 8200 java, 1 python, 1080 javascript

Earlier scans of this repository

15 scans · score 0 → 0 · compare any two
15 scans · 0 → 0 (unchanged). The filled point is the scan you are reading.
Scanned Commit Score To address
4 hours ago 61a4555fe865 main 0 804 Compare
5 hours ago 61a4555fe865 main 0 283 Compare
18 hours ago 3a720903102b main 0 283 Compare
19 hours ago this scan 13f76e360154 0 270
21 hours ago 3a720903102b main 0 283 Compare
1 day ago 3a720903102b main 0 283 Compare
1 day ago 3a720903102b main 0 283 Compare
1 day ago 3a720903102b main 0 283 Compare
1 day ago 3a720903102b main 0 257 Compare
2 days ago 68ff31182d1f main 0 245 Compare
3 days ago 0cd2f7891a69 main 0 245 Compare
3 days ago 0cd2f7891a69 main 0 245 Compare
4 days ago f5a00e4a5c2d main 0 243 Compare
10 days ago ae1a37058feb main 0 243 Compare
11 days ago 13f76e360154 0 232 Compare

Every repository in this history is re-scanned weekly.

List of cryptographic assets

SHA-1 Already broken 3 places See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

This is already unsafe today, with no quantum computer involved. SHAttered and subsequent work produced practical collisions; NIST withdrew SHA-1 in 2030 guidance and it is already unacceptable for signatures.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. server-spi-private/src/main/java/org/keycloak/protocol/saml/util/ArtifactBindingUtils.java:48 MessageDigest sha1Digester = MessageDigest.getInstance("SHA-1");
  2. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ArtifactBindingTest.java:195 test path MessageDigest sha1Digester = MessageDigest.getInstance("SHA-1");
  3. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ArtifactBindingTest.java:455 test path MessageDigest sha1Digester = MessageDigest.getInstance("SHA-1");
java.messagedigest · CWE-328
RSAES-PKCS1v15 Already broken Recorded traffic 2 places See details

Cipher transformation named away from the call

A JCA transformation string - `algorithm/mode/padding` - written somewhere other than a `getInstance()` argument, which is how a codebase that centralises its cryptography passes the choice to a helper. The string is unambiguous wherever it appears: nothing but a transformation is spelled that way.

This names an encryption method as text, and passes it to code elsewhere that does the work. It is the same choice, made in a different place.

What to do. The same migration applies as to the call that consumes it. Move the constant and the call together, so the inventory keeps naming the algorithm after the change.

  1. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:59 providers.put(CryptoConstants.RSA1_5, new DefaultRsaKeyEncryptionJWEAlgorithmProvider("RSA/ECB/PKCS1Padding"));
  2. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:60 providers.put(CryptoConstants.RSA1_5, new ElytronRsaKeyEncryptionJWEAlgorithmProvider("RSA/ECB/PKCS1Padding"));
java.transformation · CWE-327
MD5 Already broken 1 place See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

This is already unsafe today, with no quantum computer involved. Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. services/src/main/java/org/keycloak/cache/ComputedKey.java:34 return MessageDigest.getInstance("MD5");
java.messagedigest · CWE-328
RSA4096-bit Quantum-vulnerable 26 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

  1. operator/src/test/resources/example-mtls-secret.yaml:7 test path -----BEGIN CERTIFICATE-----
  2. operator/src/test/resources/example-mtls-truststore-secret.yaml:7 test path -----BEGIN CERTIFICATE-----
  3. services/src/test/resources/truststores/keycloak.pem:1 test path -----BEGIN CERTIFICATE-----
  4. tests/base/src/test/resources/keycloak-truststore.pem:6 test path -----BEGIN CERTIFICATE-----
  5. tests/base/src/test/resources/keycloak-truststore.pem:79 test path -----BEGIN CERTIFICATE-----
  6. testsuite/integration-arquillian/servers/auth-server/common/keystore/ca.crt:1 test path -----BEGIN CERTIFICATE-----
  7. testsuite/integration-arquillian/servers/auth-server/common/keystore/ca.crt:35 test path -----BEGIN CERTIFICATE-----
  8. testsuite/integration-arquillian/servers/auth-server/common/keystore/client-ca.crt:1 test path -----BEGIN CERTIFICATE-----
  9. testsuite/integration-arquillian/servers/auth-server/common/keystore/client.crt:1 test path -----BEGIN CERTIFICATE-----
  10. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/ca.cert.pem:1 test path -----BEGIN CERTIFICATE-----
  11. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-ca@localhost.csr:1 test path -----BEGIN CERTIFICATE REQUEST-----
  12. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-ca@localhost.pem:94 test path -----BEGIN CERTIFICATE-----
  13. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-obb@localhost.cert.pem:1 test path -----BEGIN CERTIFICATE-----
  14. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-obb@localhost.csr.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  15. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-san@localhost.cert.pem:1 test path -----BEGIN CERTIFICATE-----
  16. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/certs/ca-chain.cert.pem:1 test path -----BEGIN CERTIFICATE-----
  17. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/certs/ca-chain.cert.pem:35 test path -----BEGIN CERTIFICATE-----
  18. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/certs/intermediate.cert.pem:1 test path -----BEGIN CERTIFICATE-----
  19. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/csr/intermediate.csr.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  20. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/newcerts/1000.pem:1 test path -----BEGIN CERTIFICATE-----
  21. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/newcerts/2009.pem:1 test path -----BEGIN CERTIFICATE-----
  22. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/newcerts/200A.pem:1 test path -----BEGIN CERTIFICATE-----
  23. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/newcerts/200B.pem:1 test path -----BEGIN CERTIFICATE-----
  24. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/newcerts/1000.pem:1 test path -----BEGIN CERTIFICATE-----
  25. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/newcerts/1001.pem:94 test path -----BEGIN CERTIFICATE-----
  26. testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/intermediate-ca.crt:1 test path -----BEGIN CERTIFICATE-----
pem.certificate
TLS Quantum-vulnerable Recorded traffic 19 places See details

TLS context created in code

`SSLContext.getInstance()`. The protocol version is reported; the key exchange it negotiates is classical in every TLS 1.2 and 1.3 cipher suite available today.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls.

What to do. Keep TLS 1.3, and track the hybrid key-exchange groups as they reach the JDK. TLS is where harvest-now-decrypt-later exposure is largest.

  1. adapters/saml/core/src/main/java/org/keycloak/adapters/cloned/HttpClientBuilder.java:263 theContext = SSLContext.getInstance("SSL");
  2. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402SslTest.java:133 test path SSLContext context = SSLContext.getInstance("TLS");
  3. model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/JGroupsConfigurator.java:226 var sslContext = SSLContext.getInstance(TLS_PROTOCOL);
  4. model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/remote/DefaultCacheRemoteConfigProviderFactory.java:237 var sslContext = SSLContext.getInstance("TLS");
  5. operator/src/main/java/org/keycloak/operator/controllers/KeycloakClientBaseController.java:368 SSLContext sslContext = SSLContext.getInstance("TLS");
  6. operator/src/test/java/org/keycloak/operator/testsuite/utils/TrustAllSSLContext.java:48 test path sslContext = SSLContext.getInstance("TLS");
  7. services/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java:271 theContext = SSLContext.getInstance("TLS");
  8. services/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java:282 final SSLContext tlsContext = SSLContext.getInstance("TLS");
  9. services/src/main/java/org/keycloak/truststore/JSSETruststoreConfigurator.java:59 SSLContext sslctx = SSLContext.getInstance("TLS");
  10. test-framework/core/src/main/java/org/keycloak/testframework/server/DistributionKeycloakServer.java:263 test path SSLContext sslContext = SSLContext.getInstance("TLS");
  11. test-framework/core/src/main/java/org/keycloak/testframework/server/ReadinessProbe.java:88 test path SSLContext ctx = SSLContext.getInstance("TLS");
  12. tests/conformance/src/test/java/org/keycloak/tests/conformance/containers/OpenIdConformanceSuite.java:185 test path SSLContext context = SSLContext.getInstance("TLS");
  13. tests/conformance/src/test/java/org/keycloak/tests/conformance/vp/AbstractVpConformanceTest.java:96 test path SSLContext sslContext = SSLContext.getInstance("TLS");
  14. testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/AbstractQuarkusDeployableContainer.java:414 test path sslContext = SSLContext.getInstance("TLS");
  15. testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/InfinispanServerDeployableContainer.java:175 test path SSLContext sc = SSLContext.getInstance("SSL");
  16. testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/MutualTLSUtils.java:103 test path SSLContext sslContext = SSLContext.getInstance("TLS");
  17. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SslMailServer.java:119 test path final SSLContext sslContext = SSLContext.getInstance("TLS");
  18. testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/tls/TLSUtils.java:66 test path sslContext = SSLContext.getInstance("TLS");
  19. util/embedded-ldap/src/main/java/org/keycloak/util/ldap/TLS13StartTlsHandler.java:68 sslCtx = SSLContext.getInstance("TLS");
java.sslcontext · CWE-757
RSA2048-bit Quantum-vulnerable 16 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

  1. core/src/test/resources/certs/ANS-cert.pem:1 test path -----BEGIN CERTIFICATE-----
  2. core/src/test/resources/certs/UPN-cert.pem:1 test path -----BEGIN CERTIFICATE-----
  3. operator/src/test/resources/example-truststore-secret.yaml:7 test path -----BEGIN CERTIFICATE-----
  4. quarkus/tests/integration/src/test/resources/self-signed.pem:1 test path -----BEGIN CERTIFICATE-----
  5. services/src/test/resources/truststores/keycloak.pem:30 test path -----BEGIN CERTIFICATE-----
  6. tests/base/src/test/resources/keycloak-truststore.pem:46 test path -----BEGIN CERTIFICATE-----
  7. tests/base/src/test/resources/org/keycloak/tests/ssl/smtp-server.pem:1 test path -----BEGIN CERTIFICATE-----
  8. testsuite/integration-arquillian/servers/auth-server/common/keystore/ocsp/certs/ca-chain.crt:1 test path -----BEGIN CERTIFICATE-----
  9. testsuite/integration-arquillian/servers/auth-server/common/keystore/ocsp/certs/ca-chain.crt:24 test path -----BEGIN CERTIFICATE-----
  10. testsuite/integration-arquillian/servers/auth-server/common/keystore/ocsp/certs/intermediate-ca.crt:1 test path -----BEGIN CERTIFICATE-----
  11. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/newcerts/intermediate-ca-3.crt:1 test path -----BEGIN CERTIFICATE-----
  12. testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/ocsp/certs/ca-chain.crt:1 test path -----BEGIN CERTIFICATE-----
  13. testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/ocsp/certs/ca-chain.crt:24 test path -----BEGIN CERTIFICATE-----
  14. testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/ocsp/certs/intermediate-ca.crt:1 test path -----BEGIN CERTIFICATE-----
  15. testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/intermediate-ca-2.crt:1 test path -----BEGIN CERTIFICATE-----
  16. testsuite/integration-arquillian/tests/base/src/test/resources/keys/certificate.pem:1 test path -----BEGIN CERTIFICATE-----
pem.certificate
ECDH Quantum-vulnerable Recorded traffic 15 places See details

Classical key material handled through the JCA

`KeyFactory.getInstance()` for a classical algorithm. This indicates the code parses or produces keys of that family, which is a migration surface even where it does no cryptography itself.

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. Include this code path in the inventory: it has to accept post-quantum key encodings before the keys themselves can change.

  1. core/src/test/java/org/keycloak/sdjwt/TestSettings.java:166 test path KeyFactory keyFactory = KeyFactory.getInstance("EC");
  2. core/src/test/java/org/keycloak/sdjwt/TestSettings.java:192 test path KeyFactory keyFactory = KeyFactory.getInstance("EC");
  3. crypto/default/src/main/java/org/keycloak/crypto/def/BCECDSACryptoProvider.java:81 KeyFactory keyFactory = KeyFactory.getInstance("EC");
  4. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:199 KeyFactory keyFactory = KeyFactory.getInstance("EC");
  5. crypto/default/src/test/java/org/keycloak/crypto/def/test/BCEcdhEsAlgorithmProviderTest.java:116 test path KeyFactory keyFactory = KeyFactory.getInstance("EC");
  6. crypto/default/src/test/java/org/keycloak/crypto/def/test/BCEcdhEsAlgorithmProviderTest.java:127 test path KeyFactory keyFactory = KeyFactory.getInstance("EC");
  7. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSECDSACryptoProvider.java:86 KeyFactory keyFactory = KeyFactory.getInstance("EC");
  8. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSEcdhEsAlgorithmProvider.java:205 KeyFactory keyFactory = KeyFactory.getInstance("EC", "BCFIPS");
  9. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/BCFIPSEcdhEsAlgorithmProviderTest.java:104 test path KeyFactory keyFactory = KeyFactory.getInstance("EC", "BCFIPS");
  10. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/BCFIPSEcdhEsAlgorithmProviderTest.java:115 test path KeyFactory keyFactory = KeyFactory.getInstance("EC", "BCFIPS");
  11. services/src/main/java/org/keycloak/keys/AbstractGeneratedEcKeyProviderFactory.java:117 KeyFactory kf = KeyFactory.getInstance("EC");
  12. services/src/main/java/org/keycloak/keys/GeneratedEcdhKeyProvider.java:58 KeyFactory kf = KeyFactory.getInstance("EC");
  13. services/src/main/java/org/keycloak/keys/GeneratedEcdsaKeyProvider.java:58 KeyFactory kf = KeyFactory.getInstance("EC");
  14. tests/base/src/test/java/org/keycloak/tests/keys/GeneratedEcdhKeyProviderTest.java:311 test path KeyFactory kf = KeyFactory.getInstance("EC");
  15. tests/base/src/test/java/org/keycloak/tests/keys/GeneratedEcdsaKeyProviderTest.java:239 test path KeyFactory kf = KeyFactory.getInstance("EC");
java.keyfactory · CWE-327
ECDSA Quantum-vulnerable 15 places See details

Elliptic-curve cryptography through BouncyCastle

A BouncyCastle elliptic-curve class. `ECDHBasicAgreement` in particular is key establishment and carries harvest-now-decrypt-later exposure.

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 for signatures, ML-KEM-768 for key establishment.

  1. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:59 import org.bouncycastle.jce.ECNamedCurveTable;
  2. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:196 ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
  3. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:36 import org.bouncycastle.jce.ECNamedCurveTable;
  4. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:107 ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName);
  5. crypto/default/src/test/java/org/keycloak/crypto/def/test/BCEcdhEsAlgorithmProviderTest.java:44 test path import org.bouncycastle.jce.ECNamedCurveTable;
  6. crypto/default/src/test/java/org/keycloak/crypto/def/test/BCEcdhEsAlgorithmProviderTest.java:113 test path ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
  7. crypto/default/src/test/java/org/keycloak/crypto/def/test/BCEcdhEsAlgorithmProviderTest.java:124 test path ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
  8. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSEcdhEsAlgorithmProvider.java:53 import org.bouncycastle.asn1.x9.X9ECParameters;
  9. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSEcdhEsAlgorithmProvider.java:201 X9ECParameters ecParams = NISTNamedCurves.getByName(crv);
  10. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:60 import org.bouncycastle.asn1.x9.ECNamedCurveTable;
  11. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:61 import org.bouncycastle.asn1.x9.X9ECParameters;
  12. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:154 X9ECParameters params = ECNamedCurveTable.getByName(curveName);
  13. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/BCFIPSEcdhEsAlgorithmProviderTest.java:43 test path import org.bouncycastle.asn1.x9.X9ECParameters;
  14. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/BCFIPSEcdhEsAlgorithmProviderTest.java:100 test path X9ECParameters ecParams = NISTNamedCurves.getByName(crv);
  15. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/BCFIPSEcdhEsAlgorithmProviderTest.java:111 test path X9ECParameters ecParams = NISTNamedCurves.getByName(crv);
java.bouncycastle.ec · CWE-327
RSA2048-bit Quantum-vulnerable Recorded traffic 14 places See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

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. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronCertificateUtilsProviderTest.java:75 test path KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
  2. saml-core/src/test/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2SignatureTest.java:46 test path KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
  3. services/src/test/java/org/keycloak/procotol/docker/installation/DockerKeyIdentifierTest.java:27 test path final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
  4. services/src/test/java/org/keycloak/protocol/saml/SamlEncryptionTest.java:67 test path KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
  5. services/src/test/java/org/keycloak/protocol/saml/SamlProtocolTest.java:76 test path KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
  6. tests/base/src/test/java/org/keycloak/tests/broker/trust/TrustMaterialIdentityProviderTest.java:321 test path KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
  7. tests/base/src/test/java/org/keycloak/tests/oid4vc/OID4VCIssuerEndpointEncryptionTest.java:294 test path var keyGen = java.security.KeyPairGenerator.getInstance("RSA");
  8. tests/base/src/test/java/org/keycloak/tests/oid4vc/OID4VCIssuerTestBase.java:370 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
  9. tests/base/src/test/java/org/keycloak/tests/oid4vc/OID4VCIssuerTestBase.java:603 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
  10. tests/base/src/test/java/org/keycloak/tests/oid4vc/OID4VCProofTestUtils.java:151 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", BouncyIntegration.PROVIDER);
  11. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/credentialbuilder/CredentialBuilderTest.java:41 test path var kpg = java.security.KeyPairGenerator.getInstance("RSA");
  12. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/SdJwtCredentialSignerTest.java:460 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
  13. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCJwksClientRegistrationTest.java:185 test path KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
  14. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/RealmManager.java:82 test path KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
java.keypairgenerator · CWE-327
RSA Quantum-vulnerable Recorded traffic 13 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. testsuite/integration-arquillian/servers/auth-server/common/keystore/client.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  2. testsuite/integration-arquillian/servers/auth-server/common/keystore/ocsp/private/intermediate-ca.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  3. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-ca@localhost.key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  4. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user-obb@localhost.key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  5. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/certs/clients/test-user@localhost.key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  6. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/intermediate/private/intermediate.key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  7. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/newcerts/intermediate-ca-3.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  8. testsuite/integration-arquillian/servers/auth-server/common/pki/root/ca/private/ca.key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  9. testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/ocsp/private/intermediate-ca.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  10. testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/intermediate-ca-2.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  11. testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/intermediate-ca.key:1 test path -----BEGIN RSA PRIVATE KEY-----
  12. testsuite/integration-arquillian/tests/base/src/test/resources/keys/private2048.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  13. testsuite/integration-arquillian/tests/base/src/test/resources/keys/private4096.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
ECDH Quantum-vulnerable Recorded traffic 11 places See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

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. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. authz/client/src/test/java/org/keycloak/authorization/client/test/ECDSAAlgorithmTest.java:43 test path keyPair = KeyPairGenerator.getInstance("EC").genKeyPair();
  2. common/src/main/java/org/keycloak/common/util/KeyUtils.java:88 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  3. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:132 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  4. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:125 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  5. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSEcdhEsAlgorithmProvider.java:142 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BCFIPS");
  6. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/credentialbuilder/SdJwtCredentialBuilderTest.java:128 test path var holderKeyPair = KeyPairGenerator.getInstance("EC").generateKeyPair();
  7. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:140 test path KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  8. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:1089 test path KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  9. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:1340 test path KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
  10. tests/conformance/src/test/java/org/keycloak/tests/conformance/ConformanceSigningKey.java:129 test path KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("EC");
  11. tests/conformance/src/test/java/org/keycloak/tests/conformance/vci/VciTestSigningKey.java:68 test path KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("EC");
java.keypairgenerator · CWE-327
ECDSA256-bitsecg/secp256r1 Quantum-vulnerable 9 places See details

Public key declared as a JSON Web Key

A `kty` field, with the curve read from the sibling `crv` where the family needs one. A JWKS document declares a key without naming an algorithm anywhere, so it is invisible to a scan that only looks for `alg`.

This file publishes the public keys other systems use to check this system's signatures. Everyone who trusts these keys has to accept the new kind of key before the old ones can be retired.

What to do. A published JWKS is what relying parties trust. It has to accept a post-quantum key type before the keys behind it can change, so put it early in the migration order.

jose.jwk · CWE-327
RSA Quantum-vulnerable Recorded traffic 9 places See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

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. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. core/src/test/java/org/keycloak/RSAVerifierTest.java:64 test path badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  2. core/src/test/java/org/keycloak/RSAVerifierTest.java:65 test path idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  3. core/src/test/java/org/keycloak/RSAVerifierTest.java:91 test path KeyPair caKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  4. core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java:62 test path KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  5. core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java:82 test path KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  6. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/CRLDistributionPointTest.java:124 test path KeyPair keyPair = KeyPairGenerator.getInstance("RSA").genKeyPair();
  7. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronOCSPPoviderTest.java:62 test path KeyPair keyPair = KeyPairGenerator.getInstance("RSA").genKeyPair();
  8. tests/base/src/test/java/org/keycloak/tests/oauth/RefreshTokenTest.java:458 test path KeyPair rsaKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  9. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/credentialbuilder/JwtCredentialBuilderTest.java:125 test path var holderKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
java.keypairgenerator · CWE-327
RSA Quantum-vulnerable Recorded traffic 8 places See details

Classical key material handled through the JCA

`KeyFactory.getInstance()` for a classical algorithm. This indicates the code parses or produces keys of that family, which is a migration surface even where it does no cryptography itself.

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. Include this code path in the inventory: it has to accept post-quantum key encodings before the keys themselves can change.

  1. adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java:145 KeyFactory kf = KeyFactory.getInstance("RSA", CryptoConstants.BC_PROVIDER_ID);
  2. adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java:159 KeyFactory kf = KeyFactory.getInstance("RSA", CryptoConstants.BC_PROVIDER_ID);
  3. common/src/main/java/org/keycloak/common/util/KeyUtils.java:70 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  4. core/src/main/java/org/keycloak/jose/jwk/JWKParser.java:140 KeyFactory kf = KeyFactory.getInstance("RSA");
  5. saml-core-api/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RSAKeyValueType.java:103 KeyFactory rsaKeyFactory = KeyFactory.getInstance("rsa");
  6. saml-core-api/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RSAKeyValueType.java:122 KeyFactory rsaKeyFactory = KeyFactory.getInstance("rsa");
  7. tests/base/src/test/java/org/keycloak/tests/saml/AbstractSamlTest.java:70 test path KeyFactory kfRsa = KeyFactory.getInstance("RSA");
  8. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AbstractSamlTest.java:81 test path KeyFactory kfRsa = KeyFactory.getInstance("RSA");
java.keyfactory · CWE-327
ECDH256-bitsecg/secp256r1 Quantum-vulnerable Recorded traffic 7 places See details

Named elliptic curve requested

`ECGenParameterSpec` names a curve explicitly. Every standardised prime curve is broken by Shor regardless of its size, so a larger curve is not a mitigation.

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 for signatures, ML-KEM-768 for key establishment.

  1. core/src/test/java/org/keycloak/jose/jwk/JWKTest.java:190 test path ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
  2. core/src/test/java/org/keycloak/jose/jwk/JWKTest.java:205 test path ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
  3. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:141 test path keyGen.initialize(new ECGenParameterSpec("secp256r1"));
  4. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:1090 test path keyGen.initialize(new ECGenParameterSpec("secp256r1"));
  5. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:1341 test path keyGen.initialize(new ECGenParameterSpec("secp256r1"));
  6. tests/conformance/src/test/java/org/keycloak/tests/conformance/ConformanceSigningKey.java:130 test path keyGenerator.initialize(new ECGenParameterSpec("secp256r1"));
  7. tests/conformance/src/test/java/org/keycloak/tests/conformance/vci/VciTestSigningKey.java:69 test path keyGenerator.initialize(new ECGenParameterSpec("secp256r1"));
java.eccurve · CWE-327
ECDSA Quantum-vulnerable 3 places See details

JOSE algorithm declared in configuration

An `alg` value in JSON or YAML. `none` is reported as a critical defect; HS* is an HMAC and is not quantum-vulnerable; RS*, PS*, ES* and EdDSA are.

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. No standardised post-quantum JOSE algorithm exists yet. Keep token lifetimes short.

jose.algorithm · CWE-327
DSA Quantum-vulnerable 2 places See details

Classical key material handled through the JCA

`KeyFactory.getInstance()` for a classical algorithm. This indicates the code parses or produces keys of that family, which is a migration surface even where it does no cryptography itself.

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. Include this code path in the inventory: it has to accept post-quantum key encodings before the keys themselves can change.

  1. saml-core-api/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/DSAKeyValueType.java:211 KeyFactory dsaKeyFactory = KeyFactory.getInstance("dsa");
  2. saml-core-api/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/DSAKeyValueType.java:234 KeyFactory dsaKeyFactory = KeyFactory.getInstance("dsa");
java.keyfactory · CWE-327
ECDH Quantum-vulnerable Recorded traffic 2 places See details

Public key declared as a JSON Web Key

A `kty` field, with the curve read from the sibling `crv` where the family needs one. A JWKS document declares a key without naming an algorithm anywhere, so it is invisible to a scan that only looks for `alg`.

This file publishes the public keys other systems use to check this system's signatures. Everyone who trusts these keys has to accept the new kind of key before the old ones can be retired.

What to do. A published JWKS is what relying parties trust. It has to accept a post-quantum key type before the keys behind it can change, so put it early in the migration order.

jose.jwk · CWE-327
ECDH Quantum-vulnerable Recorded traffic 2 places See details

Classical key agreement through the JCA

`KeyAgreement.getInstance()` with ECDH, DH or XDH. Key agreement is the highest-priority class of finding: traffic recorded today is decrypted once the key exchange is 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. ML-KEM-768 (FIPS 203), or a hybrid X25519+ML-KEM-768 construction that keeps the classical guarantee while adding the quantum one.

  1. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:208 KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
  2. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:183 KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
java.keyagreement · CWE-327
EdDSA Quantum-vulnerable 2 places See details

Classical key material handled through the JCA

`KeyFactory.getInstance()` for a classical algorithm. This indicates the code parses or produces keys of that family, which is a migration surface even where it does no cryptography itself.

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. Include this code path in the inventory: it has to accept post-quantum key encodings before the keys themselves can change.

java.keyfactory · CWE-327
RSA2048-bit Quantum-vulnerable Recorded traffic 2 places See details

Public key file

A PEM public-key block. The algorithm is read from the SubjectPublicKeyInfo.

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. Inventory only; a public key is not itself a secret.

pem.public-key
RSA-PSS Quantum-vulnerable 2 places See details

Classical signature algorithm through the JCA

`Signature.getInstance()` with a classical algorithm. The digest and the key algorithm are split out of the JCA name, so `SHA1withRSA` reports both the broken digest and the quantum-vulnerable key.

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). Where the verifier cannot be changed, sign twice and publish both signatures.

  1. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:183 var signature = Signature.getInstance("RSASSA-PSS");
  2. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java:36 test path Signature signature = Signature.getInstance("RSASSA-PSS");
java.signature · CWE-327
ECDH256-bit Quantum-vulnerable Recorded traffic 1 place See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

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. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. tests/base/src/test/java/org/keycloak/tests/oid4vc/OID4VCProofTestUtils.java:132 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", BouncyIntegration.PROVIDER);
java.keypairgenerator · CWE-327
Ed25519255-bitother/Ed25519 Quantum-vulnerable 1 place See details

JOSE algorithm declared in configuration

An `alg` value in JSON or YAML. `none` is reported as a critical defect; HS* is an HMAC and is not quantum-vulnerable; RS*, PS*, ES* and EdDSA are.

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. No standardised post-quantum JOSE algorithm exists yet. Keep token lifetimes short.

jose.algorithm · CWE-327
RSA4096-bit 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. operator/src/test/resources/example-mtls-secret.yaml:41 test path -----BEGIN PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
RSA Quantum-vulnerable Recorded traffic 1 place See details

Public key declared as a JSON Web Key

A `kty` field, with the curve read from the sibling `crv` where the family needs one. A JWKS document declares a key without naming an algorithm anywhere, so it is invisible to a scan that only looks for `alg`.

This file publishes the public keys other systems use to check this system's signatures. Everyone who trusts these keys has to accept the new kind of key before the old ones can be retired.

What to do. A published JWKS is what relying parties trust. It has to accept a post-quantum key type before the keys behind it can change, so put it early in the migration order.

jose.jwk · CWE-327
RSA4096-bit Quantum-vulnerable Recorded traffic 1 place See details

Public key file

A PEM public-key block. The algorithm is read from the SubjectPublicKeyInfo.

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. Inventory only; a public key is not itself a secret.

pem.public-key
RSA-OAEP Quantum-vulnerable Recorded traffic 1 place See details

Classical public-key cipher through the JCA

`Cipher.getInstance()` with a transformation whose algorithm component is a public-key or legacy symmetric cipher. The transformation string is parsed into algorithm, mode and padding, so `RSA/ECB/PKCS1Padding` is separated from `RSA/ECB/OAEPWithSHA-256AndMGF1Padding`.

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. For RSA encryption, move to ML-KEM-768 and keep RSA-OAEP only as the classical half of a hybrid during transition.

  1. services/src/test/java/org/keycloak/protocol/saml/SamlEncryptionTest.java:91 test path cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
java.cipher · CWE-327
RSA-PSS Quantum-vulnerable 1 place See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

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. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java:28 test path KeyPair keyPair = KeyPairGenerator.getInstance("RSASSA-PSS").genKeyPair();
java.keypairgenerator · CWE-327
RSA-PSS Quantum-vulnerable 1 place See details

Classical key material handled through the JCA

`KeyFactory.getInstance()` for a classical algorithm. This indicates the code parses or produces keys of that family, which is a migration surface even where it does no cryptography itself.

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. Include this code path in the inventory: it has to accept post-quantum key encodings before the keys themselves can change.

  1. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java:34 test path key.setPrivateKey(KeyFactory.getInstance("RSASSA-PSS").generatePrivate(kspec));
java.keyfactory · CWE-327
RSASSA-PKCS1v15 Quantum-vulnerable 1 place See details

JOSE algorithm declared in configuration

An `alg` value in JSON or YAML. `none` is reported as a critical defect; HS* is an HMAC and is not quantum-vulnerable; RS*, PS*, ES* and EdDSA are.

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. No standardised post-quantum JOSE algorithm exists yet. Keep token lifetimes short.

jose.algorithm · CWE-327
AES Reduced margin 16 places See details

Key material constructed for a named algorithm

`new SecretKeySpec(bytes, "AES")` and the other key-spec constructors name the algorithm as an argument rather than through `getInstance()`. Code that wraps raw bytes into a key this way often never calls `getInstance()` at all, so the algorithm is invisible to a scan that only looks at the factories.

This wraps raw bytes into a key for a named algorithm. It is part of the same migration as whatever uses that key.

What to do. Wherever this key is used, the same migration applies as to the call that consumes it. Trace it to the operation and treat the two together.

  1. core/src/main/java/org/keycloak/jose/jwe/enc/AesCbcHmacShaEncryptionProvider.java:168 SecretKeySpec aesKey = new SecretKeySpec(cekAesKey, "AES");
  2. core/src/main/java/org/keycloak/jose/jwe/enc/AesGcmEncryptionProvider.java:151 SecretKeySpec aesKey = new SecretKeySpec(cekBytes, "AES");
  3. core/src/test/java/org/keycloak/jose/JWETest.java:66 test path SecretKey aesKey = new SecretKeySpec(AES_128_KEY, "AES");
  4. core/src/test/java/org/keycloak/jose/JWETest.java:76 test path final SecretKey aesKey = new SecretKeySpec(AES_256_KEY, "AES");
  5. core/src/test/java/org/keycloak/jose/JWETest.java:121 test path SecretKey aesKey = new SecretKeySpec(AES_128_KEY, "AES");
  6. core/src/test/java/org/keycloak/jose/JWETest.java:140 test path SecretKey aesKey = new SecretKeySpec(AES_128_KEY, "AES");
  7. core/src/test/java/org/keycloak/jose/JWETest.java:185 test path final SecretKey aesKey = new SecretKeySpec(AES_128_KEY, "AES");
  8. core/src/test/java/org/keycloak/jose/JWETest.java:208 test path final SecretKey aesKey = new SecretKeySpec(AES_256_KEY, "AES");
  9. core/src/test/java/org/keycloak/jose/JWETest.java:230 test path SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey, "AES");
  10. core/src/test/java/org/keycloak/jose/JWETest.java:307 test path final SecretKey aesKey = new SecretKeySpec(AES_128_KEY, "AES");
  11. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:80 cipher.init(Cipher.UNWRAP_MODE, new SecretKeySpec(derivedKey, "AES"));
  12. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:113 cipher.init(Cipher.WRAP_MODE, new SecretKeySpec(derivedKey, "AES"));
  13. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:115 return cipher.wrap(new SecretKeySpec(cekBytes, "AES"));
  14. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronCryptoJWETest.java:31 test path final SecretKey aesKey = new SecretKeySpec(AES_256_KEY, "AES");
  15. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlEncryptedAssertionTest.java:69 test path SecretKey secretKey = new SecretKeySpec(secret, "AES");
  16. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlEncryptedIdTest.java:55 test path SecretKey secretKey = new SecretKeySpec(secret, "AES");
java.keyspec · CWE-327
SHA-256 Reduced margin From a constant 15 places See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the 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.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. common/src/main/java/org/keycloak/common/util/KeyUtils.java:100 return Base64Url.encode(MessageDigest.getInstance(DEFAULT_MESSAGE_DIGEST).digest(key.getEncoded()));
  2. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronHmacTest.java:41 test path KeyGenerator keygen = KeyGenerator.getInstance("HmacSHA256");
  3. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java:33 test path SecretKeyFactory skFact = SecretKeyFactory.getInstance("HmacSHA256", BouncyIntegration.PROVIDER );
  4. operator/src/main/java/org/keycloak/operator/Utils.java:120 return MessageDigest.getInstance("SHA-256");
  5. server-spi-private/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java:138 md = MessageDigest.getInstance("SHA-256");
  6. services/src/main/java/org/keycloak/protocol/docker/DockerKeyIdentifier.java:37 final MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
  7. services/src/main/java/org/keycloak/protocol/oid4vc/issuance/signing/vcdm/Ed255192018Suite.java:121 MessageDigest md = MessageDigest.getInstance("SHA-256");
  8. services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA256PairwiseSubMapper.java:90 sha256 = MessageDigest.getInstance(HASH_ALGORITHM);
  9. services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/AbstractParEndpoint.java:88 hash = MessageDigest.getInstance("SHA-256").digest(inputData.getBytes(StandardCharsets.UTF_8));
  10. services/src/main/java/org/keycloak/services/clientpolicy/executor/PKCEEnforcerExecutor.java:230 MessageDigest md = MessageDigest.getInstance("SHA-256");
  11. services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java:271 md = MessageDigest.getInstance("SHA-256");
  12. services/src/main/java/org/keycloak/services/util/MtlsHoKTokenUtil.java:139 MessageDigest md = MessageDigest.getInstance(DIGEST_ALG);
  13. services/src/main/java/org/keycloak/utils/BrokerUtil.java:44 MessageDigest md = MessageDigest.getInstance("SHA-256");
  14. testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/MutualTLSUtils.java:143 test path MessageDigest md = MessageDigest.getInstance(digestAlg);
  15. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthProofKeyForCodeExchangeTest.java:403 test path MessageDigest md = MessageDigest.getInstance("SHA-256");
java.messagedigest · CWE-328
Kerberos Reduced margin 8 places See details

Kerberos or SPNEGO authentication

`javax.security.auth.kerberos` or a GSS-API call. Kerberos itself is symmetric and survives Shor; its PKINIT certificate flow is public-key and does not. The encryption types configured for the realm decide whether it is also a present-day concern.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the margin. Kerberos is symmetric at its core, so Shor does not break it. The surrounding PKINIT certificate flow is public-key and does fall.

What to do. Restrict the realm to AES encryption types, and treat PKINIT certificates as part of the public-key migration.

java.kerberos
AES Reduced margin 6 places See details

Classical public-key cipher through the JCA

`Cipher.getInstance()` with a transformation whose algorithm component is a public-key or legacy symmetric cipher. The transformation string is parsed into algorithm, mode and padding, so `RSA/ECB/PKCS1Padding` is separated from `RSA/ECB/OAEPWithSHA-256AndMGF1Padding`.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the 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.

What to do. For RSA encryption, move to ML-KEM-768 and keep RSA-OAEP only as the classical half of a hybrid during transition.

  1. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:142 return Cipher.getInstance("AES/CBC/PKCS7Padding", BouncyIntegration.PROVIDER);
  2. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:147 return Cipher.getInstance("AES/GCM/NoPadding", BouncyIntegration.PROVIDER);
  3. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:142 return Cipher.getInstance("AES/CBC/PKCS5Padding");
  4. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:147 return Cipher.getInstance("AES/GCM/NoPadding");
  5. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:207 return Cipher.getInstance("AES/CBC/PKCS7Padding", BouncyIntegration.PROVIDER);
  6. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:212 return Cipher.getInstance("AES/GCM/NoPadding", BouncyIntegration.PROVIDER);
java.cipher · CWE-327
PBKDF2 Reduced margin 2 places See details

Key material constructed for a named algorithm

`new SecretKeySpec(bytes, "AES")` and the other key-spec constructors name the algorithm as an argument rather than through `getInstance()`. Code that wraps raw bytes into a key this way often never calls `getInstance()` at all, so the algorithm is invisible to a scan that only looks at the factories.

This wraps raw bytes into a key for a named algorithm. It is part of the same migration as whatever uses that key.

What to do. Wherever this key is used, the same migration applies as to the call that consumes it. Trace it to the operation and treat the two together.

  1. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java:114 KeySpec spec = new PBEKeySpec(rawPasswordWithPadding.toCharArray(), salt, iterations, derivedKeySize);
  2. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:413 test path KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
java.keyspec · CWE-327
PBKDF2 Reduced margin 17 places See details

Password hashing or key derivation

A `SecretKeyFactory` for PBKDF2, or a BouncyCastle password KDF. 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. PBKDF2 needs a high iteration count. Argon2 through BouncyCastle is stronger.

  1. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProviderFactory.java:37 public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
  2. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProviderFactory.java:52 return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, DEFAULT_ITERATIONS, getMaxPaddingLength());
  3. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2Sha256PasswordHashProviderFactory.java:14 public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
  4. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2Sha256PasswordHashProviderFactory.java:23 return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, DEFAULT_ITERATIONS, getMaxPaddingLength(), 256);
  5. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2Sha512PasswordHashProviderFactory.java:14 public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA512";
  6. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2Sha512PasswordHashProviderFactory.java:23 return new Pbkdf2PasswordHashProvider(ID, PBKDF2_ALGORITHM, DEFAULT_ITERATIONS, getMaxPaddingLength());
  7. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:110 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA256", 1);
  8. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:121 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA1", 1);
  9. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:135 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA256", 1);
  10. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:156 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA1", 1);
  11. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:205 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA512", 2);
  12. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:283 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA1", Pbkdf2PasswordHashProviderFactory.DEFAULT_ITERATIONS);
  13. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:329 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA512", Pbkdf2Sha512PasswordHashProviderFactory.DEFAULT_ITERATIONS);
  14. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:340 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA256", Pbkdf2Sha256PasswordHashProviderFactory.DEFAULT_ITERATIONS);
  15. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:350 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA512", Pbkdf2Sha512PasswordHashProviderFactory.DEFAULT_ITERATIONS);
  16. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:364 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA256", Pbkdf2Sha256PasswordHashProviderFactory.DEFAULT_ITERATIONS);
  17. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:372 test path assertEncoded(credential, password, credential.getPasswordSecretData().getSalt(), "PBKDF2WithHmacSHA256", Pbkdf2Sha256PasswordHashProviderFactory.DEFAULT_ITERATIONS, false);
java.kdf
unknown Could not be determined 22 places See details

Key pair algorithm chosen at runtime

`KeyPairGenerator.getInstance(x)` where the argument is an identifier. The algorithm cannot be resolved without running the program, so this is reported as an unknown rather than assumed to be classical.

This code picks its encryption method while it runs, so a scan cannot tell which one it ends up using. Somebody has to check the configuration.

What to do. Trace the value to its configuration source and record the concrete algorithm in the cryptographic inventory by hand.

  1. common/src/main/java/org/keycloak/common/util/KeyUtils.java:79 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(curveName);
  2. core/src/main/java/org/keycloak/jose/jwk/AKPUtils.java:32 KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
  3. core/src/main/java/org/keycloak/jose/jwk/EdECUtilsImpl.java:108 publicKey = KeyFactory.getInstance(crv).generatePublic(keySpec);
  4. core/src/test/java/org/keycloak/jose/jwk/AKPJWKTest.java:80 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
  5. core/src/test/java/org/keycloak/jose/jwk/JWKTest.java:285 test path Signature signature = Signature.getInstance(javaAlgorithm);
  6. core/src/test/java/org/keycloak/jose/jwk/JWKTest.java:292 test path Signature verifier = Signature.getInstance(javaAlgorithm);
  7. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:130 return KeyPairGenerator.getInstance(algorithm, BouncyIntegration.PROVIDER);
  8. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java:136 return KeyFactory.getInstance(algorithm, BouncyIntegration.PROVIDER);
  9. crypto/default/src/main/java/org/keycloak/crypto/def/DefaultRsaKeyEncryptionJWEAlgorithmProvider.java:36 return Cipher.getInstance(jcaAlgorithmName);
  10. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronRsaKeyEncryptionJWEAlgorithmProvider.java:55 return Cipher.getInstance(jcaAlgorithmName);
  11. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:127 return KeyPairGenerator.getInstance(algorithm);
  12. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:137 return KeyFactory.getInstance(algorithm);
  13. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/WildFlyElytronProvider.java:199 return Signature.getInstance(javaAlgorithm);
  14. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:197 return KeyPairGenerator.getInstance(algorithm, BouncyIntegration.PROVIDER);
  15. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:202 return KeyFactory.getInstance(algorithm , BouncyIntegration.PROVIDER);
  16. saml-core/src/main/java/org/keycloak/saml/SignatureAlgorithm.java:87 return Signature.getInstance(javaSignatureAlgorithm);
  17. saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java:212 sig = Signature.getInstance(PicketLinkFederationConstants.DSA_SIGNATURE_ALGORITHM);
  18. saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java:214 sig = Signature.getInstance(PicketLinkFederationConstants.RSA_SIGNATURE_ALGORITHM);
  19. services/src/test/java/org/keycloak/jose/jwk/ServerJWKTest.java:112 test path Signature signature = Signature.getInstance(javaAlgorithm);
  20. services/src/test/java/org/keycloak/jose/jwk/ServerJWKTest.java:119 test path Signature verifier = Signature.getInstance(javaAlgorithm);
  21. tests/base/src/test/java/org/keycloak/tests/oid4vc/presentation/OID4VPVerifierTestBase.java:104 test path KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyType.EC);
  22. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/LogoutTokenUtil.java:46 test path Signature signature = Signature.getInstance(JavaAlgorithm.RS256);
java.keypairgenerator.variable · CWE-327
unknown Could not be determined 5 places See details

Key store holding classical key material

`KeyStore.getInstance("JKS"|"PKCS12"|"BCFKS")`. The store format itself is not the issue; it is the inventory point where the classical private keys of this application live.

This is the application's key cupboard. It is worth knowing what is in it before planning any replacement.

What to do. Record which keys this store holds. A key store is where a migration either happens or silently does not.

java.keystore
unknown Could not be determined 3 places See details

Non-cryptographic randomness near key material

`new Random()` or `Math.random()` in a file that also imports `java.security`, `javax.crypto` or BouncyCastle. `java.util.Random` is a linear congruential generator and its output is predictable from a handful of samples. The import check is what keeps this from firing on every retry jitter and test fixture in the tree.

Part of this code uses a predictable source of random numbers. If any key comes from it, that key can be guessed today, with no quantum computer needed.

What to do. `java.security.SecureRandom`. This is a classical defect, not a quantum one, and it is worth fixing first.

java.random.insecure · CWE-338
unknown Could not be determined 1 place See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

pem.certificate
unknown Could not be determined 1 place See details

Key material constructed for a named algorithm

`new SecretKeySpec(bytes, "AES")` and the other key-spec constructors name the algorithm as an argument rather than through `getInstance()`. Code that wraps raw bytes into a key this way often never calls `getInstance()` at all, so the algorithm is invisible to a scan that only looks at the factories.

This wraps raw bytes into a key for a named algorithm. It is part of the same migration as whatever uses that key.

What to do. Wherever this key is used, the same migration applies as to the call that consumes it. Trace it to the operation and treat the two together.

  1. server-spi/src/main/java/org/keycloak/models/utils/HmacOTP.java:161 SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
java.keyspec · CWE-327
unknown Could not be determined 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.

pem.private-key · CWE-321, CWE-327
unknown Could not be determined 8 places 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. adapters/saml/core/pom.xml:66 <artifactId>bcprov-jdk18on</artifactId>
  2. adapters/spi/adapter-spi/pom.xml:41 <artifactId>bcprov-jdk18on</artifactId>
  3. adapters/spi/jboss-adapter-core/pom.xml:58 <artifactId>bcprov-jdk18on</artifactId>
  4. crypto/default/pom.xml:59 <artifactId>bcprov-jdk18on</artifactId>
  5. dependencies/server-min/pom.xml:44 <artifactId>bcprov-jdk18on</artifactId>
  6. integration/client-cli/client-cli-dist/pom.xml:59 <artifactId>bcprov-jdk18on</artifactId>
  7. testsuite/integration-arquillian/tests/pom.xml:1645 test path <artifactId>bcprov-jdk18on</artifactId>
  8. testsuite/utils/pom.xml:48 test path <artifactId>bcprov-jdk18on</artifactId>
dep.crypto-library
CSPRNG Quantum-safe 36 places See details

Random number generation

`SecureRandom`. A platform CSPRNG is not a quantum exposure; it is recorded because an inventory that omits the randomness source is incomplete. `SHA1PRNG` is named explicitly where it appears, since it is a legacy algorithm even though its output is adequate.

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

What to do. No action. Prefer the platform default over naming an algorithm.

  1. adapters/saml/core/src/main/java/org/keycloak/adapters/cloned/HttpClientBuilder.java:265 new SecureRandom());
  2. common/src/main/java/org/keycloak/common/util/KeyUtils.java:89 SecureRandom randomGen = new SecureRandom();
  3. common/src/main/java/org/keycloak/common/util/SecretGenerator.java:34 private static final SecureRandom SECURE_RANDOM = new SecureRandom();
  4. core/src/main/java/org/keycloak/jose/jwe/JWEUtils.java:32 new SecureRandom().nextBytes(buf);
  5. core/src/main/java/org/keycloak/sdjwt/SdJwtUtils.java:43 private static final SecureRandom RANDOM = new SecureRandom();
  6. core/src/test/java/org/keycloak/jose/jwk/JWKTest.java:141 test path SecureRandom randomGen = new SecureRandom();
  7. crypto/default/src/main/java/org/keycloak/crypto/def/BCCertificateUtilsProvider.java:97 SecureRandom random = new SecureRandom();
  8. crypto/default/src/main/java/org/keycloak/crypto/def/BCEcdhEsAlgorithmProvider.java:133 SecureRandom randomGen = new SecureRandom();
  9. crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultSecureRandomTest.java:36 test path SecureRandom sc1 = new SecureRandom();
  10. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronCertificateUtilsProvider.java:99 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
  11. crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronEcdhEsAlgorithmProvider.java:126 SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
  12. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronHmacTest.java:42 test path SecureRandom random = isWindows() ? SecureRandom.getInstance("Windows-PRNG") : SecureRandom.getInstance("NativePRNG");
  13. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSecureRandomTest.java:43 test path SecureRandom sc1 = new SecureRandom();
  14. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSCertificateUtilsProvider.java:98 SecureRandom random = new SecureRandom();
  15. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/BCFIPSEcdhEsAlgorithmProvider.java:143 SecureRandom randomGen = SecureRandom.getInstance("DEFAULT", "BCFIPS");
  16. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java:347 SecureRandom secRandom = new SecureRandom();
  17. crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPSRsaKeyEncryptionJWEAlgorithmProvider.java:41 .withSecureRandom(SecureRandom.getInstance("DEFAULT"));
  18. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402SecureRandomTest.java:40 test path SecureRandom sc1 = new SecureRandom();
  19. federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/HardcodedLDAPAttributeMapper.java:94 SecureRandom r = new SecureRandom();
  20. model/infinispan/src/main/java/org/keycloak/connections/infinispan/TopologyInfo.java:85 return InfinispanConnectionProvider.NODE_PREFIX + new SecureRandom().nextInt(1000000);
  21. model/jpa/src/main/java/org/keycloak/models/jpa/MigrationModelAdapter.java:90 sb.append(RESOURCE_TAG_CHARSET[new SecureRandom().nextInt(RESOURCE_TAG_CHARSET.length)]);
  22. operator/src/test/java/org/keycloak/operator/testsuite/utils/TrustAllSSLContext.java:49 test path sslContext.init(null, trustAllCerts, new SecureRandom());
  23. saml-core/src/main/java/org/keycloak/saml/RandomSecret.java:37 SecureRandom random = new SecureRandom();
  24. server-spi-private/src/main/java/org/keycloak/credential/hash/Pbkdf2PasswordHashProvider.java:128 SecureRandom secureRandom = new SecureRandom();
  25. server-spi-private/src/main/java/org/keycloak/credential/hash/Salt.java:8 SecureRandom secureRandom = new SecureRandom();
  26. server-spi/src/main/java/org/keycloak/models/utils/HmacOTP.java:51 SecureRandom r = new SecureRandom();
  27. services/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java:273 new SecureRandom());
  28. services/src/main/java/org/keycloak/protocol/docker/installation/compose/DockerComposeCertsDirectory.java:30 keyGen.initialize(2048, new SecureRandom());
  29. services/src/main/java/org/keycloak/protocol/saml/DefaultSamlArtifactResolver.java:104 SecureRandom handleGenerator = new SecureRandom();
  30. services/src/test/java/org/keycloak/procotol/docker/installation/DockerComposeYamlInstallationProviderTest.java:56 test path keyGen.initialize(2048, new SecureRandom());
  31. services/src/test/java/org/keycloak/procotol/docker/installation/DockerKeyIdentifierTest.java:28 test path keyGen.initialize(2048, new SecureRandom());
  32. test-framework/core/src/main/java/org/keycloak/testframework/server/DistributionKeycloakServer.java:264 test path sslContext.init(null, new TrustManager[] { new NullTrustManager() }, new SecureRandom());
  33. tests/base/src/test/java/org/keycloak/tests/oid4vc/issuance/signing/OID4VCKeyAttestationTest.java:113 test path private static final SecureRandom RANDOM = new SecureRandom();
  34. tests/conformance/src/test/java/org/keycloak/tests/conformance/ConformanceSigningKey.java:75 test path private static final SecureRandom RANDOM = new SecureRandom();
  35. tests/conformance/src/test/java/org/keycloak/tests/conformance/vci/VciTestSigningKey.java:60 test path private static final SecureRandom RANDOM = new SecureRandom();
  36. util/embedded-ldap/src/main/java/org/keycloak/util/ldap/TLS13StartTlsHandler.java:72 new SecureRandom());
java.rng
HMAC Quantum-safe 13 places See details

Key material constructed for a named algorithm

`new SecretKeySpec(bytes, "AES")` and the other key-spec constructors name the algorithm as an argument rather than through `getInstance()`. Code that wraps raw bytes into a key this way often never calls `getInstance()` at all, so the algorithm is invisible to a scan that only looks at the factories.

This wraps raw bytes into a key for a named algorithm. It is part of the same migration as whatever uses that key.

What to do. Wherever this key is used, the same migration applies as to the call that consumes it. Trace it to the operation and treat the two together.

  1. common/src/test/java/org/keycloak/common/util/KeyUtilsTest.java:18 test path SecretKeySpec expected = new SecretKeySpec(secretBytes, "HmacSHA256");
  2. core/src/main/java/org/keycloak/jose/jwe/enc/AesCbcHmacShaEncryptionProvider.java:169 SecretKeySpec hmacKey = new SecretKeySpec(cekMacKey, "HMACSHA2");
  3. core/src/test/java/org/keycloak/jose/HmacTest.java:47 test path SecretKey secretKey = new SecretKeySpec(UUID.randomUUID().toString().getBytes(), "HmacSHA256");
  4. core/src/test/java/org/keycloak/jose/HmacTest.java:53 test path SecretKey secretKey = new SecretKeySpec("secret".getBytes(), "HmacSHA256");
  5. core/src/test/java/org/keycloak/jose/JWETest.java:67 test path SecretKey hmacKey = new SecretKeySpec(HMAC_SHA256_KEY, "HMACSHA2");
  6. core/src/test/java/org/keycloak/jose/JWETest.java:77 test path final SecretKey hmacKey = new SecretKeySpec(HMAC_SHA512_KEY, "HMACSHA2");
  7. core/src/test/java/org/keycloak/jose/JWETest.java:122 test path SecretKey hmacKey = new SecretKeySpec(HMAC_SHA256_KEY, "HMACSHA2");
  8. core/src/test/java/org/keycloak/jose/JWETest.java:186 test path final SecretKey hmacKey = new SecretKeySpec(HMAC_SHA256_KEY, "HMACSHA2");
  9. core/src/test/java/org/keycloak/jose/JWETest.java:209 test path final SecretKey hmacKey = new SecretKeySpec(HMAC_SHA512_KEY, "HMACSHA2");
  10. core/src/test/java/org/keycloak/jose/JWETest.java:308 test path final SecretKey hmacKey = new SecretKeySpec(HMAC_SHA256_KEY, "HMACSHA2");
  11. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronCryptoJWETest.java:32 test path final SecretKey hmacKey = new SecretKeySpec(HMAC_SHA512_KEY, "HMACSHA2");
  12. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java:34 test path SecretKey secretKey = skFact.generateSecret(new SecretKeySpec(UUID.randomUUID().toString().getBytes(), "HmacSHA256"));
  13. server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java:228 return secret != null ? new SecretKeySpec(secret.getBytes(), "HmacSHA256") : null;
java.keyspec · CWE-327
CSPRNG Quantum-safe 6 places See details

Random number generation

`crypto.randomBytes()`, `randomUUID()` or `getRandomValues()`. A platform CSPRNG is not a quantum exposure; it is recorded because an inventory that omits the randomness source is incomplete. `Math.random()` is a separate, present-day defect.

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

What to do. No action.

  1. js/apps/account-ui/test/support/testbed.ts:16 test path realm: crypto.randomUUID(),
  2. js/apps/admin-ui/src/components/dynamic/ClaimDisplayComponent.tsx:29 const generateId = () => crypto.randomUUID();
  3. js/apps/admin-ui/test/clients/authorization.spec.ts:45 test path const clientId = `client-authentication-${crypto.randomUUID()}`;
  4. js/apps/admin-ui/test/realm-settings/events.spec.ts:21 test path const realmName = `events-realm-settings-${crypto.randomUUID()}`;
  5. js/apps/admin-ui/test/support/testbed.ts:12 test path crypto.randomUUID(),
  6. js/themes-vendor/src/main/js/web-crypto-shim.js:44 crypto.getRandomValues(arr);
js.rng
Argon2 Quantum-safe 4 places See details

Password hashing or key derivation

A `SecretKeyFactory` for PBKDF2, or a BouncyCastle password KDF. 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. PBKDF2 needs a high iteration count. Argon2 through BouncyCastle is stronger.

  1. crypto/default/src/main/java/org/keycloak/crypto/hash/Argon2PasswordHashProvider.java:19 import org.bouncycastle.crypto.generators.Argon2BytesGenerator;
  2. crypto/default/src/main/java/org/keycloak/crypto/hash/Argon2PasswordHashProvider.java:124 Argon2BytesGenerator generator = new Argon2BytesGenerator();
  3. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:65 test path import org.bouncycastle.crypto.generators.Argon2BytesGenerator;
  4. testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PasswordHashingTest.java:428 test path Argon2BytesGenerator generator = new Argon2BytesGenerator();
java.kdf
HMAC Quantum-safe 2 places See details

Classical public-key cipher through the JCA

`Cipher.getInstance()` with a transformation whose algorithm component is a public-key or legacy symmetric cipher. The transformation string is parsed into algorithm, mode and padding, so `RSA/ECB/PKCS1Padding` is separated from `RSA/ECB/OAEPWithSHA-256AndMGF1Padding`.

No known quantum attack changes how strong this is. A keyed MAC is not affected by Shor and only marginally by Grover.

What to do. For RSA encryption, move to ML-KEM-768 and keep RSA-OAEP only as the classical half of a hybrid during transition.

  1. crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronHmacTest.java:41 test path KeyGenerator keygen = KeyGenerator.getInstance("HmacSHA256");
  2. crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java:33 test path SecretKeyFactory skFact = SecretKeyFactory.getInstance("HmacSHA256", BouncyIntegration.PROVIDER );
java.cipher · CWE-327
HMAC Quantum-safe 1 place See details

JOSE algorithm declared in configuration

An `alg` value in JSON or YAML. `none` is reported as a critical defect; HS* is an HMAC and is not quantum-vulnerable; RS*, PS*, ES* and EdDSA are.

No known quantum attack changes how strong this is. A keyed MAC is not affected by Shor and only marginally by Grover.

What to do. No standardised post-quantum JOSE algorithm exists yet. Keep token lifetimes short.

jose.algorithm · CWE-327

Cryptographic assets

Algorithm Assessment What it means Occurrences
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. 501
RSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 129
TLS Quantum-vulnerable Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls. 74
CSPRNG Quantum-safe A cryptographically secure random number generator provided by the platform. Not weakened by a quantum computer. 42
ECDH Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 38
ECDSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 27
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. 22
PBKDF2 Reduced margin Not broken by a quantum computer, but weak against modern GPU cracking at low iteration counts, which is a present-day concern. 19
Kerberos Reduced margin Kerberos is symmetric at its core, so Shor does not break it. The surrounding PKINIT certificate flow is public-key and does fall. 18
HMAC Quantum-safe A keyed MAC is not affected by Shor and only marginally by Grover. 16
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. 16
Argon2 Quantum-safe The current recommended password hashing function. Not affected by Shor, and memory-hard against Grover. 4
RSA-PSS Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 4
SHA-1 Already broken SHAttered and subsequent work produced practical collisions; NIST withdrew SHA-1 in 2030 guidance and it is already unacceptable for signatures. 3
DSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 2
EdDSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 2
RSAES-PKCS1v15 Already broken PKCS#1 v1.5 encryption padding is vulnerable to Bleichenbacher oracles today, and the underlying RSA is broken by Shor. 2
MD5 Already broken Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest. 1
Ed25519 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1
RSA-OAEP Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1
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. 1

Imported cryptographic libraries

Library Files
javax.net.ssl the TLS client and server 55
org.bouncycastle BouncyCastle, whose low-level API bypasses the JCA algorithm strings. It has shipped ML-KEM and ML-DSA since 1.79 38
org.ietf.jgss GSS-API, usually Kerberos or SPNEGO 7
@noble/hashes hash functions 1
java.security the JCA 432