java-webauthn-server
java-webauthn-server copied to clipboard
Extract DER-encoded public key from `RegistrationResult`/`AssertionResult`?
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.)
Hi! There are a few options here:
-
The WebAuthn L2 API includes a
getPublicKey()method onAuthenticatorAttestationResponse, 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 thegetPublicKey()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, theOneKeyconstructor 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.
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.