-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
ecdsa.go
120 lines (99 loc) · 3.14 KB
/
ecdsa.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package jwk
import (
"crypto/ecdsa"
"crypto/elliptic"
"math/big"
"github.com/pkg/errors"
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
)
func newECDSAPublicKey(key *ecdsa.PublicKey) (*ECDSAPublicKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.EC)
if err != nil {
return nil, errors.Wrapf(err, "Failed to set Key Type")
}
return &ECDSAPublicKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
func newECDSAPrivateKey(key *ecdsa.PrivateKey) (*ECDSAPrivateKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.EC)
if err != nil {
return nil, errors.Wrapf(err, "Failed to set Key Type")
}
return &ECDSAPrivateKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
// Materialize returns the EC-DSA public key represented by this JWK
func (k ECDSAPublicKey) Materialize() (interface{}, error) {
return k.key, nil
}
// Materialize returns the EC-DSA private key represented by this JWK
func (k ECDSAPrivateKey) Materialize() (interface{}, error) {
return k.key, nil
}
// GenerateKey creates a ECDSAPublicKey from JWK format
func (k *ECDSAPublicKey) GenerateKey(keyJSON *RawKeyJSON) error {
var x, y big.Int
if keyJSON.X == nil || keyJSON.Y == nil || keyJSON.Crv == "" {
return errors.Errorf("Missing mandatory key parameters X, Y or Crv")
}
x.SetBytes(keyJSON.X.Bytes())
y.SetBytes(keyJSON.Y.Bytes())
var curve elliptic.Curve
switch keyJSON.Crv {
case jwa.P256:
curve = elliptic.P256()
case jwa.P384:
curve = elliptic.P384()
case jwa.P521:
curve = elliptic.P521()
default:
return errors.Errorf(`invalid curve name %s`, keyJSON.Crv)
}
*k = ECDSAPublicKey{
StandardHeaders: &keyJSON.StandardHeaders,
key: &ecdsa.PublicKey{
Curve: curve,
X: &x,
Y: &y,
},
}
return nil
}
// GenerateKey creates a ECDSAPrivateKey from JWK format
func (k *ECDSAPrivateKey) GenerateKey(keyJSON *RawKeyJSON) error {
if keyJSON.D == nil {
return errors.Errorf("Missing mandatory key parameter D")
}
eCDSAPublicKey := &ECDSAPublicKey{}
err := eCDSAPublicKey.GenerateKey(keyJSON)
if err != nil {
return errors.Wrap(err, `failed to generate public key`)
}
dBytes := keyJSON.D.Bytes()
// The length of this octet string MUST be ceiling(log-base-2(n)/8)
// octets (where n is the order of the curve). This is because the private
// key d must be in the interval [1, n-1] so the bitlength of d should be
// no larger than the bitlength of n-1. The easiest way to find the octet
// length is to take bitlength(n-1), add 7 to force a carry, and shift this
// bit sequence right by 3, which is essentially dividing by 8 and adding
// 1 if there is any remainder. Thus, the private key value d should be
// output to (bitlength(n-1)+7)>>3 octets.
n := eCDSAPublicKey.key.Params().N
octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3
if octetLength-len(dBytes) != 0 {
return errors.Errorf("Failed to generate private key. Incorrect D value")
}
privateKey := &ecdsa.PrivateKey{
PublicKey: *eCDSAPublicKey.key,
D: (&big.Int{}).SetBytes(keyJSON.D.Bytes()),
}
k.key = privateKey
k.StandardHeaders = &keyJSON.StandardHeaders
return nil
}