1
// Copyright 2015 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
20
-----BEGIN RSA PRIVATE KEY-----
21
MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq
22
WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30
23
Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq
24
EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf
25
oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy
26
KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV
27
9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H
28
r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm
29
ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP
30
G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS
31
zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6
32
9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s
33
8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc
34
7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL
35
qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ
36
Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU
37
RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o
38
JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd
39
4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt
40
jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q
41
YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73
42
c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G
43
N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7
44
EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO
45
9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx
46
-----END RSA PRIVATE KEY-----
49
// This thumbprint is for the testKey defined above.
50
const testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
53
// openssl ecparam -name secp256k1 -genkey -noout
55
-----BEGIN EC PRIVATE KEY-----
56
MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49
57
AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5
58
QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ==
59
-----END EC PRIVATE KEY-----
61
// 1. opnessl ec -in key.pem -noout -text
62
// 2. remove first byte, 04 (the header); the rest is X and Y
63
// 3. covert each with: echo <val> | xxd -r -p | base64 | tr -d '=' | tr '/+' '_-'
64
testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ"
65
testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk"
66
// echo -n '{"crv":"P-256","kty":"EC","x":"<testKeyECPubX>","y":"<testKeyECPubY>"}' | \
67
// openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-'
68
testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU"
72
testKey *rsa.PrivateKey
73
testKeyEC *ecdsa.PrivateKey
77
d, _ := pem.Decode([]byte(testKeyPEM))
79
panic("no block found in testKeyPEM")
82
testKey, err = x509.ParsePKCS1PrivateKey(d.Bytes)
87
if d, _ = pem.Decode([]byte(testKeyECPEM)); d == nil {
88
panic("no block found in testKeyECPEM")
90
testKeyEC, err = x509.ParseECPrivateKey(d.Bytes)
96
func TestJWSEncodeJSON(t *testing.T) {
97
claims := struct{ Msg string }{"Hello JWS"}
98
// JWS signed with testKey and "nonce" as the nonce value
99
// JSON-serialized JWS fields are split for easier testing
101
// {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"}
102
protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" +
103
"IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" +
104
"SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" +
105
"QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" +
106
"VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" +
107
"NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" +
108
"QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" +
109
"bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" +
110
"ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" +
111
"b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" +
112
"UVEifSwibm9uY2UiOiJub25jZSJ9"
113
// {"Msg":"Hello JWS"}
114
payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ"
115
signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" +
116
"knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" +
117
"zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" +
118
"4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" +
119
"hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" +
120
"k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" +
121
"9IPLr8qZ7usYBKhEGwX3yq_eicAwBw"
124
b, err := jwsEncodeJSON(claims, testKey, "nonce")
128
var jws struct{ Protected, Payload, Signature string }
129
if err := json.Unmarshal(b, &jws); err != nil {
132
if jws.Protected != protected {
133
t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected)
135
if jws.Payload != payload {
136
t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload)
138
if jws.Signature != signature {
139
t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature)
143
func TestJWSEncodeJSONEC(t *testing.T) {
144
claims := struct{ Msg string }{"Hello JWS"}
146
b, err := jwsEncodeJSON(claims, testKeyEC, "nonce")
150
var jws struct{ Protected, Payload, Signature string }
151
if err := json.Unmarshal(b, &jws); err != nil {
155
if b, err = base64.RawURLEncoding.DecodeString(jws.Protected); err != nil {
156
t.Fatalf("jws.Protected: %v", err)
168
if err := json.Unmarshal(b, &head); err != nil {
169
t.Fatalf("jws.Protected: %v", err)
171
if head.Alg != "ES256" {
172
t.Errorf("head.Alg = %q; want ES256", head.Alg)
174
if head.Nonce != "nonce" {
175
t.Errorf("head.Nonce = %q; want nonce", head.Nonce)
177
if head.JWK.Crv != "P-256" {
178
t.Errorf("head.JWK.Crv = %q; want P-256", head.JWK.Crv)
180
if head.JWK.Kty != "EC" {
181
t.Errorf("head.JWK.Kty = %q; want EC", head.JWK.Kty)
183
if head.JWK.X != testKeyECPubX {
184
t.Errorf("head.JWK.X = %q; want %q", head.JWK.X, testKeyECPubX)
186
if head.JWK.Y != testKeyECPubY {
187
t.Errorf("head.JWK.Y = %q; want %q", head.JWK.Y, testKeyECPubY)
191
func TestJWKThumbprintRSA(t *testing.T) {
192
// Key example from RFC 7638
193
const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" +
194
"VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" +
195
"4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" +
196
"W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" +
197
"1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" +
198
"aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
199
const base64E = "AQAB"
200
const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
202
b, err := base64.RawURLEncoding.DecodeString(base64N)
204
t.Fatalf("Error parsing example key N: %v", err)
206
n := new(big.Int).SetBytes(b)
208
b, err = base64.RawURLEncoding.DecodeString(base64E)
210
t.Fatalf("Error parsing example key E: %v", err)
212
e := new(big.Int).SetBytes(b)
214
pub := &rsa.PublicKey{N: n, E: int(e.Uint64())}
215
th, err := JWKThumbprint(pub)
220
t.Errorf("thumbprint = %q; want %q", th, expected)
224
func TestJWKThumbprintEC(t *testing.T) {
225
// Key example from RFC 7520
226
// expected was computed with
227
// echo -n '{"crv":"P-521","kty":"EC","x":"<base64X>","y":"<base64Y>"}' | \
228
// openssl dgst -binary -sha256 | \
230
// tr -d '=' | tr '/+' '_-'
232
base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" +
233
"KqjqvjyekWF-7ytDyRXYgCF5cj0Kt"
234
base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" +
235
"QkAgDPrwQrJmbnX9cwlGfP-HqHZR1"
236
expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M"
239
b, err := base64.RawURLEncoding.DecodeString(base64X)
241
t.Fatalf("Error parsing example key X: %v", err)
243
x := new(big.Int).SetBytes(b)
245
b, err = base64.RawURLEncoding.DecodeString(base64Y)
247
t.Fatalf("Error parsing example key Y: %v", err)
249
y := new(big.Int).SetBytes(b)
251
pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y}
252
th, err := JWKThumbprint(pub)
257
t.Errorf("thumbprint = %q; want %q", th, expected)
261
func TestJWKThumbprintErrUnsupportedKey(t *testing.T) {
262
_, err := JWKThumbprint(struct{}{})
263
if err != ErrUnsupportedKey {
264
t.Errorf("err = %q; want %q", err, ErrUnsupportedKey)