0

When running my keycloak application, the following error appears:

java.security.NoSuchAlgorithmException: ECDSA KeyFactory not available
    at java.base/java.security.KeyFactory.<init>(KeyFactory.java:138) ~[na:na]
    at java.base/java.security.KeyFactory.getInstance(KeyFactory.java:183) ~[na:na]
    at org.keycloak.jose.jwk.JWKParser.createECPublicKey(JWKParser.java:107) ~[keycloak-core-15.0.2.jar:15.0.2]
    ... 61 common frames omitted

After doing some digging, found out KeyFactory cannot settle "ECDSA" as an algorithm and therefore I should use the "EC" algorithm to generate public key.

But if KeyFactory doesnt support "ECDSA" as an algorithm, why does Keycloak-15.0.2 JWKParser class' createECPublicKey func remain trying to generate a public key with ECDSA?

try {
            ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
            ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
            ECPoint point = new ECPoint(x, y);
            ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);

            KeyFactory kf = KeyFactory.getInstance("ECDSA");
            return kf.generatePublic(pubKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

Is this a bug? or am I juts completely missing something?

Ryuu
  • 69
  • 1
  • 9
  • What Java runtime (exact version, distributor and OS) do you use? Older OpenJDK versions (e.g. OpenJDK 8) on Linux are known to have problems with ECDSA. – Robert Jan 18 '22 at 08:17
  • I'm using openJDK 11.0.3 – Ryuu Jan 19 '22 at 05:41

1 Answers1

2

Your main problem is that you forgot to tell KeyFactory.getInstance that ECDSA is from BouncyCastle provider.

You add this, KeyFactory.getInstance("ECDSA"); will work:

public static final Provider BC = new BouncyCastleProvider();

...

public static void myMethod() {
    ...
    KeyFactory kf = KeyFactory.getInstance("ECDSA", BC);
}

Alternatively you can add BouncyCastleProvider to your list of providers:

Security.addProvider(new BouncyCastleProvider());
Robert
  • 39,162
  • 17
  • 99
  • 152
  • the line where '''KeyFactory kf = KeyFactory.getInstance("ECDSA")''' is stated is not from my method, but rather from JWKParser.class included in the Keycloak package that calls the createECPublickey() when an access request comes from a client, therefore I have no way of passing the BC object and editing the line in a way that tells Keyfactory to get the ECDSA from BC, nor can I add a line to add a provider. – Ryuu Jan 20 '22 at 04:33
  • @Ryuu Then open an issue in Keycloak project on this bug. Meanwhile you can use the workaround to manually add BouncyCastle to the whole JRE. Add `security.provider.N = org.bouncycastle.jce.provider.BouncyCastleProvider` to the file `java.security` file in your JRE. This is not a recommended way to use BouncyCastle but at least it works. – Robert Jan 20 '22 at 08:04