1
16
17 package jose
18
19 import (
20 "bytes"
21 "crypto"
22 "crypto/ecdsa"
23 "crypto/elliptic"
24 "crypto/rsa"
25 "crypto/sha1"
26 "crypto/sha256"
27 "crypto/x509"
28 "encoding/hex"
29 "math/big"
30 "reflect"
31 "strings"
32 "testing"
33
34 "github.com/google/go-cmp/cmp"
35 "github.com/stretchr/testify/assert"
36 "github.com/stretchr/testify/require"
37
38 "golang.org/x/crypto/ed25519"
39
40 "gopkg.in/square/go-jose.v2/json"
41 )
42
43
44 var testCertificates, _ = x509.ParseCertificates(fromBase64Bytes(`
45 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`))
84
85 func TestCurveSize(t *testing.T) {
86 size256 := curveSize(elliptic.P256())
87 size384 := curveSize(elliptic.P384())
88 size521 := curveSize(elliptic.P521())
89 if size256 != 32 {
90 t.Error("P-256 have 32 bytes")
91 }
92 if size384 != 48 {
93 t.Error("P-384 have 48 bytes")
94 }
95 if size521 != 66 {
96 t.Error("P-521 have 66 bytes")
97 }
98 }
99
100 func TestRoundtripRsaPrivate(t *testing.T) {
101 jwk, err := fromRsaPrivateKey(rsaTestKey)
102 if err != nil {
103 t.Error("problem constructing JWK from rsa key", err)
104 }
105
106 rsa2, err := jwk.rsaPrivateKey()
107 if err != nil {
108 t.Error("problem converting RSA private -> JWK", err)
109 }
110
111 if rsa2.N.Cmp(rsaTestKey.N) != 0 {
112 t.Error("RSA private N mismatch")
113 }
114 if rsa2.E != rsaTestKey.E {
115 t.Error("RSA private E mismatch")
116 }
117 if rsa2.D.Cmp(rsaTestKey.D) != 0 {
118 t.Error("RSA private D mismatch")
119 }
120 if len(rsa2.Primes) != 2 {
121 t.Error("RSA private roundtrip expected two primes")
122 }
123 if rsa2.Primes[0].Cmp(rsaTestKey.Primes[0]) != 0 {
124 t.Error("RSA private P mismatch")
125 }
126 if rsa2.Primes[1].Cmp(rsaTestKey.Primes[1]) != 0 {
127 t.Error("RSA private Q mismatch")
128 }
129 }
130
131 func TestRoundtripRsaPrivatePrecomputed(t *testing.T) {
132
133 localKey := &(*rsaTestKey)
134 localKey.Precompute()
135
136 jwk, err := fromRsaPrivateKey(localKey)
137 if err != nil {
138 t.Error("problem constructing JWK from rsa key", err)
139 }
140
141 rsa2, err := jwk.rsaPrivateKey()
142 if err != nil {
143 t.Error("problem converting RSA private -> JWK", err)
144 }
145
146 if rsa2.Precomputed.Dp == nil {
147 t.Error("RSA private Dp nil")
148 }
149 if rsa2.Precomputed.Dq == nil {
150 t.Error("RSA private Dq nil")
151 }
152 if rsa2.Precomputed.Qinv == nil {
153 t.Error("RSA private Qinv nil")
154 }
155
156 if rsa2.Precomputed.Dp.Cmp(localKey.Precomputed.Dp) != 0 {
157 t.Error("RSA private Dp mismatch")
158 }
159 if rsa2.Precomputed.Dq.Cmp(localKey.Precomputed.Dq) != 0 {
160 t.Error("RSA private Dq mismatch")
161 }
162 if rsa2.Precomputed.Qinv.Cmp(localKey.Precomputed.Qinv) != 0 {
163 t.Error("RSA private Qinv mismatch")
164 }
165 }
166
167 func TestRsaPrivateInsufficientPrimes(t *testing.T) {
168 brokenRsaPrivateKey := rsa.PrivateKey{
169 PublicKey: rsa.PublicKey{
170 N: rsaTestKey.N,
171 E: rsaTestKey.E,
172 },
173 D: rsaTestKey.D,
174 Primes: []*big.Int{rsaTestKey.Primes[0]},
175 }
176
177 _, err := fromRsaPrivateKey(&brokenRsaPrivateKey)
178 if err != ErrUnsupportedKeyType {
179 t.Error("expected unsupported key type error, got", err)
180 }
181 }
182
183 func TestRsaPrivateExcessPrimes(t *testing.T) {
184 brokenRsaPrivateKey := rsa.PrivateKey{
185 PublicKey: rsa.PublicKey{
186 N: rsaTestKey.N,
187 E: rsaTestKey.E,
188 },
189 D: rsaTestKey.D,
190 Primes: []*big.Int{
191 rsaTestKey.Primes[0],
192 rsaTestKey.Primes[1],
193 big.NewInt(3),
194 },
195 }
196
197 _, err := fromRsaPrivateKey(&brokenRsaPrivateKey)
198 if err != ErrUnsupportedKeyType {
199 t.Error("expected unsupported key type error, got", err)
200 }
201 }
202
203 func TestRoundtripEcPublic(t *testing.T) {
204 for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} {
205 jwk, err := fromEcPublicKey(&ecTestKey.PublicKey)
206
207 ec2, err := jwk.ecPublicKey()
208 if err != nil {
209 t.Error("problem converting ECDSA private -> JWK", i, err)
210 }
211
212 if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) {
213 t.Error("ECDSA private curve mismatch", i)
214 }
215 if ec2.X.Cmp(ecTestKey.X) != 0 {
216 t.Error("ECDSA X mismatch", i)
217 }
218 if ec2.Y.Cmp(ecTestKey.Y) != 0 {
219 t.Error("ECDSA Y mismatch", i)
220 }
221 }
222 }
223
224 func TestRoundtripEcPrivate(t *testing.T) {
225 for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} {
226 jwk, err := fromEcPrivateKey(ecTestKey)
227
228 ec2, err := jwk.ecPrivateKey()
229 if err != nil {
230 t.Fatalf("problem converting ECDSA private -> JWK for %#v: %s", ecTestKey, err)
231 }
232
233 if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) {
234 t.Error("ECDSA private curve mismatch", i)
235 }
236 if ec2.X.Cmp(ecTestKey.X) != 0 {
237 t.Error("ECDSA X mismatch", i)
238 }
239 if ec2.Y.Cmp(ecTestKey.Y) != 0 {
240 t.Error("ECDSA Y mismatch", i)
241 }
242 if ec2.D.Cmp(ecTestKey.D) != 0 {
243 t.Error("ECDSA D mismatch", i)
244 }
245 }
246 }
247
248 func TestRoundtripX509(t *testing.T) {
249 x5tSHA1 := sha1.Sum(testCertificates[0].Raw)
250 x5tSHA256 := sha256.Sum256(testCertificates[0].Raw)
251
252 cases := []struct {
253 name string
254 jwk JSONWebKey
255 }{
256 {
257 name: "all fields",
258 jwk: JSONWebKey{
259 Key: testCertificates[0].PublicKey,
260 KeyID: "bar",
261 Algorithm: "foo",
262 Certificates: testCertificates,
263 CertificateThumbprintSHA1: x5tSHA1[:],
264 CertificateThumbprintSHA256: x5tSHA256[:],
265 },
266 },
267 {
268 name: "no optional x5ts",
269 jwk: JSONWebKey{
270 Key: testCertificates[0].PublicKey,
271 KeyID: "bar",
272 Algorithm: "foo",
273 Certificates: testCertificates,
274 },
275 },
276 {
277 name: "no x5t",
278 jwk: JSONWebKey{
279 Key: testCertificates[0].PublicKey,
280 KeyID: "bar",
281 Algorithm: "foo",
282 Certificates: testCertificates,
283 CertificateThumbprintSHA256: x5tSHA256[:],
284 },
285 },
286 {
287 name: "no x5t#S256",
288 jwk: JSONWebKey{
289 Key: testCertificates[0].PublicKey,
290 KeyID: "bar",
291 Algorithm: "foo",
292 Certificates: testCertificates,
293 CertificateThumbprintSHA1: x5tSHA1[:],
294 },
295 },
296 }
297
298 for _, c := range cases {
299 t.Run(c.name, func(t *testing.T) {
300 jsonbar, err := c.jwk.MarshalJSON()
301 require.NoError(t, err)
302
303 var jwk2 JSONWebKey
304 err = jwk2.UnmarshalJSON(jsonbar)
305 require.NoError(t, err)
306
307 if !reflect.DeepEqual(testCertificates, jwk2.Certificates) {
308 t.Error("Certificates not equal", c.jwk.Certificates, jwk2.Certificates)
309 }
310
311 jsonbar2, err := jwk2.MarshalJSON()
312 require.NoError(t, err)
313
314 require.Empty(t, cmp.Diff(jsonbar, jsonbar2))
315 if !bytes.Equal(jsonbar, jsonbar2) {
316 t.Error("roundtrip should not lose information")
317 }
318 })
319 }
320 }
321
322 func TestRoundtripX509Hex(t *testing.T) {
323 var hexJWK = `{
324 "kty":"RSA",
325 "kid":"bar",
326 "alg":"foo",
327 "n":"u7LUr30Mhrh8N79-H4rKiHQ123q6xaBZPYbf1nV4GM19rizSnbEfyebG1kpfCv-XY6c499XiM6lOvcPL-0goTOcfW6Lg7AAR895GbnMeXEmnxICaI8rAZHK6t1WPmiWp82y_qhK2F_pYUaT3GSuiTFiMGq_GNwdpWuMlsInnnMNv1nxFbxtDPwzmCp0fEBxbH5d1EtXZwTPOHMyj8rfa-NIA5Nl4h_5RrbOWveKwBr26_CDAratJgOWh9xcd5g0ot_uDGcMoAgB6xeTuYklfaxCPptvu49kvoxw1J71fp6nKW_ZuhDRAp2F_BQ9inKpTo05sPLJg8tPTdjaeouOuJQ",
328 "e":"AQAB",
329 "x5c":[
330 "MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKdsR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafEgJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieecw2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a94rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+jHDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGjTzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAjhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloSaa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObiqdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIU=",
331 "MIIDUzCCAjugAwIBAgIJAKg+LQlirffwMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1yb290MB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLXJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKOEoSiNjMQ8/zUFcQW89LWw+UeTXKGwNDSpGjyi8jBKZ1lWPbnMmrjI6DZ9ReevHHzqBdKZt+9NFPFEz7djDMRByIuJhRvzhfFBflaIdSeNk2+NpUaFuUUUd6IIePu0AdRveJ8ZGHXRwCeEDIVCZS4oBYPHOhX/zMWDg8vSO4pSxTjGc7I8fHxaUSkVzUBbeO9T/1eFk0m2uxs3UziUck2X/8YqRd+p/EaBED78nXvKRALAguKAzqxIgk3ccPK0SVQFNFq+eV1/qo8coueQuqMpCAvwVkfpVKhneyC2NlMrfzlcZZbfG/irlSjQn5+ExZX4Isy1pCUbOiVfSrsCdtAgMBAAGjJjAkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCLEJU65vTU+oLbNHLOCR6fALrbjK7xsi6SFDpSXBMm74MWsy3myDBmXpOcN8hCYgsgivUXTQz9ynXP/pzOj4b83zzlaOfPtLTAmMhKWVV4Q85mrDQz+HzG4lKXM78eTsD8PyrocA/tSE7mVEJ0Jal4E2KI/Z9/fqpYFLB6LFlx5n83ehXM/egA0l4OeCC9nBKCeNUN3sIQO85lljyzAJdtWnsdoWogJs6qjcV8n2U5xjZxN5ZFdclYLjq6g2cjEXXMQxb8b7ZhHjLWFdjHP85UvXHK3DpK3JmUg8bYS7t1DJffDQNjawhlsMycKZN+r0ND0Um4m7AjGqxbKT/M2yKF"
332 ],
333 "x5t": "MDYxMjU0ZmRmNzIwZjJjMGU0YmQzZjMzMzlhMmZlNTM1MGExNWRlMQ",
334 "x5t#S256": "MjAzMjRhNGI5MmYxMjI2OGVmOWFlMDI1ZmQ1Yzc5ZDE1OGZmNzQ1NzQwMDkyMTk2ZTgzNTNjMDAzMTUxNzUxMQ"
335 }`
336
337
338 var output = `{
339 "kty":"RSA",
340 "kid":"bar",
341 "alg":"foo",
342 "n":"u7LUr30Mhrh8N79-H4rKiHQ123q6xaBZPYbf1nV4GM19rizSnbEfyebG1kpfCv-XY6c499XiM6lOvcPL-0goTOcfW6Lg7AAR895GbnMeXEmnxICaI8rAZHK6t1WPmiWp82y_qhK2F_pYUaT3GSuiTFiMGq_GNwdpWuMlsInnnMNv1nxFbxtDPwzmCp0fEBxbH5d1EtXZwTPOHMyj8rfa-NIA5Nl4h_5RrbOWveKwBr26_CDAratJgOWh9xcd5g0ot_uDGcMoAgB6xeTuYklfaxCPptvu49kvoxw1J71fp6nKW_ZuhDRAp2F_BQ9inKpTo05sPLJg8tPTdjaeouOuJQ",
343 "e":"AQAB",
344 "x5c":[
345 "MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKdsR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafEgJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieecw2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a94rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+jHDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGjTzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAjhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloSaa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObiqdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIU=",
346 "MIIDUzCCAjugAwIBAgIJAKg+LQlirffwMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1yb290MB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLXJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKOEoSiNjMQ8/zUFcQW89LWw+UeTXKGwNDSpGjyi8jBKZ1lWPbnMmrjI6DZ9ReevHHzqBdKZt+9NFPFEz7djDMRByIuJhRvzhfFBflaIdSeNk2+NpUaFuUUUd6IIePu0AdRveJ8ZGHXRwCeEDIVCZS4oBYPHOhX/zMWDg8vSO4pSxTjGc7I8fHxaUSkVzUBbeO9T/1eFk0m2uxs3UziUck2X/8YqRd+p/EaBED78nXvKRALAguKAzqxIgk3ccPK0SVQFNFq+eV1/qo8coueQuqMpCAvwVkfpVKhneyC2NlMrfzlcZZbfG/irlSjQn5+ExZX4Isy1pCUbOiVfSrsCdtAgMBAAGjJjAkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCLEJU65vTU+oLbNHLOCR6fALrbjK7xsi6SFDpSXBMm74MWsy3myDBmXpOcN8hCYgsgivUXTQz9ynXP/pzOj4b83zzlaOfPtLTAmMhKWVV4Q85mrDQz+HzG4lKXM78eTsD8PyrocA/tSE7mVEJ0Jal4E2KI/Z9/fqpYFLB6LFlx5n83ehXM/egA0l4OeCC9nBKCeNUN3sIQO85lljyzAJdtWnsdoWogJs6qjcV8n2U5xjZxN5ZFdclYLjq6g2cjEXXMQxb8b7ZhHjLWFdjHP85UvXHK3DpK3JmUg8bYS7t1DJffDQNjawhlsMycKZN+r0ND0Um4m7AjGqxbKT/M2yKF"
347 ],
348 "x5t":"BhJU_fcg8sDkvT8zOaL-U1ChXeE",
349 "x5t#S256":"IDJKS5LxImjvmuAl_Vx50Vj_dFdACSGW6DU8ADFRdRE"
350 }`
351
352 var jwk2 JSONWebKey
353 err := jwk2.UnmarshalJSON([]byte(hexJWK))
354 require.NoError(t, err)
355
356 js, err := jwk2.MarshalJSON()
357 require.NoError(t, err)
358
359 var j1, j2 map[string]interface{}
360 require.NoError(t, json.Unmarshal(js, &j1))
361 require.NoError(t, json.Unmarshal([]byte(output), &j2))
362 require.Empty(t, cmp.Diff(j1, j2))
363 }
364
365 func TestInvalidThumbprintsX509(t *testing.T) {
366
367 jwk := JSONWebKey{
368 Key: rsaTestKey,
369 KeyID: "bar",
370 Algorithm: "foo",
371 Certificates: testCertificates,
372 CertificateThumbprintSHA1: []byte{0x01},
373 CertificateThumbprintSHA256: []byte{0x02},
374 }
375
376 _, err := jwk.MarshalJSON()
377 if err == nil {
378 t.Error("should not marshal JWK with too short thumbprints")
379 }
380
381
382 sha1sum := sha1.Sum(nil)
383 jwk.CertificateThumbprintSHA1 = sha1sum[:]
384 sha256sum := sha256.Sum256(nil)
385 jwk.CertificateThumbprintSHA256 = sha256sum[:]
386
387 _, err = jwk.MarshalJSON()
388 if err == nil {
389 t.Error("should not marshal JWK with mismatched thumbprints")
390 }
391
392
393 shortThumbprints := []byte(`{
394 "kty": "RSA",
395 "kid": "bar",
396 "alg": "foo",
397 "n": "wN3v274Fr7grvZdXirEGkHlhYKh72gP-46MxQilMgANi6EaX2m0mYiMC60X1UmOhQNoVW0ItthMME-CGh7haA_Jeou_L6-EVOz-7lGu_J06VRl-mgkQZO0sYSkRY8Rsu7TW-pgnWWwZjSdgxN2gq7DvjjC4RLroV94Lgrb2Qwx6J5bZNOfj3pHmEWZ_eRFEH73Ct5RxwUKtNKx_XAmodZn9oFXBlN7F2Js-4DO-8UgbS7ALkTmhDzClT1GPfdLMusmXw4BXyV72vBOWrbUTdwk4pG8ahPQ0cGQ1ubaAmro_k3Bxg06voWPhXx7ALrpzmZCzr6YY-c5Y5rku4qXh-HQ",
398 "e": "AQAB",
399 "d": "RRM3xMvZ3YVopQ5_G_0rDLNsXOH6-apUr9LS4Y9JBtAvrGEcIe7VwHApq3ny0v870a5J19Vr6boIqVXQ2Or90kwL-O9JacHDiOTamd29KKbMb9fyGtWo88OBf5fbAv9pXyvQjEcZrqArD1eOyPlV5iXM6XfWT5X2KB-HuLIcFsVJSEb0yw943dEhZKkv2fySlVtKEhji2CfkMWP438G8auxwFPNIXmuvA1xvcAepOiI9I1Wy17txLOQg8MYBl98F7mxPUMpL3jm8-CSuxpknucFuFIrqIsbGmukSNp14APcu7bN0cJW5uVW-XtGbuioJkPjU2YJgfhIeMI8kuny5QQ",
400 "p": "yRNzbsreZK9MqJgbVsbl7SX2MyyJW_JnFKGdyrXzMqCtzRS7XJ9L3SwdDG_ERgSCkT9PP2dax9fS7RghHNJIU_NlPnJqzBPvPyzbjho7hcGYGDU2UO8E3SBP1WKm1SnlYhm1uHwrHudAO0D5jhVYQfRwem-zX3QibrsxEyxSELM",
401 "q": "9Yx0zzrhSxdE8ubryZfOyOw6cSbUdyCMgY3IFmEdb_UDZOQNMDCFj2RS1g6yFGKuaFqnL9ZRnmprikf20w-mu-LtLU_l0eK4U7pbAoB--pxFP_O6Yk3ZBu_YJ3FpimyX1v4OVZT-JOU_caKiTrPnlw3P7KbEc9iu_bOc8dE-_e8",
402 "dp": "GwiFbXDS44B58vS4QDtvcCm5Zvnm4bi-SRTNbRJ3Rug5Vagi5Hn6LhsfMKvaHHvAvhxf4CtaFiIbFos28HQJC1he1T12xEct1DWIsxstw3bapu6IhesMoVoVwZ-IxIHkeALy3oG7HmWCyjSbGJIgEoX1lVBtMjkf4_lAyM4dnmc",
403 "dq": "XYtXyMbOo3PG8Z6lfxRVU9gi346CbKu6u3RPIK94rnkyBNKYb55ck2cN47yPfRKnDNxUSvYj--zg8To_PuL8iyGFZ7jDffUYcdVR7J8VQNYdz6JDhEXSA0GGIGilY3XBVsdMoK_1Lgsj41-o48DH3pUFfEuAFf4blE1D4h_sFoM",
404 "qi": "CN3q5TMZO06DlK4onrJ687bPp2GE-fynd7ADPdf1ek3cXbeaFApVNp4w-i8zr7IVugQohn01i_jnkymw4UN-acoIzX2sGYhgDm6le1jyfv28bQ_Z5hT0rFNlPfGyK0kkPYUTxZ4ZCKpCYJT9C1nH58Yu4xFk4VR1zhULegjCCd4",
405 "x5c": [
406 "MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKdsR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafEgJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieecw2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a94rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+jHDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGjTzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAjhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloSaa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObiqdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIU="
407 ],
408 "x5t": "BhJU_fcg8sDkvT8zOaL-U1C",
409 "x5t#S256": "IDJKS5LxImjvmuAl_Vx50Vj_dFdACSGW6DU8ADF"
410 }`)
411
412
413 mismatchedThumbprints := []byte(`{
414 "kty": "RSA",
415 "kid": "bar",
416 "alg": "foo",
417 "n": "wN3v274Fr7grvZdXirEGkHlhYKh72gP-46MxQilMgANi6EaX2m0mYiMC60X1UmOhQNoVW0ItthMME-CGh7haA_Jeou_L6-EVOz-7lGu_J06VRl-mgkQZO0sYSkRY8Rsu7TW-pgnWWwZjSdgxN2gq7DvjjC4RLroV94Lgrb2Qwx6J5bZNOfj3pHmEWZ_eRFEH73Ct5RxwUKtNKx_XAmodZn9oFXBlN7F2Js-4DO-8UgbS7ALkTmhDzClT1GPfdLMusmXw4BXyV72vBOWrbUTdwk4pG8ahPQ0cGQ1ubaAmro_k3Bxg06voWPhXx7ALrpzmZCzr6YY-c5Y5rku4qXh-HQ",
418 "e": "AQAB",
419 "d": "RRM3xMvZ3YVopQ5_G_0rDLNsXOH6-apUr9LS4Y9JBtAvrGEcIe7VwHApq3ny0v870a5J19Vr6boIqVXQ2Or90kwL-O9JacHDiOTamd29KKbMb9fyGtWo88OBf5fbAv9pXyvQjEcZrqArD1eOyPlV5iXM6XfWT5X2KB-HuLIcFsVJSEb0yw943dEhZKkv2fySlVtKEhji2CfkMWP438G8auxwFPNIXmuvA1xvcAepOiI9I1Wy17txLOQg8MYBl98F7mxPUMpL3jm8-CSuxpknucFuFIrqIsbGmukSNp14APcu7bN0cJW5uVW-XtGbuioJkPjU2YJgfhIeMI8kuny5QQ",
420 "p": "yRNzbsreZK9MqJgbVsbl7SX2MyyJW_JnFKGdyrXzMqCtzRS7XJ9L3SwdDG_ERgSCkT9PP2dax9fS7RghHNJIU_NlPnJqzBPvPyzbjho7hcGYGDU2UO8E3SBP1WKm1SnlYhm1uHwrHudAO0D5jhVYQfRwem-zX3QibrsxEyxSELM",
421 "q": "9Yx0zzrhSxdE8ubryZfOyOw6cSbUdyCMgY3IFmEdb_UDZOQNMDCFj2RS1g6yFGKuaFqnL9ZRnmprikf20w-mu-LtLU_l0eK4U7pbAoB--pxFP_O6Yk3ZBu_YJ3FpimyX1v4OVZT-JOU_caKiTrPnlw3P7KbEc9iu_bOc8dE-_e8",
422 "dp": "GwiFbXDS44B58vS4QDtvcCm5Zvnm4bi-SRTNbRJ3Rug5Vagi5Hn6LhsfMKvaHHvAvhxf4CtaFiIbFos28HQJC1he1T12xEct1DWIsxstw3bapu6IhesMoVoVwZ-IxIHkeALy3oG7HmWCyjSbGJIgEoX1lVBtMjkf4_lAyM4dnmc",
423 "dq": "XYtXyMbOo3PG8Z6lfxRVU9gi346CbKu6u3RPIK94rnkyBNKYb55ck2cN47yPfRKnDNxUSvYj--zg8To_PuL8iyGFZ7jDffUYcdVR7J8VQNYdz6JDhEXSA0GGIGilY3XBVsdMoK_1Lgsj41-o48DH3pUFfEuAFf4blE1D4h_sFoM",
424 "qi": "CN3q5TMZO06DlK4onrJ687bPp2GE-fynd7ADPdf1ek3cXbeaFApVNp4w-i8zr7IVugQohn01i_jnkymw4UN-acoIzX2sGYhgDm6le1jyfv28bQ_Z5hT0rFNlPfGyK0kkPYUTxZ4ZCKpCYJT9C1nH58Yu4xFk4VR1zhULegjCCd4",
425 "x5c": [
426 "MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYxMDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKdsR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafEgJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieecw2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a94rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+jHDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGjTzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAjhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloSaa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObiqdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIU="
427 ],
428 "x5t": "BhJU_fcg8sDkvT8zOaL-U1ChXeX",
429 "x5t#S256": "IDJKS5LxImjvmuAl_Vx50Vj_dFdACSGW6DU8ADFRdRX"
430 }`)
431
432 var jwk2 JSONWebKey
433 err = jwk2.UnmarshalJSON(mismatchedThumbprints)
434 if err == nil {
435 t.Error("should not unmarshal JWK with mismatched thumbprints")
436 }
437
438 err = jwk2.UnmarshalJSON(shortThumbprints)
439 if err == nil {
440 t.Error("should not unmarshal JWK with too short thumbprints")
441 }
442 }
443
444 func TestKeyMismatchX509(t *testing.T) {
445 x5tSHA1 := sha1.Sum(testCertificates[0].Raw)
446 x5tSHA256 := sha256.Sum256(testCertificates[0].Raw)
447
448 jwk := JSONWebKey{
449 KeyID: "bar",
450 Algorithm: "foo",
451 Certificates: testCertificates,
452 CertificateThumbprintSHA1: x5tSHA1[:],
453 CertificateThumbprintSHA256: x5tSHA256[:],
454 }
455
456 for _, key := range []interface{}{
457
458 ecTestKey256,
459 ecTestKey256.Public(),
460 ecTestKey384,
461 ecTestKey384.Public(),
462 ecTestKey521,
463 ecTestKey521.Public(),
464 rsaTestKey,
465 rsaTestKey.Public(),
466 ed25519PrivateKey,
467 ed25519PrivateKey.Public(),
468 } {
469 jwk.Key = key
470 raw, _ := jwk.MarshalJSON()
471
472 var jwk2 JSONWebKey
473 err := jwk2.UnmarshalJSON(raw)
474 if err == nil {
475 t.Error("should not unmarshal JWK with key/cert mismatch")
476 }
477 }
478 }
479
480 func TestMarshalUnmarshal(t *testing.T) {
481 kid := "DEADBEEF"
482
483 for i, key := range []interface{}{
484 ecTestKey256,
485 ecTestKey256.Public(),
486 ecTestKey384,
487 ecTestKey384.Public(),
488 ecTestKey521,
489 ecTestKey521.Public(),
490 rsaTestKey,
491 rsaTestKey.Public(),
492 ed25519PrivateKey,
493 ed25519PrivateKey.Public(),
494 } {
495 for _, use := range []string{"", "sig", "enc"} {
496 jwk := JSONWebKey{Key: key, KeyID: kid, Algorithm: "foo"}
497 if use != "" {
498 jwk.Use = use
499 }
500
501 jsonbar, err := jwk.MarshalJSON()
502 if err != nil {
503 t.Error("problem marshaling", i, err)
504 }
505
506 var jwk2 JSONWebKey
507 err = jwk2.UnmarshalJSON(jsonbar)
508 if err != nil {
509 t.Fatal("problem unmarshalling", i, err)
510 }
511
512 jsonbar2, err := jwk2.MarshalJSON()
513 if err != nil {
514 t.Fatal("problem marshaling", i, err)
515 }
516
517 if !bytes.Equal(jsonbar, jsonbar2) {
518 t.Error("roundtrip should not lose information", i)
519 }
520 if jwk2.KeyID != kid {
521 t.Error("kid did not roundtrip JSON marshalling", i)
522 }
523
524 if jwk2.Algorithm != "foo" {
525 t.Error("alg did not roundtrip JSON marshalling", i)
526 }
527
528 if jwk2.Use != use {
529 t.Error("use did not roundtrip JSON marshalling", i)
530 }
531 }
532 }
533 }
534
535 func TestMarshalNonPointer(t *testing.T) {
536 type EmbedsKey struct {
537 Key JSONWebKey
538 }
539
540 keyJSON := []byte(`{
541 "e": "AQAB",
542 "kty": "RSA",
543 "n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw"
544 }`)
545 var parsedKey JSONWebKey
546 err := json.Unmarshal(keyJSON, &parsedKey)
547 if err != nil {
548 t.Errorf("Error unmarshalling key: %v", err)
549 return
550 }
551 ek := EmbedsKey{
552 Key: parsedKey,
553 }
554 out, err := json.Marshal(ek)
555 if err != nil {
556 t.Errorf("Error marshalling JSON: %v", err)
557 return
558 }
559 expected := "{\"Key\":{\"kty\":\"RSA\",\"n\":\"vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw\",\"e\":\"AQAB\"}}"
560 if string(out) != expected {
561 t.Error("Failed to marshal embedded non-pointer JWK properly:", string(out))
562 }
563 }
564
565 func TestMarshalUnmarshalInvalid(t *testing.T) {
566
567
568 invalidCoord := make([]byte, curveSize(ecTestKey256.Curve)+1)
569 invalidCoord[0] = 1
570
571 keys := []interface{}{
572
573 &rsa.PrivateKey{},
574 &ecdsa.PrivateKey{},
575
576 &ecdsa.PrivateKey{
577 PublicKey: ecdsa.PublicKey{
578
579 Curve: elliptic.P256(),
580 },
581 },
582 &ecdsa.PrivateKey{
583 PublicKey: ecdsa.PublicKey{
584
585 Curve: nil,
586 X: ecTestKey256.X,
587 Y: ecTestKey256.Y,
588 },
589 },
590 &ecdsa.PrivateKey{
591
592 PublicKey: ecTestKey256.PublicKey,
593 },
594 &ecdsa.PrivateKey{
595
596 PublicKey: ecdsa.PublicKey{
597 Curve: ecTestKey256.Curve,
598 X: big.NewInt(0).SetBytes(invalidCoord),
599 Y: big.NewInt(0).SetBytes(invalidCoord),
600 },
601 D: ecTestKey256.D,
602 },
603 nil,
604 }
605
606 for i, key := range keys {
607 jwk := JSONWebKey{Key: key}
608 _, err := jwk.MarshalJSON()
609 if err == nil {
610 t.Error("managed to serialize invalid key", i)
611 }
612 }
613 }
614
615 func TestWebKeyVectorsInvalid(t *testing.T) {
616 keys := []string{
617
618 "{X",
619
620 "{}",
621
622 `{"kty":"RSA"}`,
623 `{"kty":"RSA","e":""}`,
624 `{"kty":"RSA","e":"XXXX"}`,
625 `{"kty":"RSA","d":"XXXX"}`,
626
627 `{"kty":"EC","crv":"ABC"}`,
628 `{"kty":"EC","crv":"P-256"}`,
629 `{"kty":"EC","crv":"P-256","d":"XXX"}`,
630 `{"kty":"EC","crv":"ABC","d":"dGVzdA","x":"dGVzdA"}`,
631 `{"kty":"EC","crv":"P-256","d":"dGVzdA","x":"dGVzdA"}`,
632 }
633
634 for _, key := range keys {
635 var jwk2 JSONWebKey
636 err := jwk2.UnmarshalJSON([]byte(key))
637 if err == nil {
638 t.Error("managed to parse invalid key:", key)
639 }
640 }
641 }
642
643
644 var cookbookJWKs = []string{
645
646 stripWhitespace(`{
647 "kty": "EC",
648 "kid": "bilbo.baggins@hobbiton.example",
649 "use": "sig",
650 "crv": "P-521",
651 "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9
652 A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt",
653 "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy
654 SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1"
655 }`),
656
657
658 stripWhitespace(`{
659 "kty": "OKP",
660 "crv": "Ed25519",
661 "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
662 "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A"
663 }`),
664
665
666 stripWhitespace(`{
667 "kty": "EC",
668 "kid": "bilbo.baggins@hobbiton.example",
669 "use": "sig",
670 "crv": "P-521",
671 "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9
672 A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt",
673 "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy
674 SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1",
675 "d": "AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zb
676 KipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt"
677 }`),
678
679
680 stripWhitespace(`{
681 "kty": "RSA",
682 "kid": "bilbo.baggins@hobbiton.example",
683 "use": "sig",
684 "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT
685 -O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqV
686 wGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-
687 oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde
688 3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuC
689 LqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5g
690 HdrNP5zw",
691 "e": "AQAB"
692 }`),
693
694
695 stripWhitespace(`{"kty":"RSA",
696 "kid":"juliet@capulet.lit",
697 "use":"enc",
698 "n":"t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy
699 O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP
700 8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0
701 Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X
702 OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1
703 _I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q",
704 "e":"AQAB",
705 "d":"GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS
706 NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U
707 vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu
708 ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu
709 rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a
710 hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ",
711 "p":"2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf
712 QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8
713 UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws",
714 "q":"1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6I
715 edis4S7B_coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYK
716 rYl52ziqK0E_ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s",
717 "dp":"KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_MOzqYAJMcLMZtbUtwKqvVDq3
718 tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_lhqigI4y_kqS1w
719 Y52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c",
720 "dq":"AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9
721 GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy
722 mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots",
723 "qi":"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq
724 abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o
725 Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"}`),
726
727
728 stripWhitespace(`{"kty":"RSA",
729 "use":"sig",
730 "kid":"1b94c",
731 "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08
732 PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q
733 u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a
734 YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH
735 MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv
736 VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ",
737 "e":"AQAB",
738 "x5c":
739 ["MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB
740 gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD
741 VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1
742 wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg
743 NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV
744 QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w
745 YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH
746 YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66
747 s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6
748 SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn
749 fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq
750 PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk
751 aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA
752 QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL
753 +9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1
754 zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL
755 2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo
756 4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq
757 gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA=="]}`),
758 }
759
760
761 var cookbookJWKThumbprints = []string{
762 "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793",
763 "90facafea9b1556698540f70c0117a22ea37bd5cf3ed3c47093c1707282b4b89",
764 "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793",
765 "f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932",
766 "0fc478f8579325fcee0d4cbc6d9d1ce21730a6e97e435d6008fb379b0ebe47d4",
767 "0ddb05bfedbec2070fa037324ba397396561d3425d6d69245570c261dc49dee3",
768 }
769
770 func TestWebKeyVectorsValid(t *testing.T) {
771 for _, key := range cookbookJWKs {
772 var jwk2 JSONWebKey
773 err := jwk2.UnmarshalJSON([]byte(key))
774 if err != nil {
775 t.Error("unable to parse valid key:", key, err)
776 }
777 }
778 }
779
780 func TestEd25519Serialization(t *testing.T) {
781 jwk := JSONWebKey{
782 Key: ed25519PrivateKey,
783 }
784 serialized, _ := json.Marshal(jwk)
785
786 var jwk2 JSONWebKey
787 json.Unmarshal(serialized, &jwk2)
788
789 assert.True(t, bytes.Equal(
790 []byte(jwk.Key.(ed25519.PrivateKey).Public().(ed25519.PublicKey)),
791 []byte(jwk2.Key.(ed25519.PrivateKey).Public().(ed25519.PublicKey))))
792 }
793
794 func TestThumbprint(t *testing.T) {
795 for i, key := range cookbookJWKs {
796 var jwk2 JSONWebKey
797 err := jwk2.UnmarshalJSON([]byte(key))
798 if err != nil {
799 t.Error("unable to parse valid key:", key, err)
800 }
801
802 tp, err := jwk2.Thumbprint(crypto.SHA256)
803 if err != nil {
804 t.Error("unable to compute thumbprint:", key, err)
805 }
806
807 tpHex := hex.EncodeToString(tp)
808 if cookbookJWKThumbprints[i] != tpHex {
809 t.Error("incorrect thumbprint:", i, cookbookJWKThumbprints[i], tpHex)
810 }
811 }
812 }
813
814 func TestMarshalUnmarshalJWKSet(t *testing.T) {
815 jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"}
816 jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"}
817 var set JSONWebKeySet
818 set.Keys = append(set.Keys, jwk1)
819 set.Keys = append(set.Keys, jwk2)
820
821 jsonbar, err := json.Marshal(&set)
822 if err != nil {
823 t.Error("problem marshalling set", err)
824 }
825 var set2 JSONWebKeySet
826 err = json.Unmarshal(jsonbar, &set2)
827 if err != nil {
828 t.Fatal("problem unmarshalling set", err)
829 }
830 jsonbar2, err := json.Marshal(&set2)
831 if err != nil {
832 t.Fatal("problem marshalling set", err)
833 }
834 if !bytes.Equal(jsonbar, jsonbar2) {
835 t.Error("roundtrip should not lose information")
836 }
837 }
838
839 func TestJWKSetKey(t *testing.T) {
840 jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"}
841 jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"}
842 var set JSONWebKeySet
843 set.Keys = append(set.Keys, jwk1)
844 set.Keys = append(set.Keys, jwk2)
845 k := set.Key("ABCDEFG")
846 if len(k) != 1 {
847 t.Errorf("method should return slice with one key not %d", len(k))
848 }
849 if k[0].KeyID != "ABCDEFG" {
850 t.Error("method should return key with ID ABCDEFG")
851 }
852 }
853
854 func TestJWKSymmetricKey(t *testing.T) {
855 sample1 := `{"kty":"oct","alg":"A128KW","k":"GawgguFyGrWKav7AX4VKUg"}`
856 sample2 := `{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow","kid":"HMAC key used in JWS spec Appendix A.1 example"}`
857
858 var jwk1 JSONWebKey
859 json.Unmarshal([]byte(sample1), &jwk1)
860
861 if jwk1.Algorithm != "A128KW" {
862 t.Errorf("expected Algorithm to be A128KW, but was '%s'", jwk1.Algorithm)
863 }
864 expected1 := fromHexBytes("19ac2082e1721ab58a6afec05f854a52")
865 if !bytes.Equal(jwk1.Key.([]byte), expected1) {
866 t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected1), hex.EncodeToString(jwk1.Key.([]byte)))
867 }
868
869 var jwk2 JSONWebKey
870 json.Unmarshal([]byte(sample2), &jwk2)
871
872 if jwk2.KeyID != "HMAC key used in JWS spec Appendix A.1 example" {
873 t.Errorf("expected KeyID to be 'HMAC key used in JWS spec Appendix A.1 example', but was '%s'", jwk2.KeyID)
874 }
875 expected2 := fromHexBytes(`
876 0323354b2b0fa5bc837e0665777ba68f5ab328e6f054c928a90f84b2d2502ebf
877 d3fb5a92d20647ef968ab4c377623d223d2e2172052e4f08c0cd9af567d080a3`)
878 if !bytes.Equal(jwk2.Key.([]byte), expected2) {
879 t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected2), hex.EncodeToString(jwk2.Key.([]byte)))
880 }
881 }
882
883 func TestJWKSymmetricRoundtrip(t *testing.T) {
884 jwk1 := JSONWebKey{Key: []byte{1, 2, 3, 4}}
885 marshaled, err := jwk1.MarshalJSON()
886 if err != nil {
887 t.Error("failed to marshal valid JWK object", err)
888 }
889
890 var jwk2 JSONWebKey
891 err = jwk2.UnmarshalJSON(marshaled)
892 if err != nil {
893 t.Error("failed to unmarshal valid JWK object", err)
894 }
895
896 if !bytes.Equal(jwk1.Key.([]byte), jwk2.Key.([]byte)) {
897 t.Error("round-trip of symmetric JWK gave different raw keys")
898 }
899 }
900
901 func TestJWKSymmetricInvalid(t *testing.T) {
902 invalid := JSONWebKey{}
903 _, err := invalid.MarshalJSON()
904 if err == nil {
905 t.Error("excepted error on marshaling invalid symmetric JWK object")
906 }
907
908 var jwk JSONWebKey
909 err = jwk.UnmarshalJSON([]byte(`{"kty":"oct"}`))
910 if err == nil {
911 t.Error("excepted error on unmarshaling invalid symmetric JWK object")
912 }
913 }
914
915 func TestJWKIsPublic(t *testing.T) {
916 bigInt := big.NewInt(0)
917 eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt}
918 rsaPub := rsa.PublicKey{bigInt, 1}
919
920 cases := []struct {
921 key interface{}
922 expectedIsPublic bool
923 }{
924 {&eccPub, true},
925 {&ecdsa.PrivateKey{eccPub, bigInt}, false},
926 {&rsaPub, true},
927 {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, false},
928 {ed25519PublicKey, true},
929 {ed25519PrivateKey, false},
930 }
931
932 for _, tc := range cases {
933 k := &JSONWebKey{Key: tc.key}
934 if public := k.IsPublic(); public != tc.expectedIsPublic {
935 t.Errorf("expected IsPublic to return %t, got %t", tc.expectedIsPublic, public)
936 }
937 }
938 }
939
940 func TestJWKValid(t *testing.T) {
941 bigInt := big.NewInt(0)
942 eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt}
943 rsaPub := rsa.PublicKey{bigInt, 1}
944 edPubEmpty := ed25519.PublicKey([]byte{})
945 edPrivEmpty := ed25519.PublicKey([]byte{})
946
947 cases := []struct {
948 key interface{}
949 expectedValidity bool
950 }{
951 {nil, false},
952 {&ecdsa.PublicKey{}, false},
953 {&eccPub, true},
954 {&ecdsa.PrivateKey{}, false},
955 {&ecdsa.PrivateKey{eccPub, bigInt}, true},
956 {&rsa.PublicKey{}, false},
957 {&rsaPub, true},
958 {&rsa.PrivateKey{}, false},
959 {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, true},
960 {ed25519PublicKey, true},
961 {ed25519PrivateKey, true},
962 {edPubEmpty, false},
963 {edPrivEmpty, false},
964 }
965
966 for _, tc := range cases {
967 k := &JSONWebKey{Key: tc.key}
968 valid := k.Valid()
969 if valid != tc.expectedValidity {
970 t.Errorf("expected Valid to return %t, got %t", tc.expectedValidity, valid)
971 }
972 if valid {
973 wasPublic := k.IsPublic()
974 p := k.Public()
975 if !p.Valid() {
976 t.Errorf("unable to derive public key from valid asymmetric key")
977 }
978 if wasPublic != k.IsPublic() {
979 t.Errorf("original key was touched during public key derivation")
980 }
981 }
982 }
983 }
984
985 func TestJWKBufferSizeCheck(t *testing.T) {
986 key := `{
987 "kty":"EC",
988 "crv":"P-256",
989 "x":"m9GSmJ5iGmAYlMlaOJGSFN_CjN9cIn8GGYExP-C0FBiIXlWTNvGN38R9WdrHcppfsKF0FXMOMyutpHIRaiMxYSA",
990 "y":"ZaPcRZ3q_7T3h-Gwz2i-T2JjJXfj6YVGgKHcFz5zqmg"}`
991 var jwk JSONWebKey
992 jwk.UnmarshalJSON([]byte(key))
993 jwk.Valid()
994
995
996 jwk.Thumbprint(crypto.SHA256)
997 }
998
999 func TestJWKPaddingPrivateX(t *testing.T) {
1000 key := `{
1001 "kty": "EC",
1002 "crv": "P-256",
1003 "x": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ",
1004 "y": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs",
1005 "d": "nIVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0"
1006 }`
1007 var jwk JSONWebKey
1008 err := jwk.UnmarshalJSON([]byte(key))
1009 if err == nil {
1010 t.Errorf("Expected key with short x to fail unmarshalling")
1011 }
1012 if !strings.Contains(err.Error(), "wrong length for x") {
1013 t.Errorf("Wrong error for short x, got %q", err)
1014 }
1015 if jwk.Valid() {
1016 t.Errorf("Expected key to be invalid, but it was valid.")
1017 }
1018 }
1019
1020 func TestJWKPaddingPrivateY(t *testing.T) {
1021 key := `{
1022 "kty": "EC",
1023 "crv": "P-256",
1024 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs",
1025 "y": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ",
1026 "d": "nIVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0"
1027 }`
1028 var jwk JSONWebKey
1029 err := jwk.UnmarshalJSON([]byte(key))
1030 if err == nil {
1031 t.Errorf("Expected key with short x to fail unmarshalling")
1032 }
1033 if !strings.Contains(err.Error(), "wrong length for y") {
1034 t.Errorf("Wrong error for short y, got %q", err)
1035 }
1036 if jwk.Valid() {
1037 t.Errorf("Expected key to be invalid, but it was valid.")
1038 }
1039 }
1040
1041 func TestJWKPaddingPrivateD(t *testing.T) {
1042 key := `{
1043 "kty": "EC",
1044 "crv": "P-256",
1045 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs",
1046 "y": "qnPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ",
1047 "d": "IVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0"
1048 }`
1049 var jwk JSONWebKey
1050 err := jwk.UnmarshalJSON([]byte(key))
1051 if err == nil {
1052 t.Errorf("Expected key with short x to fail unmarshalling")
1053 }
1054 if !strings.Contains(err.Error(), "wrong length for d") {
1055 t.Errorf("Wrong error for short d, got %q", err)
1056 }
1057 if jwk.Valid() {
1058 t.Errorf("Expected key to be invalid, but it was valid.")
1059 }
1060 }
1061
1062 func TestJWKPaddingX(t *testing.T) {
1063 key := `{
1064 "kty": "EC",
1065 "crv": "P-256",
1066 "x": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ",
1067 "y": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs"
1068 }`
1069 var jwk JSONWebKey
1070 err := jwk.UnmarshalJSON([]byte(key))
1071 if err == nil {
1072 t.Errorf("Expected key with short x to fail unmarshalling")
1073 }
1074 if !strings.Contains(err.Error(), "wrong length for x") {
1075 t.Errorf("Wrong error for short x, got %q", err)
1076 }
1077 if jwk.Valid() {
1078 t.Errorf("Expected key to be invalid, but it was valid.")
1079 }
1080 }
1081
1082 func TestJWKPaddingY(t *testing.T) {
1083 key := `{
1084 "kty": "EC",
1085 "crv": "P-256",
1086 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs",
1087 "y": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ"
1088 }`
1089 var jwk JSONWebKey
1090 err := jwk.UnmarshalJSON([]byte(key))
1091 if err == nil {
1092 t.Errorf("Expected key with short y to fail unmarshalling")
1093 }
1094 if !strings.Contains(err.Error(), "wrong length for y") {
1095 t.Errorf("Wrong error for short y, got %q", err)
1096 }
1097 if jwk.Valid() {
1098 t.Errorf("Expected key to be invalid, but it was valid.")
1099 }
1100 }
1101
View as plain text