extractPublicKeyFromRegistration

fun extractPublicKeyFromRegistration(publicKey: ByteArray? = null, authenticatorData: ByteArray? = null, attestationObject: ByteArray? = null): ByteArray

Extracts the secp256r1 public key from a WebAuthn registration response using multiple fallback strategies.

Tries three strategies in order:

  1. Direct public key: If publicKey is provided, validate it as a 65-byte uncompressed secp256r1 key (0x04 prefix) and verify the point lies on the secp256r1 curve. This is the primary path -- WebAuthnProvider implementations should return the public key directly in WebAuthnRegistrationResult.publicKey.

  2. Authenticator data parsing: If authenticatorData is provided, parse the attested credential data structure to extract X/Y coordinates from the COSE key.

  3. Attestation object pattern matching: If attestationObject is provided, search for the COSE key prefix pattern and extract X/Y coordinates.

At least one of the three parameters must be non-null.

Compressed keys (0x02/0x03 prefix) are not supported. WebAuthn platforms must provide uncompressed keys. If a compressed key is detected, an exception is thrown immediately and no fallback is attempted.

Return

Uncompressed secp256r1 public key (65 bytes: 0x04 prefix + X + Y)

Parameters

publicKey

Optional direct public key bytes (may include COSE/SPKI wrapping; the last 65 bytes are used if longer than 65 bytes)

authenticatorData

Optional raw authenticator data from WebAuthn registration

attestationObject

Optional raw attestation object from WebAuthn registration

Throws

if a compressed key prefix (0x02 or 0x03) is detected, or if the public key cannot be extracted from any provided source

Example:

// Strategy 1: Direct public key from provider
val pk = SmartAccountUtils.extractPublicKeyFromRegistration(
publicKey = registrationResult.publicKey
)

// Strategy 2: From authenticator data
val pk = SmartAccountUtils.extractPublicKeyFromRegistration(
authenticatorData = authData
)

// Strategy 3: From attestation object (fallback)
val pk = SmartAccountUtils.extractPublicKeyFromRegistration(
attestationObject = attestObj
)