Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract DER-encoded public key from RegistrationResult/AssertionResult? #288

Open
iaik-jheher opened this issue May 30, 2023 · 2 comments
Open

Comments

@iaik-jheher
Copy link
Contributor

iaik-jheher commented May 30, 2023

We have a business requirement to submit credential public keys to a third-party library for accreditation. This library only accepts Java PublicKey implementations (and expects them to return DER-encoded byte arrays from getEncoded()).

Internally, java-webauthn-server presumably already has to parse the COSE-encoded public key; would it be possible to expose this in a more "common" standard form, such as DER-encoded bytes?

(I am trying to avoid implementing COSE parsing myself.)

@emlun
Copy link
Member

emlun commented May 30, 2023

Hi! There are a few options here:

  • The WebAuthn L2 API includes a getPublicKey() method on AuthenticatorAttestationResponse, which returns the public key encoded as DER SubjectPublicKeyInfo. You could use that, but note that it'll not work for any users with a browser that only implements the L1 API. Note also that the getPublicKey() result is unsigned, so you may have to verify on the server side that the client was honest about it.

  • java-webauthn-server internally uses COSE-JAVA to parse keys (see here), which in turn uses CBOR-Java. The COSE.OneKey(com.upokecenter.cbor.CBORObject) constructor works well for parsing RSA and ECDSA keys.

    Example:

    import COSE.OneKey
    import com.upokecenter.cbor.CBORObject
    
    java.security.PublicKey parsePublicKey(AssertionResult result) {
      return new OneKey(CBORObject.DecodeFromBytes(result.getCredential.getPublicKeyCose.getBytes)).AsPublicKey();
    }

    For EdDSA keys, COSE-JAVA is hardcoded to use the "EdDSA" provider from the ed25519-java project. Therefore java-webauthn-server translates EdDSA keys to an X.509 format before importing them, in order to avoid an additional dependency. But if you add the "EdDSA" provider from ed25519-java, the OneKey constructor should work for EdDSA keys too.

Both of the above options are available today without any changes to existing libraries, though you may need to add a few dependencies to your application.

We'll also consider adding a java.security.PublicKey getter to the *Result types, or maybe RegisteredCredential, in a future java-webauthn-server release. That seems like a reasonable thing to support.

@iaik-jheher
Copy link
Contributor Author

Thanks for your quick response!

The client-side getPublicKey() method does not seem like a workable solution for us, since we use authenticator attestation. Since only the COSE public key is attested, we would need to re-verify that the two provided public keys match (which would require us to parse the COSE-encoded key, putting us back where we started.)

Thanks for the insights on how the library itself handles COSE parsing, though -- it looks like less of a complexity nightmare than anticipated. Still, we think it'd also be an appropriate thing for the library to provide.

PS: RegistrationResult does not currently expose the to-be-registered credential as a RegisteredCredential, so adding it there would not (by itself) expose the needed information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants