diff --git a/ldap/compositetypes/composite_types.go b/ldap/compositetypes/composite_types.go index 326441aaa9eeb825d6d8239ce2224990c2031b86..812da55697d1ccf5e114055e7b9b7969550a1e49 100644 --- a/ldap/compositetypes/composite_types.go +++ b/ldap/compositetypes/composite_types.go @@ -16,8 +16,11 @@ package compositetypes import ( + "encoding/base64" + "encoding/hex" "encoding/json" "errors" + "fmt" "strings" "github.com/duo-labs/webauthn/webauthn" @@ -149,6 +152,30 @@ func UnmarshalU2FRegistration(s string) (*U2FRegistration, error) { }, nil } +// ParseU2FRegistrationFromStrings parses the legacy U2F format used +// in manual key specifications etc. which consists of a +// base64(url)-encoded key handle, and a hex-encoded public key (in +// legacy U2F format). +func ParseU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistration, error) { + // U2F key handles are base64(url)-encoded (no trailing =s). + kh, err := base64.RawURLEncoding.DecodeString(keyHandle) + if err != nil { + return nil, fmt.Errorf("error decoding key handle: %w", err) + } + + // U2F public keys are hex-encoded. + pk, err := hex.DecodeString(publicKey) + if err != nil { + return nil, fmt.Errorf("error decoding public key: %w", err) + } + + return &U2FRegistration{ + PublicKey: u2fToCOSE(pk), + KeyHandle: kh, + Legacy: true, + }, nil +} + // Decode returns a u2f.Registration object with the decoded public // key ready for use in verification. func (r *U2FRegistration) Decode() (webauthn.Credential, error) {