This repository has been archived by the owner on May 24, 2023. It is now read-only.
/
crypto.go
165 lines (130 loc) · 4.51 KB
/
crypto.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package jwtware
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"encoding/base64"
"fmt"
"math/big"
)
const (
// HS256 represents a public cryptography key generated by a 256 bit HMAC algorithm.
HS256 = "HS256"
// HS384 represents a public cryptography key generated by a 384 bit HMAC algorithm.
HS384 = "HS384"
// HS512 represents a public cryptography key generated by a 512 bit HMAC algorithm.
HS512 = "HS512"
// ES256 represents a public cryptography key generated by a 256 bit ECDSA algorithm.
ES256 = "ES256"
// ES384 represents a public cryptography key generated by a 384 bit ECDSA algorithm.
ES384 = "ES384"
// ES512 represents a public cryptography key generated by a 512 bit ECDSA algorithm.
ES512 = "ES512"
// P256 represents a cryptographic elliptical curve type.
P256 = "P-256"
// P384 represents a cryptographic elliptical curve type.
P384 = "P-384"
// P521 represents a cryptographic elliptical curve type.
P521 = "P-521"
// RS256 represents a public cryptography key generated by a 256 bit RSA algorithm.
RS256 = "RS256"
// RS384 represents a public cryptography key generated by a 384 bit RSA algorithm.
RS384 = "RS384"
// RS512 represents a public cryptography key generated by a 512 bit RSA algorithm.
RS512 = "RS512"
// PS256 represents a public cryptography key generated by a 256 bit RSA algorithm.
PS256 = "PS256"
// PS384 represents a public cryptography key generated by a 384 bit RSA algorithm.
PS384 = "PS384"
// PS512 represents a public cryptography key generated by a 512 bit RSA algorithm.
PS512 = "PS512"
)
// getECDSA parses a JSONKey and turns it into an ECDSA public key.
func (j *rawJWK) getECDSA() (publicKey *ecdsa.PublicKey, err error) {
// Check if the key has already been computed.
if j.precomputed != nil {
var ok bool
if publicKey, ok = j.precomputed.(*ecdsa.PublicKey); ok {
return publicKey, nil
}
}
// Confirm everything needed is present.
if j.X == "" || j.Y == "" || j.Curve == "" {
return nil, fmt.Errorf("%w: ecdsa", errMissingAssets)
}
// Decode the X coordinate from Base64.
//
// According to RFC 7518, this is a Base64 URL unsigned integer.
// https://tools.ietf.org/html/rfc7518#section-6.3
var xCoordinate []byte
if xCoordinate, err = base64.RawURLEncoding.DecodeString(j.X); err != nil {
return nil, err
}
// Decode the Y coordinate from Base64.
var yCoordinate []byte
if yCoordinate, err = base64.RawURLEncoding.DecodeString(j.Y); err != nil {
return nil, err
}
// Create the ECDSA public key.
publicKey = &ecdsa.PublicKey{}
// Set the curve type.
var curve elliptic.Curve
switch j.Curve {
case P256:
curve = elliptic.P256()
case P384:
curve = elliptic.P384()
case P521:
curve = elliptic.P521()
}
publicKey.Curve = curve
// Turn the X coordinate into *big.Int.
//
// According to RFC 7517, these numbers are in big-endian format.
// https://tools.ietf.org/html/rfc7517#appendix-A.1
publicKey.X = big.NewInt(0).SetBytes(xCoordinate)
// Turn the Y coordinate into a *big.Int.
publicKey.Y = big.NewInt(0).SetBytes(yCoordinate)
// Keep the public key so it won't have to be computed every time.
j.precomputed = publicKey
return publicKey, nil
}
// getRSA parses a JSONKey and turns it into an RSA public key.
func (j *rawJWK) getRSA() (publicKey *rsa.PublicKey, err error) {
// Check if the key has already been computed.
if j.precomputed != nil {
var ok bool
if publicKey, ok = j.precomputed.(*rsa.PublicKey); ok {
return publicKey, nil
}
}
// Confirm everything needed is present.
if j.Exponent == "" || j.Modulus == "" {
return nil, fmt.Errorf("%w: rsa", errMissingAssets)
}
// Decode the exponent from Base64.
//
// According to RFC 7518, this is a Base64 URL unsigned integer.
// https://tools.ietf.org/html/rfc7518#section-6.3
var exponent []byte
if exponent, err = base64.RawURLEncoding.DecodeString(j.Exponent); err != nil {
return nil, err
}
// Decode the modulus from Base64.
var modulus []byte
if modulus, err = base64.RawURLEncoding.DecodeString(j.Modulus); err != nil {
return nil, err
}
// Create the RSA public key.
publicKey = &rsa.PublicKey{}
// Turn the exponent into an integer.
//
// According to RFC 7517, these numbers are in big-endian format.
// https://tools.ietf.org/html/rfc7517#appendix-A.1
publicKey.E = int(big.NewInt(0).SetBytes(exponent).Uint64())
// Turn the modulus into a *big.Int.
publicKey.N = big.NewInt(0).SetBytes(modulus)
// Keep the public key so it won't have to be computed every time.
j.precomputed = publicKey
return publicKey, nil
}