Skip to content
Snippets Groups Projects
Commit ac022b21 authored by ale's avatar ale
Browse files

Use more robust U2F -> COSE conversion method

parent 8cfdcfb5
Branches
No related tags found
1 merge request!32Add support for WebAuthN registrations
Pipeline #24671 passed
......@@ -11,6 +11,7 @@ require (
github.com/coreos/go-systemd/v22 v22.3.2
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594
github.com/fxamacker/cbor/v2 v2.2.0
github.com/go-asn1-ber/asn1-ber v1.5.3
github.com/go-ldap/ldap/v3 v3.4.1
github.com/gofrs/flock v0.8.0 // indirect
......
......@@ -23,7 +23,9 @@ import (
"fmt"
"strings"
"github.com/duo-labs/webauthn/protocol/webauthncose"
"github.com/duo-labs/webauthn/webauthn"
"github.com/fxamacker/cbor/v2"
)
// AppSpecificPassword stores information on an application-specific
......@@ -152,11 +154,11 @@ func UnmarshalU2FRegistration(s string) (*U2FRegistration, error) {
}, nil
}
// ParseU2FRegistrationFromStrings parses the legacy U2F format used
// ParseLegacyU2FRegistrationFromStrings 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) {
func ParseLegacyU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistration, error) {
// U2F key handles are base64(url)-encoded (no trailing =s).
kh, err := base64.RawURLEncoding.DecodeString(keyHandle)
if err != nil {
......@@ -176,6 +178,26 @@ func ParseU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistrat
}, nil
}
// ParseU2FRegistrationFromStrings parses the U2F registration format
// used in manual key specifications that is used by Fido2-aware
// programs such as pamu2fcfg >= 1.0.0. Both parameters are
// base64-encoded, public key should be in COSE format.
func ParseU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistration, error) {
kh, err := base64.StdEncoding.DecodeString(keyHandle)
if err != nil {
return nil, fmt.Errorf("error decoding key handle: %w", err)
}
pk, err := base64.StdEncoding.DecodeString(publicKey)
if err != nil {
return nil, fmt.Errorf("error decoding public key: %w", err)
}
return &U2FRegistration{
PublicKey: pk,
KeyHandle: kh,
}, nil
}
// Decode returns a u2f.Registration object with the decoded public
// key ready for use in verification.
func (r *U2FRegistration) Decode() (webauthn.Credential, error) {
......@@ -185,21 +207,32 @@ func (r *U2FRegistration) Decode() (webauthn.Credential, error) {
}, nil
}
// Convert a legacy U2F public key to COSE format.
func u2fToCOSE(pk []byte) []byte {
x := pk[1:33]
y := pk[33:]
out := []byte{
0xa4,
0x01, 0x02,
0x03, 0x26,
0x21, 0x58, 0x20,
}
out = append(out, x...)
out = append(out, []byte{
0x22, 0x58, 0x20,
}...)
out = append(out, y...)
return out
var key webauthncose.EC2PublicKeyData
key.KeyType = int64(webauthncose.EllipticKey)
key.Algorithm = int64(webauthncose.AlgES256)
key.XCoord = pk[1:33]
key.YCoord = pk[33:]
data, _ := cbor.Marshal(&key) // nolint: errcheck
return data
}
// Faster, but more questionable, implementation of the above:
//
// func u2fToCOSE(pk []byte) []byte {
// x := pk[1:33]
// y := pk[33:]
// out := []byte{
// 0xa4,
// 0x01, 0x02,
// 0x03, 0x26,
// 0x21, 0x58, 0x20,
// }
// out = append(out, x...)
// out = append(out, []byte{
// 0x22, 0x58, 0x20,
// }...)
// out = append(out, y...)
// return out
// }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment