681 lines
52 KiB
Go
Vendored
681 lines
52 KiB
Go
Vendored
package webauthncose
|
|
|
|
import (
|
|
"crypto/ecdh"
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"testing"
|
|
|
|
"github.com/fxamacker/cbor/v2"
|
|
"github.com/google/go-tpm/tpm2"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/go-webauthn/webauthn/protocol/webauthncbor"
|
|
)
|
|
|
|
// TestOKPSignatureVerification is a compatibility test to ensure that removing
|
|
// a previously used dependency doesn't introduce new issues.
|
|
//
|
|
// Since OKPs are used to represent Ed25519 keys, this test largely ensures
|
|
// that the underlying Ed25519 signature verification passes.
|
|
func TestOKPSignatureVerification(t *testing.T) {
|
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
require.NoError(t, err)
|
|
|
|
data := []byte("Sample data to sign")
|
|
validSig := ed25519.Sign(priv, data)
|
|
invalidSig := []byte("invalid")
|
|
|
|
key := OKPPublicKeyData{
|
|
XCoord: pub,
|
|
}
|
|
|
|
// Test that a valid signature passes.
|
|
ok, err := key.Verify(data, validSig)
|
|
assert.True(t, ok)
|
|
assert.NoError(t, err)
|
|
|
|
ok, err = key.Verify(data, invalidSig)
|
|
assert.NoError(t, err)
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestP256SignatureVerification(t *testing.T) {
|
|
// Private/public key pair was generated with the following:
|
|
//
|
|
// $ openssl ecparam -genkey -name secp256r1 -noout -out private_key.pem
|
|
// $ openssl ec -in private_key.pem -noout -text
|
|
// Private-Key: (256 bit)
|
|
// priv:
|
|
// 48:7f:36:1d:df:d7:34:40:e7:07:f4:da:a6:77:5b:
|
|
// 37:68:59:e8:a3:c9:f2:9b:3b:b6:94:a1:29:27:c0:
|
|
// 21:3c
|
|
// pub:
|
|
// 04:f7:39:f8:c7:7b:32:f4:d5:f1:32:65:86:1f:eb:
|
|
// d7:6e:7a:9c:61:a1:14:0d:29:6b:8c:16:30:25:08:
|
|
// 87:03:16:c2:49:70:ad:78:11:cc:d9:da:7f:1b:88:
|
|
// f2:02:be:ba:c7:70:66:3e:f5:8b:a6:83:46:18:6d:
|
|
// d7:78:20:0d:d4
|
|
// ASN1 OID: prime256v1
|
|
// NIST CURVE: P-256
|
|
// ----.
|
|
pubX, err := hex.DecodeString("f739f8c77b32f4d5f13265861febd76e7a9c61a1140d296b8c16302508870316")
|
|
assert.NoError(t, err)
|
|
|
|
pubY, err := hex.DecodeString("c24970ad7811ccd9da7f1b88f202bebac770663ef58ba68346186dd778200dd4")
|
|
assert.NoError(t, err)
|
|
|
|
key := EC2PublicKeyData{
|
|
// These constants are from https://datatracker.ietf.org/doc/rfc9053/
|
|
// (see "ECDSA" and "Elliptic Curve Keys").
|
|
PublicKeyData: PublicKeyData{
|
|
KeyType: 2, // EC.
|
|
Algorithm: -7, // "ES256".
|
|
},
|
|
Curve: 1, // P-256.
|
|
XCoord: pubX,
|
|
YCoord: pubY,
|
|
}
|
|
|
|
data := []byte("webauthnFTW")
|
|
|
|
validSig, err := hex.DecodeString("3045022053584980793ee4ec01d583f303604c4f85a7e87df3fe9551962c5ab69a5ce27b022100c801fd6186ca4681e87fbbb97c5cb659f039473995a75a9a9dffea2708d6f8fb")
|
|
assert.NoError(t, err)
|
|
|
|
ok, err := VerifySignature(key, data, validSig)
|
|
assert.True(t, ok)
|
|
assert.NoError(t, err)
|
|
|
|
ok, err = VerifySignature(key, []byte("webauthnFTL"), validSig)
|
|
assert.NoError(t, err)
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestOKPDisplayPublicKey(t *testing.T) {
|
|
// Sample public key generated from ed25519.GenerateKey(rand.Reader).
|
|
var pub ed25519.PublicKey = []byte{0x7b, 0x88, 0x10, 0x24, 0xad, 0xc9, 0x82, 0xd3, 0x80, 0xb8, 0x77, 0x1e, 0x3b, 0x9b, 0xf8, 0xe4, 0xb3, 0x99, 0x8b, 0xc7, 0xd0, 0x58, 0x30, 0x66, 0x2, 0xce, 0x4d, 0xf, 0x2f, 0xe4, 0xb7, 0x81}
|
|
// The PEM encoded representation of the public key in PKIX, ASN.1 DER format.
|
|
expected := `-----BEGIN PUBLIC KEY-----
|
|
MCowBQYDK2VwAyEAe4gQJK3JgtOAuHceO5v45LOZi8fQWDBmAs5NDy/kt4E=
|
|
-----END PUBLIC KEY-----
|
|
`
|
|
key := OKPPublicKeyData{
|
|
XCoord: pub,
|
|
PublicKeyData: PublicKeyData{
|
|
KeyType: int64(OctetKey),
|
|
},
|
|
}
|
|
|
|
// Get the CBOR-encoded representation of the OKPPublicKeyData.
|
|
buf, _ := webauthncbor.Marshal(key)
|
|
|
|
actual := DisplayPublicKey(buf)
|
|
|
|
assert.Equal(t, expected, actual)
|
|
}
|
|
|
|
func TestRSAExponent(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
have *RSAPublicKeyData
|
|
expected int
|
|
err string
|
|
}{
|
|
{
|
|
"ShouldHandle3ByteExponent",
|
|
&RSAPublicKeyData{
|
|
Exponent: []byte{0x01, 0x00, 0x01},
|
|
},
|
|
65537,
|
|
"",
|
|
},
|
|
{
|
|
"ShouldHandle3ByteExponentAlt",
|
|
&RSAPublicKeyData{
|
|
Exponent: []byte{0x01, 0x00, 0x02},
|
|
},
|
|
65538,
|
|
"",
|
|
},
|
|
{
|
|
"ShouldHandle3ByteExponentLarge",
|
|
&RSAPublicKeyData{
|
|
Exponent: []byte{0xff, 0xff, 0xff},
|
|
},
|
|
16777215,
|
|
"",
|
|
},
|
|
{
|
|
"ShouldHandle4ByteExponent",
|
|
&RSAPublicKeyData{
|
|
Exponent: []byte{0x01, 0x00, 0x02, 0xff},
|
|
},
|
|
16777983,
|
|
"",
|
|
},
|
|
{
|
|
"ShouldHandleZeroLength",
|
|
&RSAPublicKeyData{
|
|
Exponent: []byte{},
|
|
},
|
|
0,
|
|
"invalid exponent length",
|
|
},
|
|
{
|
|
"ShouldHandleNilExponent",
|
|
&RSAPublicKeyData{
|
|
Exponent: nil,
|
|
},
|
|
0,
|
|
"invalid exponent length",
|
|
},
|
|
{
|
|
"ShouldHandleNilKey",
|
|
nil,
|
|
0,
|
|
"invalid key",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
actual, err := parseRSAPublicKeyDataExponent(tc.have)
|
|
|
|
if tc.err != "" {
|
|
assert.EqualError(t, err, tc.err)
|
|
assert.Equal(t, 0, actual)
|
|
} else {
|
|
assert.Equal(t, tc.expected, actual)
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnsupportedKeyMethods(t *testing.T) {
|
|
verified, err := VerifySignature(PublicKeyData{}, nil, nil)
|
|
assert.EqualError(t, err, "Unsupported Public Key Type")
|
|
assert.False(t, verified)
|
|
}
|
|
|
|
func TestParsePublicKey(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
attestationObject string
|
|
clientDataJSON string
|
|
authenticatorData string
|
|
signature string
|
|
expected any
|
|
tpmcurve tpm2.TPMECCCurve
|
|
isEC2Key bool
|
|
isRSAKey bool
|
|
isOKPKey bool
|
|
}{
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-none-es256
|
|
"ShouldHandleTestVector17",
|
|
"a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b559000000008446ccb9ab1db374750b2367ff6f3a1f0020f91f391db4c9b2fde0ea70189cba3fb63f579ba6122b33ad94ff3ec330084be4a5010203262001215820afefa16f97ca9b2d23eb86ccb64098d20db90856062eb249c33a9b672f26df61225820930a56b87a2fca66334b03458abf879717c12cc68ed73290af2e2664796b9220",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224f63446e55685158756c5455506f334a5558543049393770767a7a59425039745a63685879617630314167222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000",
|
|
"3046022100f50a4e2e4409249c4a853ba361282f09841df4dd4547a13a87780218deffcd380221008480ac0f0b93538174f575bf11a1dd5d78c6e486013f937295ea13653e331e87",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0xaf, 0xef, 0xa1, 0x6f, 0x97, 0xca, 0x9b, 0x2d, 0x23, 0xeb, 0x86, 0xcc, 0xb6, 0x40, 0x98, 0xd2, 0xd, 0xb9, 0x8, 0x56, 0x6, 0x2e, 0xb2, 0x49, 0xc3, 0x3a, 0x9b, 0x67, 0x2f, 0x26, 0xdf, 0x61}, YCoord: []uint8{0x93, 0xa, 0x56, 0xb8, 0x7a, 0x2f, 0xca, 0x66, 0x33, 0x4b, 0x3, 0x45, 0x8a, 0xbf, 0x87, 0x97, 0x17, 0xc1, 0x2c, 0xc6, 0x8e, 0xd7, 0x32, 0x90, 0xaf, 0x2e, 0x26, 0x64, 0x79, 0x6b, 0x92, 0x20}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-self-es256
|
|
"ShouldHandleTestVector19",
|
|
"a363666d74667061636b65646761747453746d74a263616c67266373696758483046022100ae045923ded832b844cae4d5fc864277c0dc114ad713e271af0f0d371bd3ac540221009077a088ed51a673951ad3ba2673d5029bab65b64f4ea67b234321f86fcfac5d68617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000df850e09db6afbdfab51697791506cfc0020455ef34e2043a87db3d4afeb39bbcb6cc32df9347c789a865ecdca129cbef58ca5010203262001215820eb151c8176b225cc651559fecf07af450fd85802046656b34c18f6cf193843c5225820927b8aa427a2be1b8834d233a2d34f61f13bfd44119c325d5896e183fee484f2",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225248696843784e534e493352594d45314f7731476d3132786e726b634a5f6666707637546e2d4a71386773222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a206754623533727a36456853576f6d58477a696d4331513d3d227d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000",
|
|
"3044022076691be76a8618976d9803c4cdc9b97d34a7af37e3bdc894a2bf54f040ffae850220448033a015296ffb09a762efd0d719a55346941e17e91ebf64c60d439d0b9744",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0xeb, 0x15, 0x1c, 0x81, 0x76, 0xb2, 0x25, 0xcc, 0x65, 0x15, 0x59, 0xfe, 0xcf, 0x7, 0xaf, 0x45, 0xf, 0xd8, 0x58, 0x2, 0x4, 0x66, 0x56, 0xb3, 0x4c, 0x18, 0xf6, 0xcf, 0x19, 0x38, 0x43, 0xc5}, YCoord: []uint8{0x92, 0x7b, 0x8a, 0xa4, 0x27, 0xa2, 0xbe, 0x1b, 0x88, 0x34, 0xd2, 0x33, 0xa2, 0xd3, 0x4f, 0x61, 0xf1, 0x3b, 0xfd, 0x44, 0x11, 0x9c, 0x32, 0x5d, 0x58, 0x96, 0xe1, 0x83, 0xfe, 0xe4, 0x84, 0xf2}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-none-es256-crossOrigin
|
|
"ShouldHandleTestVector21",
|
|
"a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54500000000883f4f6014f19c09d87aa38123be48d000206e1050c0d2ca2f07c755cb2c66a74c64fa43065c18f938354d9915db2bd5ce57a501020326200121582022200a473f90b11078851550d03b4e44a2279f8c4eca27b3153dedfe03e4e97d225820cbd0be95e746ad6f5a8191be11756e4c0420e72f65b466d39bc56b8b123a9c6e",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a226832716c463771445f65356c5f505f62796b7945377135645650674547685f49584a6b655737736e4d5463222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2039327063545644304162792d713464746d6a366566673d3d227d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000",
|
|
"304402204396b14b216ed47920dc359e46aa0a1d4a912cf9d50f25a58ec236a11db4cf5e02204fdb59ff01656c4b0868e415436a464b0e30e94b02c719b995afaba9c917146b",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x22, 0x20, 0xa, 0x47, 0x3f, 0x90, 0xb1, 0x10, 0x78, 0x85, 0x15, 0x50, 0xd0, 0x3b, 0x4e, 0x44, 0xa2, 0x27, 0x9f, 0x8c, 0x4e, 0xca, 0x27, 0xb3, 0x15, 0x3d, 0xed, 0xfe, 0x3, 0xe4, 0xe9, 0x7d}, YCoord: []uint8{0xcb, 0xd0, 0xbe, 0x95, 0xe7, 0x46, 0xad, 0x6f, 0x5a, 0x81, 0x91, 0xbe, 0x11, 0x75, 0x6e, 0x4c, 0x4, 0x20, 0xe7, 0x2f, 0x65, 0xb4, 0x66, 0xd3, 0x9b, 0xc5, 0x6b, 0x8b, 0x12, 0x3a, 0x9c, 0x6e}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-none-es256-topOrigin
|
|
"ShouldHandleTestVector23",
|
|
"a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b5410000000097586fd09799a76401c200455099ef2a0020b8ad59b996047ab18e2ceb57206c362da57458793481f4a8ebf101c7ca7cc0f1a5010203262001215820a1c47c1d82da4ebe82cd72207102b380670701993bc35398ae2e5726427fe01d22582086c1080d82987028c7f54ecb1b01185de243b359294a0ed210cd47480f0adc88",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22315570636a4b53324b6f34377379486a7372787a68572d466f51465132796b3572426c584f6573656f4759222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22746f704f726967696e223a2268747470733a2f2f6578616d706c652e636f6d222c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205569466f4a4d565251484441465746693476785570513d3d227d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000",
|
|
"304402206a19613fa8cfacfc8027272aec5dae3555fea9f983d841581466678d71e6761a02207a9785ba22e48eb18525850357d9dc70795aaad2e6021159c4a4a183146eaa71",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0xa1, 0xc4, 0x7c, 0x1d, 0x82, 0xda, 0x4e, 0xbe, 0x82, 0xcd, 0x72, 0x20, 0x71, 0x2, 0xb3, 0x80, 0x67, 0x7, 0x1, 0x99, 0x3b, 0xc3, 0x53, 0x98, 0xae, 0x2e, 0x57, 0x26, 0x42, 0x7f, 0xe0, 0x1d}, YCoord: []uint8{0x86, 0xc1, 0x8, 0xd, 0x82, 0x98, 0x70, 0x28, 0xc7, 0xf5, 0x4e, 0xcb, 0x1b, 0x1, 0x18, 0x5d, 0xe2, 0x43, 0xb3, 0x59, 0x29, 0x4a, 0xe, 0xd2, 0x10, 0xcd, 0x47, 0x48, 0xf, 0xa, 0xdc, 0x88}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-none-es256-long-credential-id
|
|
"ShouldHandleTestVector25",
|
|
"a363666d74646e6f6e656761747453746d74a0686175746844617461590483bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b549000000008f3360c2cd1b0ac14ffe0795c5d2638e03ff3a761a4e1674ad6c4305869435c0eee9c286172c229bb91b48b4ada140c0863417031305cce5b4a27a88d7fe728a5f5a627de771b4b40e77f187980c124f9fe832d7136010436a056cce716680587d23187cf1fc2c62ae86fc3e508ee9617ffc74fbc10488ec16ec5e9096328669a898709b655e549738c666c1ae6281dc3b5f733c251d3eefb76ee70a3805ca91bcc18e49c8dc7f63ebcb486ba8c3d6ab52b88ff72c6a5bb47c32f3ee8683a3ddc8abf60870448ec8a21b5bdcb183c7dead870255575a6df96eb1b6a2a1019780cba9e4887b17ff1164bbbcc10eb0d86ed75984cd3fa3419103024507dfd9ce8f92c56af7914cb0bb50b87ba82a312bb7dcd93028dbdcd6adb266979667158335171e3682d37755701edbf9d872846a291d49e57ef09da1ec637f5052ed2aa7407f7e61827468e94b461844f4c67be5fa9c6055a566f8fdfc29d4bf78a9ff275f552cc68ba543fa3962eea36fd1ea8453764577d021d0a181efc1f6100ab2e4110039e21ee16970bda7432b6134492155afc126295b3a2eccd12c66a68e340969e995e3e8c9c476e395cfc21203414110779474f1c9797406637dbe414f132519d3bf0ce4f01734ef0e1a12c3ad604ff15d766b1624db6a5a7ccbff7bc35c9908df94aba277e0af48f04ff3d16381c47e5a37ed3988a67a3b1ecaa926336b33391fff04128f869991c9fabd905b6fe3ceef5f8b630ec1c5d2636d5b1961ad5ca5004170f6f5e482792aad989b0287fe91e5c479403397152f1fa56aa79b156eb47e6c8ea3eb175c34cfb38ad8e772874639b1023d4d01395c94e55831671cc022aa6fa1e02a02c2e4abc776f6960e51f83b71a8c0f207b6a347573977812c9aa5480b0011aa739bd4b76c18c000cc4757cceccb920f007c40c00e37e5ab21476cd9f6054a8fffb55a108f5c706e2cea2049d81fd321ff47d2a5761b0800955ab1d4f4889f55a84e2601c684f17a4ade7453ea49591d0b59c8d9a765052f62219cf6ef4a5dd9539f0617d6ebbebce7c000455475d18449e25c49ef9a1e3efe18c09082ebe2058d7c347defaa92f0664553b805c7d76bbfce5f330aca220ac90a789380fc479ea0d8793205813cca590a912f699ad52f991a1bc0a503c3ec4b2a696719e3c26591a87127f7305cc7e72f4c8e39355ebb06a5b1042990f38710ee7aa612ee4374bb82e878585a70a96c2a6b47f101a4ff154be4fd76a3167577a5cc54d9167c154c69ac35485e44cc898b719e1be3cc9c0fb5624b8f8a0dae10947a41bf848b6c1bb33d1006ec077d7e286e3f2a7b4843716390119449fe2721e81a5ed2333d331c7120765da58fadae73c19d9a8c4509cf8ac1e9d98b799a5274509069739b5823f3fb496663820033426988eefca53e580e0f9e0dfe0992fc2e53a97e053639f98577058f995bdbd41cefdba50102032620012158203b8176b7504489cc593046d7988abb7905a742de6ac2cdc748a873c663e90cb12258201436d5edc9a75f23999eef9d5950a5c2455514ee1014084720f841a06b828a11",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22377833727057334f53505a307045664d396a75566d53574d36485a4935634f573875384d6f647047446a73222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000",
|
|
"304502203ecef83fb12a0cae7841055f9f87103a99fd14b424194bbf06c4623d3ee6e3fd022100d2ace346db262b1374a6b70faa51f518a42ddca13a4125ce6f5052a75bac9fb6",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x3b, 0x81, 0x76, 0xb7, 0x50, 0x44, 0x89, 0xcc, 0x59, 0x30, 0x46, 0xd7, 0x98, 0x8a, 0xbb, 0x79, 0x5, 0xa7, 0x42, 0xde, 0x6a, 0xc2, 0xcd, 0xc7, 0x48, 0xa8, 0x73, 0xc6, 0x63, 0xe9, 0xc, 0xb1}, YCoord: []uint8{0x14, 0x36, 0xd5, 0xed, 0xc9, 0xa7, 0x5f, 0x23, 0x99, 0x9e, 0xef, 0x9d, 0x59, 0x50, 0xa5, 0xc2, 0x45, 0x55, 0x14, 0xee, 0x10, 0x14, 0x8, 0x47, 0x20, 0xf8, 0x41, 0xa0, 0x6b, 0x82, 0x8a, 0x11}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-es256
|
|
"ShouldHandleTestVector27",
|
|
"a363666d74667061636b65646761747453746d74a363616c67266373696758473045022025fcee945801b94e63d7c029e6f761654cf02e7100d5364a3b90e03daa6276fc022100eabcdf4ce19feb0980e829c3b6137079b18e42f43ce5c3c573b83368794f354c637835638159022530820221308201c8a00302010202110088c220f83c8ef1feafe94deae45faad0300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004a91ba4389409dd38a428141940ca8feb1ac0d7b4350558104a3777a49322f3798440f378b3398ab2d3bb7bf91322c92eb23556f59ad0a836fec4c7663b0e4dc3a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414a589ba72d060842ab11f74fb246bdedab16f9b9b301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d040302034700304402201726b9d85ecd8a5ed51163722ca3a20886fd9b242a0aa0453d442116075defd502207ef471e530ac87961a88a7f0d0c17b091ffc6b9238d30f79f635b417be5910e768617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d00000000876ca4f52071c3e9b25509ef2cdf7ed60020c9a6f5b3462d02873fea0c56862234f99f081728084e511bb7760201a89054a5a50102032620012158201cf27f25da591208a4239c2e324f104f585525479a29edeedd830f48e77aeae522582059e4b7da6c0106e206ce390c93ab98a15a5ec3887e57f0cc2bece803b920c423",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273524276704770587676463446524841565833496d4b4130453958773858306b526a44426c4d6668726255222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20415a4d77794d78496244382d756775464e70367238513d3d227d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000",
|
|
"30460221009d8d54895393894d37b9fa7bdfbcff05403de3cf0d6443ffb394fa239f101579022100c8871288f19c6c48a3b64c09d39868c12d16ed80ea4c5d8890288975c0272f50",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x1c, 0xf2, 0x7f, 0x25, 0xda, 0x59, 0x12, 0x8, 0xa4, 0x23, 0x9c, 0x2e, 0x32, 0x4f, 0x10, 0x4f, 0x58, 0x55, 0x25, 0x47, 0x9a, 0x29, 0xed, 0xee, 0xdd, 0x83, 0xf, 0x48, 0xe7, 0x7a, 0xea, 0xe5}, YCoord: []uint8{0x59, 0xe4, 0xb7, 0xda, 0x6c, 0x1, 0x6, 0xe2, 0x6, 0xce, 0x39, 0xc, 0x93, 0xab, 0x98, 0xa1, 0x5a, 0x5e, 0xc3, 0x88, 0x7e, 0x57, 0xf0, 0xcc, 0x2b, 0xec, 0xe8, 0x3, 0xb9, 0x20, 0xc4, 0x23}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-es384
|
|
"ShouldHandleTestVector29",
|
|
"a363666d74667061636b65646761747453746d74a363616c67266373696758473045022100c56ecc970b7843833e0f461fde26233f61eb395161d481558c08b9c6ed61675b022029f5e05033705cd0f9b0a07e149468ec308a4f84906409efdceb1da20a7518d6637835638159022530820221308201c7a00302010202103d0a5588bb87ebb1d4cee4a1807c1b7c300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000417e5cc91d676d370e36aa7de40c25aacb45a3845f13d2932088ece2270b9b431241c219c22d0c256c9438ade00f2c05e62f8ef906b9b997ae9f3c460c2db66f5a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414c7c8dd95382a2230e4c0dd3664338fa908169a9c301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020348003045022054068cc9ae038937b7c468c307edb9c6927ffdeb6a20070c483eb40330f99f10022100cf41953919c3c04693d6b1f42a613753f204e70e85fc6e9b17036170b83596e068617574684461746158c5bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55900000000e950dcda3bdae1d087cda380a897848b0020953ae2dd9f28b1a1d5802c83e1f65833bb9769a08de82d812bc27c13fc6f06a9a5010203382220022158304866bd8b01da789e9eb806e5eab05ae5a638542296ab057a2f1bbce9b58f8a08b9171390b58a37ac7fffc2c5f45857da2258302a0b024c7f4b72072a1f96bd30a7261aae9571dd39870eb29e55c0941c6b08e89629a1ea1216aa64ce57c2807bf3901a",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225f304844306c32396957623759654b4f39655277516545333753614649454574646941726f4b307446464d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000",
|
|
"3065023100e4efbb46745ed00e67c4d51ab2bacab2af62ffa8b7c5fecec6d7d9bf2582275034a713a3dd731685eee81adfaf6aa63f0230161655353f07e018a3c2539f8de7c8c4cf88d4c32d2be29fe4e76fa096ecc9458bbfe0895d57129ab324130e6f0692db",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -35}, Curve: 2, XCoord: []uint8{0x48, 0x66, 0xbd, 0x8b, 0x1, 0xda, 0x78, 0x9e, 0x9e, 0xb8, 0x6, 0xe5, 0xea, 0xb0, 0x5a, 0xe5, 0xa6, 0x38, 0x54, 0x22, 0x96, 0xab, 0x5, 0x7a, 0x2f, 0x1b, 0xbc, 0xe9, 0xb5, 0x8f, 0x8a, 0x8, 0xb9, 0x17, 0x13, 0x90, 0xb5, 0x8a, 0x37, 0xac, 0x7f, 0xff, 0xc2, 0xc5, 0xf4, 0x58, 0x57, 0xda}, YCoord: []uint8{0x2a, 0xb, 0x2, 0x4c, 0x7f, 0x4b, 0x72, 0x7, 0x2a, 0x1f, 0x96, 0xbd, 0x30, 0xa7, 0x26, 0x1a, 0xae, 0x95, 0x71, 0xdd, 0x39, 0x87, 0xe, 0xb2, 0x9e, 0x55, 0xc0, 0x94, 0x1c, 0x6b, 0x8, 0xe8, 0x96, 0x29, 0xa1, 0xea, 0x12, 0x16, 0xaa, 0x64, 0xce, 0x57, 0xc2, 0x80, 0x7b, 0xf3, 0x90, 0x1a}},
|
|
tpm2.TPMECCNistP384,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-es512
|
|
"ShouldHandleTestVector31",
|
|
"a363666d74667061636b65646761747453746d74a363616c67266373696758483046022100c48fcbd826bbc79680802026688d41ab6da8c3a1d22ab6cecf36c8d7695d22500221008767dfe591277e973078d5692c8c35cf9d579792822e7145c96a0ac4515df5b0637835638159022730820223308201c8a0030201020211008a128b7ebe52b993835779e6d9b81355300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004940b68885291536e2f7c60c05acfb252e7eebcf4304425dd93ab7b1962f20492bf18dc0f12862599e81fb764ac92151f9a78fcbb35d7a26c8c52949b18133c06a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604143ffad863abcd3dc5717b8a252189f41af97e7f31301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100832c8b64c4f0188bd32e1bec63e13301cdc03165d3ef840d1f3dabb9a5719f83022100add57a9d5bedec98f29222dfc97ea795d055ee13a02a153d02be9ce00aedeb9168617574684461746158e9bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d0000000039d8ce6a3cf61025775083a738e5c2540020d17d5af7e3f37c56622a67c8462c9e1c6336dfccb8b61d359dc47378dba58ce4a5010203382320032158420083240a2c3ad21a3dc0a6daa3d8bc05a46d7cd9825ba010ae2a22686c2d6d663d7d5f678987fb1e767542e63dc197ae915e25f8ee284651af29066910a2cc083f50225842017337df47ab5cce5d716ef8caffa97a3012689b1f326ea6c43a1ba9596c72f71f0122390143552b42be772b4c35ffb961220c743b486a601ea4cb6d5412f5b078d3",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22434e4d5a4447334c5055384d746c6d674d7a763136684a4e337a61677a5450564945734e65694b6f7a436279355046703067416f5848657a2d794c67386366306d6f66557669306c3653313565416a6471716d31635637394f6d72616b7a6e544253706f666278644c3479484777525234476b66563630546855473374793536714a4d334b6577635a6b7679354e376134574674434f7a7671416f71553745445a6a7a6c7149454569436b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000",
|
|
"3081870242009bda02fe384e77bcb9fb42b07c395b7a53ec9d9616dd0308ab8495c2141c8364c7d16e212a4a4fb8e3987ff6c99eafd64d8484fd28c3fc7968f658a9033d1bb1b802416383e9f3ee20c691b66620299fef36bea2df4d39c92b2ead92f58e7b79ab0d9864d2ebf3b0dcc66ea13234492ccee6e9d421db43c959bcb94c162dc9494136c9f6",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -36}, Curve: 3, XCoord: []uint8{0x0, 0x83, 0x24, 0xa, 0x2c, 0x3a, 0xd2, 0x1a, 0x3d, 0xc0, 0xa6, 0xda, 0xa3, 0xd8, 0xbc, 0x5, 0xa4, 0x6d, 0x7c, 0xd9, 0x82, 0x5b, 0xa0, 0x10, 0xae, 0x2a, 0x22, 0x68, 0x6c, 0x2d, 0x6d, 0x66, 0x3d, 0x7d, 0x5f, 0x67, 0x89, 0x87, 0xfb, 0x1e, 0x76, 0x75, 0x42, 0xe6, 0x3d, 0xc1, 0x97, 0xae, 0x91, 0x5e, 0x25, 0xf8, 0xee, 0x28, 0x46, 0x51, 0xaf, 0x29, 0x6, 0x69, 0x10, 0xa2, 0xcc, 0x8, 0x3f, 0x50}, YCoord: []uint8{0x1, 0x73, 0x37, 0xdf, 0x47, 0xab, 0x5c, 0xce, 0x5d, 0x71, 0x6e, 0xf8, 0xca, 0xff, 0xa9, 0x7a, 0x30, 0x12, 0x68, 0x9b, 0x1f, 0x32, 0x6e, 0xa6, 0xc4, 0x3a, 0x1b, 0xa9, 0x59, 0x6c, 0x72, 0xf7, 0x1f, 0x1, 0x22, 0x39, 0x1, 0x43, 0x55, 0x2b, 0x42, 0xbe, 0x77, 0x2b, 0x4c, 0x35, 0xff, 0xb9, 0x61, 0x22, 0xc, 0x74, 0x3b, 0x48, 0x6a, 0x60, 0x1e, 0xa4, 0xcb, 0x6d, 0x54, 0x12, 0xf5, 0xb0, 0x78, 0xd3}},
|
|
tpm2.TPMECCNistP521,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-rs256
|
|
"ShouldHandleTestVector33",
|
|
"a363666d74667061636b65646761747453746d74a363616c672663736967584730450221008b8c5c6ea8c142c032e0be69e1353d44461c5c9109941cdda951b976eb95b6b302204d52f406c19e254b3ff9589bd18070fb055ac8db12fdd0a6734bea9d7168e900637835638159022630820222308201c7a00302010202101f6fb7a5ece81b45896b983a995da5f3300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004b7b36b7542a11120b443c794d0c99fdc25a06b76586413d81e086163ef6fe147a557afc34e2861d9057d6d465d4705a0310550bdeeb5f35ee35b9425ab859981a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414fb37b647bccfb9e54d989eaaacc1633868703fb3301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100b86bc129d92afca7d9869a39f70f139a305b4073a39eb654d81424bed5757d91022100cf9f7c60cab7c4a7d3e7f0020f281a93d4fd0a9f95121b989f56932a68885fba68617574684461746159021bbfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000428f8878298b9862a36ad8c7527bfef20020992a18acc83f67533600c1138a4b4c4bd236de13629cf025ed17cb00b00b74dfa4010303390100205901b403fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012143010001",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224b56395a39667150356978617970346e596d7834794e6f33617562597a5333536d75757459423462784d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000",
|
|
"01063d52d7c39b4d432fc7063c5d93e582bdcb16889cd71f888d67d880ea730a428498d3bc8e1ee11f2b1ecbe6c292b118c55ffaaddefa8cad0a54dd137c51f1eec673f1bb6c4d1789d6826a222b22d0f585fc901fdc933212e579d199b89d672aa44891333e6a1355536025e82b25590256c3538229b55737083b2f6b9377e49e2472f11952f79fdd0da180b5ffd901b4049a8f081bb40711bef76c62aed943571f2d0575304cb549d68d8892f95086a30f93716aee818f8dc06e96c0d5e0ed4cfa9fd8773d90464b68cf140f7986666ff9c9e3302acd0535d60d769f465e2ab57ef8aabc89fccfef7ba32a64154a8b3d26be2298f470b8cc5377dbe3dfd4b0b45f8f01e63bde6cfc76b62771f9b70aa27cf40152cad93aa5acd784fd4b90f676e2ea828d0bf2400aebbaae4153e5838f537f88b6228346782a93a899be66ec77de45b3efcf311da6321c92e6b0cd11bfe653bf3e98cee8e341f02d67dbb6f9c98d9e8178090cfb5b70fbc6d541599ac794ae2f1d4de1286ec8de8c2daf7b1d15c8438e90d924df5c19045220a4c8438c1b979bbe016cf3d0eeec23c3999d4882cc645b776de930756612cdc6dd398160ff02a6",
|
|
RSAPublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 3, Algorithm: -257}, Modulus: []uint8{0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, Exponent: []uint8{0x1, 0x0, 0x1}},
|
|
tpm2.TPMECCNistP256,
|
|
false,
|
|
true,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-packed-ed25519
|
|
"ShouldHandleTestVector35",
|
|
"a363666d74667061636b65646761747453746d74a363616c672663736967584730450220730a54d4f76cb1f2b7dd4a5a6eee3374e3c8a60fb3c4daa527c9277e365b64aa0221008b31a04a28cc4148b14c42a916548ee7f430bc7629295b42ee93e5d1aaba8ee6637835638159022530820221308201c7a00302010202106e391f23f57150dc7a12dad18f2b43ad300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004fb96a581a0b36742a8c45d6ffb5af1ef155524b50339445ec1109874045e0087db77edef91f3dc949927470d84b01627087b72c86b7c9d02e1389cba680ffc36a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414ef2ce1a86caba85121130a16e8ce82a75d5a6653301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020348003045022100ad4fa628cffba5a642a562cbfefe63efecce26d90c80114114d1745383e12f01022028af87ba3b0ff868a34b9458bc6973b27380a328dd87b7436651ffa823280bca6861757468446174615881bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54900000000164009ea09faae7c397bc3e2ad0e7ec00020c6cffa01b7fda368a7e0b29c1384a719820246bca894dd12914708743af0cecda401010327200621582089f81eba4a1f510cb243ff7fb9e9cf899bf627e49ce1ac3c3eae8adb2a8d7d7b",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224e35446169797479376f7a686c32463465744f4d763670706672504b41546f545170694856726d48686173222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000",
|
|
"4c873571377ac019f257d6bf07249f63ac2487483c51bc511ce0f0e3266c840cb07a09cdc445a2f963d8603a9f0f6cf9ce709d7fc6a96c7c51ea08d33776010c",
|
|
OKPPublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 1, Algorithm: -8}, Curve: 0, XCoord: []uint8{0x89, 0xf8, 0x1e, 0xba, 0x4a, 0x1f, 0x51, 0xc, 0xb2, 0x43, 0xff, 0x7f, 0xb9, 0xe9, 0xcf, 0x89, 0x9b, 0xf6, 0x27, 0xe4, 0x9c, 0xe1, 0xac, 0x3c, 0x3e, 0xae, 0x8a, 0xdb, 0x2a, 0x8d, 0x7d, 0x7b}},
|
|
tpm2.TPMECCNistP256,
|
|
false,
|
|
false,
|
|
true,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-tpm-es256
|
|
"ShouldHandleTestVector37",
|
|
"a363666d746374706d6761747453746d74a663616c67266373696758463044022066e5826a652091030fd444e33c3eca2bc6dc548cf3045013addb38aa6457a21002203f3a5c95c9e707d0e555041bcc8698ee4ebc04e26cc8bae459705471789851766376657263322e30637835638159023a30820236308201dca0030201020210311fc42da0ab10c43a9b1bf3a75e34e2300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004c54e3f109094f60d7699b7db5d838569ffd1f3e1c9e897cd9eb40063f9402e3e9937e936cf1fcd5eb743ff443c97ab2edcd7c8e0e6cf6cfd413b8ab19fffa769a381d33081d0300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604145f546cb6973d4981e80fcdc7463859f5879680e4301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e30100603551d250409300706056781050803305e0603551d110101ff04543052a450304e314c3014060567810502010c0b69643a30303030303030303014060567810502030c0b69643a3030303030303030301e060567810502020c15576562417574686e207465737420766563746f7273300a06082a8648ce3d0403020348003045022063c9a2797b8066f1db34dd609f1ab6695607e7a98e9ff8090a68853c9a9fc949022100a55831a39f5b8a2aa9a68837829cabf43fea2a5cea4859ae851cac78e6ac3e97677075624172656158560023000b0004000000000010001000030010002041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b0020d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d076863657274496e666f5869ff544347801700000020277d0e05579dd013215a62273f7f3a3e7e191ead2654a3036d75a5a3ee37a6b0000000000000000011111111222222223300000000000000000022000b9c42d8aad5939331b9af3711af179f17123178098c9a7d0ca89fcd1fc800f3c7000068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d000000004b92a377fc5f6107c4c85c190adbfd990020ec27bec7521c894bbb821105ea3724c90e770cf1fa354157ef18d0f18f78bea9a501020326200121582041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b225820d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d07",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2241416b375a7349645731364a393642776768474a422d6f2d554330304f7a464c6a46705531693279417673222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000",
|
|
"3045022060dc76b1607ec716c6e5eba8d056695ed6bc47b2e3d7a729c34e759e3ab66aa0022100d010a9e8fddcb64c439dfdca628ddb33cf245d567d157d9f66f942601bed9b38",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x41, 0x20, 0x26, 0x98, 0xc9, 0xd9, 0x75, 0x3f, 0xb4, 0xbb, 0x3f, 0x27, 0xcd, 0x9, 0xfe, 0x6b, 0x8a, 0xfd, 0xb7, 0x64, 0x38, 0xee, 0x2a, 0xe5, 0x4d, 0x7c, 0x9d, 0xad, 0xe1, 0xd, 0x86, 0x4b}, YCoord: []uint8{0xd8, 0x73, 0x51, 0x15, 0xcd, 0xb3, 0x30, 0xa6, 0x3e, 0xa1, 0xd6, 0xe4, 0x3d, 0x50, 0x0, 0xf4, 0xbd, 0x56, 0xf9, 0x9b, 0xce, 0x83, 0xee, 0x1d, 0x73, 0x30, 0x1f, 0xc2, 0x70, 0x11, 0x6d, 0x7}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-android-key-es256
|
|
"ShouldHandleTestVector39",
|
|
"a363666d746b616e64726f69642d6b65796761747453746d74a363616c672663736967584630440220592bbc3c4c5f6158b52be1e085c92848986d7844245dfc9512e1a7e9ff7a2cd8022015bdd0852d3bd091e1c22da4211f4ccf0fdf4d912599d1c6630b1f310d3166f5637835638159026d3082026930820210a00302010202101ff91f76b63f44812f998b250b0286bf300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000499169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accfdd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6ba381a83081a5300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604141ac81e50641e8d1339ab9f7eb25f0cd5aac054b0301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e3045060a2b06010401d679020111043730350202012c0201000201000201000420b20e943e3a7544b3a438943b6d5655313a47ef1af34e00ff3261aeb9ed155817040030003000300a06082a8648ce3d040302034700304402206f4609c9ffc946c418cef04c64a0d07bcce78f329b99270b822f2a4d1e3b75330220093c8d18328f36ef157f296393bdc7721dd2bd67438ffeaa42f051a044b7457168617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000ade9705e1ce7085b899a540d02199bf800200a4729519788b6ed8a2d772b494e186244d8c798c052960dbc8c10c915176795a501020326200121582099169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accf225820dd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6b",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22354f344679703238375851525a55447954746d74786971756851645742534b45545f702d36685433723459222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2071784a78422d5f78677277794d4c3631386472536e413d3d227d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000",
|
|
"304502202060107d953b286aa1bf35e3e8c78b383fddab5591b2db17ffb23ed83fe7df20022100a99be0297cb0d9d38aa96f30b760a4e0749dab385acd2a51d0560caae570d225",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x99, 0x16, 0x96, 0x57, 0x3, 0x6d, 0x8, 0x9a, 0x2a, 0x98, 0x21, 0xa7, 0xd0, 0x6, 0x3d, 0x34, 0x1f, 0x1a, 0x46, 0x13, 0x38, 0x93, 0x59, 0x63, 0x6e, 0xfa, 0xb5, 0xf3, 0xcb, 0xf1, 0xac, 0xcf}, YCoord: []uint8{0xdd, 0x91, 0xc5, 0x55, 0x43, 0x17, 0x6e, 0xa9, 0x9b, 0x64, 0x44, 0x6, 0xdd, 0x1d, 0xd6, 0x37, 0x74, 0xb6, 0xaf, 0x65, 0xac, 0x75, 0x9e, 0x6, 0xff, 0x40, 0xb1, 0xc8, 0xab, 0x2, 0xdf, 0x6b}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
{
|
|
// Test Vector: https://www.w3.org/TR/webauthn-3/#sctn-test-vectors-apple-es256
|
|
"ShouldHandleTestVector41",
|
|
"a363666d74656170706c656761747453746d74a1637835638159025c30820258308201fea0030201020210394275613d5310b81a29ce90f48b61c1300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d030107034200048a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761af728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136ca38196308193300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e0416041412f1ce6c0ae39b403bfc9200317bc183a4e4d766301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e303306092a864886f76364080204263024a122042097851a1a98b69c0614b26a94b70ec3aa07c061f89dbee23fbee01b6c42d718b0300a06082a8648ce3d040302034800304502207d541a5553f38b93b78b26a9dca58e64a7f8fac15ca206ae3ea32497cda375fb0221009137c6b75e767ec08224b29a7f703db4b745686dcc8a26b66e793688866d064f68617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54900000000748210a20076616a733b2114336fc38400209c4a5886af9283d9be3e9ec55978dedfdce2e3b365cab193ae850c16238fafb8a50102032620012158208a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761a225820f728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136c",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22302d73705a4751654a76375149304136637433676b37476353366b416a442d6432445f503030656d625155222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000",
|
|
"3046022100ee35db795ce28044e1f8231d68b3d79a9882f7415aa35c1b5ac74d24251073c8022100dcc65691650a412d0ceef843710c09827acf26c7845bddac07eec95863e7fc4c",
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: 1, XCoord: []uint8{0x8a, 0x3d, 0x5b, 0x1b, 0x4c, 0x54, 0x3a, 0x70, 0x6b, 0xf6, 0xe4, 0xb0, 0xa, 0xfe, 0xdb, 0x3c, 0x93, 0xb, 0x69, 0xd, 0xd2, 0x86, 0x93, 0x4f, 0xe2, 0x91, 0x1f, 0x77, 0x9c, 0xc7, 0x76, 0x1a}, YCoord: []uint8{0xf7, 0x28, 0xe1, 0xaa, 0x3b, 0xf, 0xf6, 0x66, 0x92, 0x19, 0x2d, 0xaa, 0x77, 0x6b, 0x83, 0xdd, 0xf8, 0xe3, 0x34, 0xd, 0x2d, 0x9a, 0xe, 0xab, 0xdf, 0xc3, 0x24, 0xeb, 0x3e, 0x2f, 0x13, 0x6c}},
|
|
tpm2.TPMECCNistP256,
|
|
true,
|
|
false,
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var (
|
|
keyBytes []byte
|
|
err error
|
|
)
|
|
|
|
keyBytes = MustExtractCBORKeyFromAttestationObject(t, tc.attestationObject)
|
|
result, err := ParsePublicKey(keyBytes)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
|
|
data := MustConstructSignedData(t, tc.clientDataJSON, tc.authenticatorData)
|
|
signature := MustDecodeHex(t, tc.signature)
|
|
|
|
switch key := result.(type) {
|
|
case EC2PublicKeyData:
|
|
assert.True(t, tc.isEC2Key)
|
|
assert.False(t, tc.isRSAKey)
|
|
assert.False(t, tc.isOKPKey)
|
|
|
|
assert.Equal(t, tc.tpmcurve, key.TPMCurveID())
|
|
|
|
ec, err := key.ToECDSA()
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, ec)
|
|
case RSAPublicKeyData:
|
|
assert.False(t, tc.isEC2Key)
|
|
assert.True(t, tc.isRSAKey)
|
|
assert.False(t, tc.isOKPKey)
|
|
case OKPPublicKeyData:
|
|
assert.False(t, tc.isEC2Key)
|
|
assert.False(t, tc.isRSAKey)
|
|
assert.True(t, tc.isOKPKey)
|
|
default:
|
|
t.Fatalf("Unexpected key type: %T", key)
|
|
}
|
|
|
|
ok, err := VerifySignature(result, data, signature)
|
|
assert.NoError(t, err)
|
|
assert.True(t, ok)
|
|
assert.Equal(t, tc.expected, result)
|
|
|
|
SetExperimentalInsecureAllowBERIntegers(true)
|
|
|
|
ok, err = VerifySignature(result, data, signature)
|
|
assert.NoError(t, err)
|
|
assert.True(t, ok)
|
|
assert.Equal(t, tc.expected, result)
|
|
|
|
SetExperimentalInsecureAllowBERIntegers(false)
|
|
|
|
display := DisplayPublicKey(keyBytes)
|
|
|
|
assert.NotEmpty(t, display)
|
|
assert.NotEqual(t, keyCannotDisplay, display)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParsePublicKeyValidation(t *testing.T) {
|
|
mustMarshalCOSEKey := func(t *testing.T, kty, alg int64, extra map[int64]any) []byte {
|
|
t.Helper()
|
|
|
|
m := map[int64]any{1: kty, 3: alg}
|
|
for k, v := range extra {
|
|
m[k] = v
|
|
}
|
|
|
|
data, err := webauthncbor.Marshal(m)
|
|
require.NoError(t, err)
|
|
|
|
return data
|
|
}
|
|
|
|
// Generate valid key material for accept tests.
|
|
okpPub, _, err := ed25519.GenerateKey(rand.Reader)
|
|
require.NoError(t, err)
|
|
|
|
ec2Priv, err := ecdh.P256().GenerateKey(rand.Reader)
|
|
require.NoError(t, err)
|
|
|
|
ec2Pub := ec2Priv.PublicKey().Bytes()
|
|
ec2X := ec2Pub[1:33]
|
|
ec2Y := ec2Pub[33:65]
|
|
|
|
// COSE Key parameters per RFC 9052 §7 and RFC 9053 §2/§7:
|
|
// 1 (kty), 3 (alg), -1 (crv / n), -2 (x / e), -3 (y).
|
|
testCases := []struct {
|
|
name string
|
|
input []byte
|
|
err string
|
|
}{
|
|
{
|
|
"ShouldAcceptValidOKPKey",
|
|
mustMarshalCOSEKey(t, int64(OctetKey), int64(AlgEdDSA), map[int64]any{-2: []byte(okpPub)}),
|
|
"",
|
|
},
|
|
{
|
|
"ShouldAcceptValidEC2Key",
|
|
mustMarshalCOSEKey(t, int64(EllipticKey), int64(AlgES256), map[int64]any{-1: int64(P256), -2: ec2X, -3: ec2Y}),
|
|
"",
|
|
},
|
|
{
|
|
"ShouldAcceptValidRSAKey",
|
|
mustMarshalCOSEKey(t, int64(RSAKey), int64(AlgRS256), map[int64]any{-1: []byte{0xFF}, -2: []byte{0x01, 0x00, 0x01}}),
|
|
"",
|
|
},
|
|
{
|
|
"ShouldRejectOKPWithInvalidXCoordLength",
|
|
mustMarshalCOSEKey(t, int64(OctetKey), int64(AlgEdDSA), map[int64]any{-2: make([]byte, 16)}),
|
|
"OKP key x coordinate has invalid length 16, expected 32",
|
|
},
|
|
{
|
|
"ShouldRejectEC2WithUnsupportedAlgorithm",
|
|
mustMarshalCOSEKey(t, int64(EllipticKey), int64(999), map[int64]any{-1: int64(P256), -2: make([]byte, 32), -3: make([]byte, 32)}),
|
|
"Unsupported EC2 algorithm",
|
|
},
|
|
{
|
|
"ShouldRejectEC2WithInvalidCoordLength",
|
|
mustMarshalCOSEKey(t, int64(EllipticKey), int64(AlgES256), map[int64]any{-1: int64(P256), -2: make([]byte, 48), -3: make([]byte, 48)}),
|
|
"EC2 key x or y coordinate has invalid length",
|
|
},
|
|
{
|
|
"ShouldRejectEC2WithOffCurvePoint",
|
|
mustMarshalCOSEKey(t, int64(EllipticKey), int64(AlgES256), map[int64]any{-1: int64(P256), -2: make([]byte, 32), -3: make([]byte, 32)}),
|
|
"EC2 key point is not on curve",
|
|
},
|
|
{
|
|
"ShouldRejectRSAWithEmptyModulus",
|
|
mustMarshalCOSEKey(t, int64(RSAKey), int64(AlgRS256), map[int64]any{-1: []byte{}, -2: []byte{0x01, 0x00, 0x01}}),
|
|
"RSA key contains zero or empty modulus",
|
|
},
|
|
{
|
|
"ShouldRejectRSAWithEmptyExponent",
|
|
mustMarshalCOSEKey(t, int64(RSAKey), int64(AlgRS256), map[int64]any{-1: []byte{0xFF}, -2: []byte{}}),
|
|
"RSA key contains invalid exponent: invalid exponent length",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result, err := ParsePublicKey(tc.input)
|
|
|
|
if tc.err != "" {
|
|
assert.Nil(t, result)
|
|
assert.EqualError(t, err, tc.err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func MustExtractCBORKeyFromAttestationObject(t *testing.T, have string) []byte {
|
|
type AttObj struct {
|
|
AuthData []byte `cbor:"authData"`
|
|
}
|
|
|
|
raw := MustDecodeHex(t, have)
|
|
|
|
att := AttObj{}
|
|
|
|
require.NoError(t, cbor.Unmarshal(raw, &att))
|
|
|
|
// rpIdHash/flags/counter.
|
|
offset := 32 + 1 + 4
|
|
|
|
// AAGUID.
|
|
offset += 16
|
|
|
|
credLen := int(att.AuthData[offset])<<8 | int(att.AuthData[offset+1])
|
|
offset += 2 + credLen
|
|
|
|
return att.AuthData[offset:]
|
|
}
|
|
|
|
func TestFIDOPublicKey(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
have string
|
|
clientDataJSON string
|
|
authenticatorData string
|
|
signature string
|
|
public bool
|
|
expected EC2PublicKeyData
|
|
tpmcurve tpm2.TPMECCCurve
|
|
err string
|
|
}{
|
|
{
|
|
// Test Vector: https://w3c.github.io/webauthn/#sctn-test-vectors-fido-u2f-es256
|
|
"ShouldHandleTestVector45",
|
|
"51bd002938fa10b83683ac2a2032d0a7338c7f65a90228cfd1f61b81ec7288d0",
|
|
"7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a222d5178684b59485954316d554f4e3461554139326b6d36537a49532d2d4f417362694e5650774249564455222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d",
|
|
"bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50100000000",
|
|
"304402206172459958fea907b7292b92f555034bfd884895f287a76200c1ba287239137002204727b166147e26a21bbc2921d192ebfed569b79438538e5c128b5e28e6926dd7",
|
|
false,
|
|
EC2PublicKeyData{PublicKeyData: PublicKeyData{_struct: false, KeyType: 2, Algorithm: -7}, Curve: int64(P256), XCoord: []uint8{0xb0, 0xd6, 0x2d, 0xe6, 0xb3, 0xf, 0x86, 0xf0, 0xba, 0xc7, 0xa9, 0x1, 0x69, 0x51, 0x39, 0x1c, 0x2e, 0x31, 0x84, 0x9e, 0x2e, 0x64, 0x66, 0x1c, 0xbd, 0x2b, 0x13, 0xcd, 0x7d, 0x55, 0x8, 0xad}, YCoord: []uint8{0x50, 0x3b, 0xb, 0xda, 0x2a, 0x35, 0x7a, 0x9a, 0x4b, 0x34, 0x47, 0x5a, 0x28, 0xe6, 0x5b, 0x66, 0xb, 0x48, 0x98, 0xa9, 0xe3, 0xe9, 0xbb, 0xf0, 0x82, 0xd, 0x43, 0x49, 0x42, 0x97, 0xed, 0xd0}},
|
|
tpm2.TPMECCNistP256,
|
|
"",
|
|
},
|
|
{
|
|
"ShouldNotParseTestFixture1AsPublicKey",
|
|
"51bd002938fa10b83683ac2a2032d0a7338c7f65a90228cfd1f61b81ec7288d0",
|
|
"",
|
|
"",
|
|
"",
|
|
true,
|
|
EC2PublicKeyData{},
|
|
0x00,
|
|
"failed to parse FIDO public key: crypto/ecdh: invalid public key",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var (
|
|
keyBytes []byte
|
|
result EC2PublicKeyData
|
|
err error
|
|
)
|
|
|
|
if tc.public {
|
|
keyBytes, err = hex.DecodeString(tc.have)
|
|
require.NoError(t, err)
|
|
|
|
result, err = ParseFIDOPublicKey(keyBytes)
|
|
} else {
|
|
keyBytes = DeriveEC2P256PublicKeyFromPrivateKey(t, tc.have)
|
|
result, err = ParseFIDOPublicKey(keyBytes)
|
|
}
|
|
|
|
assert.Equal(t, tc.expected, result)
|
|
|
|
if tc.err != "" {
|
|
assert.EqualError(t, err, tc.err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
|
|
key, err := result.ToECDSA()
|
|
require.NoError(t, err)
|
|
|
|
assert.NotNil(t, key)
|
|
|
|
assert.Equal(t, tc.tpmcurve, result.TPMCurveID())
|
|
|
|
data := MustConstructSignedData(t, tc.clientDataJSON, tc.authenticatorData)
|
|
signature := MustDecodeHex(t, tc.signature)
|
|
|
|
ok, err := VerifySignature(result, data, signature)
|
|
assert.NoError(t, err)
|
|
assert.True(t, ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func MustConstructSignedData(t *testing.T, hexClientDataJSON, hexAuthenticatorData string) []byte {
|
|
clientDataJSON := MustDecodeHex(t, hexClientDataJSON)
|
|
authenticatorData := MustDecodeHex(t, hexAuthenticatorData)
|
|
|
|
sum := sha256.Sum256(clientDataJSON)
|
|
|
|
data := make([]byte, 0, len(authenticatorData)+len(sum))
|
|
data = append(data, authenticatorData...)
|
|
data = append(data, sum[:]...)
|
|
|
|
return data
|
|
}
|
|
|
|
func MustDecodeHex(t *testing.T, s string) []byte {
|
|
b, err := hex.DecodeString(s)
|
|
require.NoError(t, err)
|
|
|
|
return b
|
|
}
|
|
|
|
func DeriveEC2P256PublicKeyFromPrivateKey(t *testing.T, keyHex string) []byte {
|
|
key, err := hex.DecodeString(keyHex)
|
|
require.NoError(t, err)
|
|
require.Len(t, key, 32)
|
|
|
|
curve := ecdh.P256()
|
|
|
|
private, err := curve.NewPrivateKey(key)
|
|
require.NoError(t, err)
|
|
|
|
public, ok := private.Public().(*ecdh.PublicKey)
|
|
require.True(t, ok)
|
|
|
|
return public.Bytes()
|
|
}
|