Skip to content
This repository was archived by the owner on Feb 27, 2023. It is now read-only.

Commit d84c719

Browse files
mangasmbyczkowski
andauthored
Fix decoding x5t parameters (#304)
When support for optional x5u, x5t, and x5t#S256 parameters in JWK was added in #242 (and subsequently released in 2.5.0) it actually broke parsing of JWKs which included those parameters. See #299 for detailed analysis and discussion. Co-authored-by: Mat Byczkowski <[email protected]>
1 parent 21f2ca2 commit d84c719

File tree

5 files changed

+167
-38
lines changed

5 files changed

+167
-38
lines changed

.golangci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ issues:
4848
- path: _test\.go
4949
linters:
5050
- scopelint
51+
- path: jwk.go
52+
linters:
53+
- gocyclo

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/square/go-jose/v3
33
go 1.12
44

55
require (
6+
github.com/google/go-cmp v0.4.0
67
github.com/stretchr/testify v1.5.1
78
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
89
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
4+
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
35
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
46
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
57
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
@@ -13,6 +15,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
1315
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1416
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1517
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
18+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
19+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1620
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1721
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1822
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

jwk.go

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"crypto/sha256"
2828
"crypto/x509"
2929
"encoding/base64"
30+
"encoding/hex"
3031
"errors"
3132
"fmt"
3233
"math/big"
@@ -60,10 +61,10 @@ type rawJSONWebKey struct {
6061
Dq *byteBuffer `json:"dq,omitempty"`
6162
Qi *byteBuffer `json:"qi,omitempty"`
6263
// Certificates
63-
X5c []string `json:"x5c,omitempty"`
64-
X5u *url.URL `json:"x5u,omitempty"`
65-
X5tSHA1 *byteBuffer `json:"x5t,omitempty"`
66-
X5tSHA256 *byteBuffer `json:"x5t#S256,omitempty"`
64+
X5c []string `json:"x5c,omitempty"`
65+
X5u *url.URL `json:"x5u,omitempty"`
66+
X5tSHA1 string `json:"x5t,omitempty"`
67+
X5tSHA256 string `json:"x5t#S256,omitempty"`
6768
}
6869

6970
// JSONWebKey represents a public or private key in JWK format.
@@ -129,13 +130,13 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
129130
if x5tSHA1Len != sha1.Size {
130131
return nil, fmt.Errorf("square/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
131132
}
132-
raw.X5tSHA1 = newFixedSizeBuffer(k.CertificateThumbprintSHA1, sha1.Size)
133+
raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
133134
}
134135
if x5tSHA256Len > 0 {
135136
if x5tSHA256Len != sha256.Size {
136137
return nil, fmt.Errorf("square/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
137138
}
138-
raw.X5tSHA256 = newFixedSizeBuffer(k.CertificateThumbprintSHA256, sha256.Size)
139+
raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
139140
}
140141

141142
// If cert chain is attached (as opposed to being behind a URL), check the
@@ -145,9 +146,12 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
145146
if len(k.Certificates) > 0 {
146147
expectedSHA1 := sha1.Sum(k.Certificates[0].Raw)
147148
expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
148-
if !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) ||
149-
!bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
150-
return nil, errors.New("square/go-jose: invalid SHA-1 or SHA-256 thumbprint, does not match cert chain")
149+
150+
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
151+
return nil, errors.New("square/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
152+
}
153+
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
154+
return nil, errors.New("square/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
151155
}
152156
}
153157

@@ -240,16 +244,51 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
240244
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
241245

242246
k.CertificatesURL = raw.X5u
243-
k.CertificateThumbprintSHA1 = raw.X5tSHA1.bytes()
244-
k.CertificateThumbprintSHA256 = raw.X5tSHA256.bytes()
247+
248+
// x5t parameters are base64url-encoded SHA thumbprints
249+
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
250+
x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
251+
if err != nil {
252+
return errors.New("square/go-jose: invalid JWK, x5t header has invalid encoding")
253+
}
254+
255+
// RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex,
256+
// for this reason, after base64 decoding, if the size is sha1.Size it's likely that the value is a byte encoded
257+
// checksum so we skip this. Otherwise if the checksum was hex encoded we expect a 40 byte sized array so we'll
258+
// try to hex decode it. When Marshalling this value we'll always use a base64 encoded version of byte format checksum.
259+
if len(x5tSHA1bytes) == 2*sha1.Size {
260+
hx, err := hex.DecodeString(string(x5tSHA1bytes))
261+
if err != nil {
262+
return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t: %w", err)
263+
264+
}
265+
x5tSHA1bytes = hx
266+
}
267+
268+
k.CertificateThumbprintSHA1 = x5tSHA1bytes
269+
270+
x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
271+
if err != nil {
272+
return errors.New("square/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
273+
}
274+
275+
if len(x5tSHA256bytes) == 2*sha256.Size {
276+
hx256, err := hex.DecodeString(string(x5tSHA256bytes))
277+
if err != nil {
278+
return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t#S256: %w", err)
279+
}
280+
x5tSHA256bytes = hx256
281+
}
282+
283+
k.CertificateThumbprintSHA256 = x5tSHA256bytes
245284

246285
x5tSHA1Len := len(k.CertificateThumbprintSHA1)
247286
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
248287
if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
249288
return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size")
250289
}
251290
if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
252-
return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size")
291+
return errors.New("square/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
253292
}
254293

255294
// If certificate chain *and* thumbprints are set, verify correctness.

jwk_test.go

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ import (
3232
"strings"
3333
"testing"
3434

35-
"github.com/stretchr/testify/assert"
36-
3735
"github.com/square/go-jose/v3/json"
36+
37+
"github.com/google/go-cmp/cmp"
38+
"github.com/stretchr/testify/assert"
39+
"github.com/stretchr/testify/require"
3840
)
3941

4042
// Test chain of two X.509 certificates
@@ -252,37 +254,117 @@ func TestRoundtripX509(t *testing.T) {
252254
x5tSHA1 := sha1.Sum(testCertificates[0].Raw)
253255
x5tSHA256 := sha256.Sum256(testCertificates[0].Raw)
254256

255-
jwk := JSONWebKey{
256-
Key: testCertificates[0].PublicKey,
257-
KeyID: "bar",
258-
Algorithm: "foo",
259-
Certificates: testCertificates,
260-
CertificateThumbprintSHA1: x5tSHA1[:],
261-
CertificateThumbprintSHA256: x5tSHA256[:],
257+
cases := []struct {
258+
name string
259+
jwk JSONWebKey
260+
}{
261+
{
262+
name: "all fields",
263+
jwk: JSONWebKey{
264+
Key: testCertificates[0].PublicKey,
265+
KeyID: "bar",
266+
Algorithm: "foo",
267+
Certificates: testCertificates,
268+
CertificateThumbprintSHA1: x5tSHA1[:],
269+
CertificateThumbprintSHA256: x5tSHA256[:],
270+
},
271+
},
272+
{
273+
name: "no optional x5ts",
274+
jwk: JSONWebKey{
275+
Key: testCertificates[0].PublicKey,
276+
KeyID: "bar",
277+
Algorithm: "foo",
278+
Certificates: testCertificates,
279+
},
280+
},
281+
{
282+
name: "no x5t",
283+
jwk: JSONWebKey{
284+
Key: testCertificates[0].PublicKey,
285+
KeyID: "bar",
286+
Algorithm: "foo",
287+
Certificates: testCertificates,
288+
CertificateThumbprintSHA256: x5tSHA256[:],
289+
},
290+
},
291+
{
292+
name: "no x5t#S256",
293+
jwk: JSONWebKey{
294+
Key: testCertificates[0].PublicKey,
295+
KeyID: "bar",
296+
Algorithm: "foo",
297+
Certificates: testCertificates,
298+
CertificateThumbprintSHA1: x5tSHA1[:],
299+
},
300+
},
262301
}
263302

264-
jsonbar, err := jwk.MarshalJSON()
265-
if err != nil {
266-
t.Error("problem marshaling", err)
303+
for _, c := range cases {
304+
t.Run(c.name, func(t *testing.T) {
305+
jsonbar, err := c.jwk.MarshalJSON()
306+
require.NoError(t, err)
307+
308+
var jwk2 JSONWebKey
309+
err = jwk2.UnmarshalJSON(jsonbar)
310+
require.NoError(t, err)
311+
312+
if !reflect.DeepEqual(testCertificates, jwk2.Certificates) {
313+
t.Error("Certificates not equal", c.jwk.Certificates, jwk2.Certificates)
314+
}
315+
316+
jsonbar2, err := jwk2.MarshalJSON()
317+
require.NoError(t, err)
318+
319+
require.Empty(t, cmp.Diff(jsonbar, jsonbar2))
320+
if !bytes.Equal(jsonbar, jsonbar2) {
321+
t.Error("roundtrip should not lose information")
322+
}
323+
})
267324
}
325+
}
326+
327+
func TestRoundtripX509Hex(t *testing.T) {
328+
var hexJWK = `{
329+
"kty":"RSA",
330+
"kid":"bar",
331+
"alg":"foo",
332+
"n":"u7LUr30Mhrh8N79-H4rKiHQ123q6xaBZPYbf1nV4GM19rizSnbEfyebG1kpfCv-XY6c499XiM6lOvcPL-0goTOcfW6Lg7AAR895GbnMeXEmnxICaI8rAZHK6t1WPmiWp82y_qhK2F_pYUaT3GSuiTFiMGq_GNwdpWuMlsInnnMNv1nxFbxtDPwzmCp0fEBxbH5d1EtXZwTPOHMyj8rfa-NIA5Nl4h_5RrbOWveKwBr26_CDAratJgOWh9xcd5g0ot_uDGcMoAgB6xeTuYklfaxCPptvu49kvoxw1J71fp6nKW_ZuhDRAp2F_BQ9inKpTo05sPLJg8tPTdjaeouOuJQ",
333+
"e":"AQAB",
334+
"x5c":[
335+
"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=",
336+
"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"
337+
],
338+
"x5t": "MDYxMjU0ZmRmNzIwZjJjMGU0YmQzZjMzMzlhMmZlNTM1MGExNWRlMQ",
339+
"x5t#S256": "MjAzMjRhNGI5MmYxMjI2OGVmOWFlMDI1ZmQ1Yzc5ZDE1OGZmNzQ1NzQwMDkyMTk2ZTgzNTNjMDAzMTUxNzUxMQ"
340+
}`
341+
342+
// json output
343+
var output = `{
344+
"kty":"RSA",
345+
"kid":"bar",
346+
"alg":"foo",
347+
"n":"u7LUr30Mhrh8N79-H4rKiHQ123q6xaBZPYbf1nV4GM19rizSnbEfyebG1kpfCv-XY6c499XiM6lOvcPL-0goTOcfW6Lg7AAR895GbnMeXEmnxICaI8rAZHK6t1WPmiWp82y_qhK2F_pYUaT3GSuiTFiMGq_GNwdpWuMlsInnnMNv1nxFbxtDPwzmCp0fEBxbH5d1EtXZwTPOHMyj8rfa-NIA5Nl4h_5RrbOWveKwBr26_CDAratJgOWh9xcd5g0ot_uDGcMoAgB6xeTuYklfaxCPptvu49kvoxw1J71fp6nKW_ZuhDRAp2F_BQ9inKpTo05sPLJg8tPTdjaeouOuJQ",
348+
"e":"AQAB",
349+
"x5c":[
350+
"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=",
351+
"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"
352+
],
353+
"x5t":"BhJU_fcg8sDkvT8zOaL-U1ChXeE",
354+
"x5t#S256":"IDJKS5LxImjvmuAl_Vx50Vj_dFdACSGW6DU8ADFRdRE"
355+
}`
268356

269357
var jwk2 JSONWebKey
270-
err = jwk2.UnmarshalJSON(jsonbar)
271-
if err != nil {
272-
t.Fatal("problem unmarshalling", err)
273-
}
358+
err := jwk2.UnmarshalJSON([]byte(hexJWK))
359+
require.NoError(t, err)
274360

275-
if !reflect.DeepEqual(testCertificates, jwk2.Certificates) {
276-
t.Error("Certificates not equal", jwk.Certificates, jwk2.Certificates)
277-
}
361+
js, err := jwk2.MarshalJSON()
362+
require.NoError(t, err)
278363

279-
jsonbar2, err := jwk2.MarshalJSON()
280-
if err != nil {
281-
t.Error("problem marshaling", err)
282-
}
283-
if !bytes.Equal(jsonbar, jsonbar2) {
284-
t.Error("roundtrip should not lose information")
285-
}
364+
var j1, j2 map[string]interface{}
365+
require.NoError(t, json.Unmarshal(js, &j1))
366+
require.NoError(t, json.Unmarshal([]byte(output), &j2))
367+
require.Empty(t, cmp.Diff(j1, j2))
286368
}
287369

288370
func TestInvalidThumbprintsX509(t *testing.T) {

0 commit comments

Comments
 (0)