/
public_key.go
105 lines (91 loc) · 1.94 KB
/
public_key.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package webauthn
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
"hash"
"math/big"
"github.com/fxamacker/cbor/v2"
)
func decodeKey(data []byte) (PublicKey, error) {
publicKeyData := publicKeyData{}
err := cbor.Unmarshal(data, &publicKeyData)
if err != nil {
return nil, err
}
switch publicKeyData.KeyType {
case 2:
ec2PublicKey := ec2PublicKey{}
err := cbor.Unmarshal(data, &ec2PublicKey)
if err != nil {
return nil, err
}
ec2PublicKey.publicKeyData = publicKeyData
return &ec2PublicKey, nil
default:
return nil, fmt.Errorf("invalid keyType")
}
}
type publicKeyData struct {
KeyType int64 `cbor:"1,keyasint" json:"kty"`
Alg int64 `cbor:"3,keyasint" json:"alg"`
}
func (k *publicKeyData) Algorithm() int {
return int(k.Alg)
}
func (k *publicKeyData) GetHashFunc() func() hash.Hash {
switch k.Alg {
case -7:
return crypto.SHA256.New
case -35:
return crypto.SHA384.New
case -36:
return crypto.SHA512.New
default:
// TODO: proper error handling
return nil
}
}
type ec2PublicKey struct {
publicKeyData
Curve elliptic.Curve
X *big.Int
Y *big.Int
}
func (k *ec2PublicKey) UnmarshalCBOR(data []byte) error {
type ec2Data struct {
publicKeyData
Curve int64 `cbor:"-1,keyasint" json:"crv"`
X []byte `cbor:"-2,keyasint" json:"x"`
Y []byte `cbor:"-3,keyasint" json:"y"`
}
cborData := ec2Data{}
err := cbor.Unmarshal(data, &cborData)
if err != nil {
return err
}
switch cborData.Curve {
case 1:
k.Curve = elliptic.P256()
case 2:
k.Curve = elliptic.P384()
case 3:
k.Curve = elliptic.P521()
default:
k.Curve = elliptic.P256()
}
k.X = big.NewInt(0).SetBytes(cborData.X)
k.Y = big.NewInt(0).SetBytes(cborData.Y)
return nil
}
func (k *ec2PublicKey) Verify(signature []byte, data []byte) bool {
key := ecdsa.PublicKey{
Curve: k.Curve,
X: k.X,
Y: k.Y,
}
hash := k.GetHashFunc()()
hash.Write(data)
return ecdsa.VerifyASN1(&key, hash.Sum(nil), signature)
}