Search code examples
javajakarta-eewildflybouncycastlefido-u2f

Wildfly 10 BouncyCastleCrypto ECDSA key spec not recognized


I am adding support for FIDO U2F to my J2EE application (which is basicaly securing login with hardware token). I am using library from yubico, u2flib-server-core, which handles cryptographic operations in protocol using BouncyCastleCrypto. Hovewer, while decoding public key from persistent storage I keep getting exception with message

"key spec not recognized"

I have narrowed problem down to this function from library

public PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2fBadInputException {
        try {
            X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
            ECPoint point;
            try {
                point = curve.getCurve().decodePoint(encodedPublicKey);
            } catch (RuntimeException e) {
                throw new U2fBadInputException("Could not parse user public key", e);
            }

            return KeyFactory.getInstance("ECDSA").generatePublic(
                    new ECPublicKeySpec(point,
                            new ECParameterSpec(
                                    curve.getCurve(),
                                    curve.getG(),
                                    curve.getN(),
                                    curve.getH()
                            )
                    )
            );
        } catch (GeneralSecurityException e) { //This should not happen
            throw new RuntimeException(e);
        }
    }

Method generatePublic throws exception which is caught and rethrown as RuntimeException.

I have verified that KeyFactory.getInstance returns KeyFactory, from BC provider. Running this code outside Wildfly works perfectly. (I had to put bcprov-ext-jdk15on-154.jar into /lib/ext of java).

I have already tried updating wildfly's module for bouncycastle, currently I have added all 6 jars published on http://www.bouncycastle.org/latest_releases.html

Interesting part from stack trace is

java.security.spec.InvalidKeySpecException: key spec not recognised
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at com.yubico.u2f.crypto.BouncyCastleCrypto.decodePublicKey(BouncyCastleCrypto.java:60)
    at com.yubico.u2f.data.messages.key.RawAuthenticateResponse.checkSignature(RawAuthenticateResponse.java:64)
    at com.yubico.u2f.U2fPrimitives.finishAuthentication(U2fPrimitives.java:153)
    at com.yubico.u2f.U2F.finishAuthentication(U2F.java:116)
    at com.yubico.u2f.U2F.finishAuthentication(U2F.java:90)

Hope someone can help me :-) Thanks in advance

EDIT: I have tried that code with other modes and look like not event single one gets recognized. Using EC The excpetion is different because it uses other provider, however configuring providers list that BC is on the top yelds still same exception as I mentioned.

EDIT I think it might be a some sort of classloading issue so i turned verbose logging on and here is interesting Logs

[Loaded org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$ECDSA from file:/home/martin/java/jdk1.8.0_45/jre/lib/ext/bcprov-jdk15on-154.jar]
[Loaded org.bouncycastle.jce.spec.ECKeySpec from jar:file:/opt/wildfly-10.0.0.Final/modules/system/layers/base/org/bouncycastle/main/bcprov-jdk15on-1.52.jar!/]

KeyFactorySpi and ECKeySpec are comming from two different jars (classloaders?) hence the instanceof used in KeyFactory fails


Solution

  • Finally found issue :-)

    When I turned on verbose logging of classloaders i found that KeySpec is comming from different classloader as KeyFactorySpi which checked instanceof that KeySpec. It's problem that I have caused during solving this issue. As wildfly 10 is shipped with BouncyCastle module, on which RestEasy depends, it gets loaded. Hovever library that I have used also shipped some BouncyCastle classes.

    All i had to do was create jboss-deployment-structure.xml with following contents

    <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
        <deployment>
            <dependencies>
                <module name="org.bouncycastle" />
            </dependencies>
        </deployment>
    </jboss-deployment-structure>
    

    This allowed me to use wildfly's module for BouncyCastle. Hovewer, when I have done this I have already tried to put BouncyCastle in lib/ext/ of JRE that I have used to run server with. This caused exact same error with another cause :-)

    So to sum up, when using BouncyCastle with wildfly 10 you have to ensure following:

    1. Create jboss-deployment-structure.xml with dependency on Wildfly's module }or alternatively, you can use MANIFEST.mf to do this|
    2. Ensure that you don't have BouncyCastle provider in lib/ext/ of JRE you are using
    3. If you add BouncyCastle JCE provider dynamicaly, you also have to use JCE Unlimited policy files (if you legally can of course)

    Hope this helps someone in the future :-)