line / line-fido2-server

FIDO2(WebAuthn) server officially certified by FIDO Alliance and Relying Party examples.
Apache License 2.0
515 stars 94 forks source link

EdDSA authentication not functioning due to UserKeyServiceImpl convert function #4

Closed gmulhearn closed 2 years ago

gmulhearn commented 2 years ago

the convert function in UserKeyServiceImpl does not handle the EdDSA case. It only handles RSA and ECDSA, this can be seen below:

try {
            if (algorithm.isRSAAlgorithm()) {
                keyFactory = KeyFactory.getInstance("RSA");
            } else {
                keyFactory = KeyFactory.getInstance("ECDSA");
            }
            publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw FIDO2ServerRuntimeException.makeCryptoError(e);
}

Because of this, when the x509 encoded EdDSA algo key spec is input into the keyFactor.generatePublic method, an InvalidKeySpecException is thrown because the keyFactory assumed it was a ECDSA instance. This means that, from what I've seen, all EdDSA algo keys are unable to authenticate...

I have asserted this is an issue with the RP and not the authenticator, because I tested if this error is thrown on an official YubiKey authenticator. To do that, I injected some javascript into my browser such that the pubKeyCredParams passed into navigator.credentials.create(..) only included the -8 algorithm (i.e. force the YubiKey to use EdDSA). This results in a successful registration with the server using -8, however on authentication the InvalidKeySpecException is thrown.

I believe the fix to this is just to handle the isEDDSAAlgorithm() case with a KeyFactory instance of "EdDSA". My MR shows this fix and I have confirmed it to work on a custom authenticator running locally where it previously did not. Fix:

try {
            if (algorithm.isRSAAlgorithm()) {
                keyFactory = KeyFactory.getInstance("RSA");
            } else if (algorithm.isEdDSAAlgorithm()) {
                keyFactory = KeyFactory.getInstance("EdDSA");
            } else {
                keyFactory = KeyFactory.getInstance("ECDSA");
            }
            publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw FIDO2ServerRuntimeException.makeCryptoError(e);
}