1 package jwe_test
2
3 import (
4 "context"
5 "reflect"
6 "testing"
7
8 "github.com/lestrrat-go/jwx/internal/jwxtest"
9 "github.com/lestrrat-go/jwx/jwa"
10 "github.com/lestrrat-go/jwx/jwe"
11 "github.com/lestrrat-go/jwx/jwk"
12 "github.com/stretchr/testify/assert"
13 )
14
15 var zeroval reflect.Value
16
17 func TestHeaders(t *testing.T) {
18 certs := []string{
19 "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYwMTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3HKrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQmVZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpRSgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRTcDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEuMB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUHAgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IGOgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMUA2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTXRE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuHqDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWVU+4=",
20 "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoXDTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHUTBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMbVmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwgSW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlvbiBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEgMB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUwAwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdvZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUdIAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4OWBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0VmsfSxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==",
21 "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd",
22 }
23
24 rawKey, err := jwxtest.GenerateEcdsaKey(jwa.P521)
25 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaKey should succeed`) {
26 return
27 }
28 privKey, err := jwk.New(rawKey)
29 if !assert.NoError(t, err, `jwk.New should succeed`) {
30 return
31 }
32
33 pubKey, err := jwk.New(rawKey.PublicKey)
34 if !assert.NoError(t, err, `jwk.PublicKey should succeed`) {
35 return
36 }
37
38 data := []struct {
39 Key string
40 Value interface{}
41 Expected interface{}
42 Method string
43 }{
44 {
45 Key: jwe.AgreementPartyUInfoKey,
46 Value: []byte("apu foobarbaz"),
47 Method: "AgreementPartyUInfo",
48 },
49 {Key: jwe.AgreementPartyVInfoKey, Value: []byte("apv foobarbaz")},
50 {Key: jwe.CompressionKey, Value: jwa.Deflate},
51 {Key: jwe.ContentEncryptionKey, Value: jwa.A128GCM},
52 {
53 Key: jwe.ContentTypeKey,
54 Value: "application/json",
55 Method: "ContentType",
56 },
57 {
58 Key: jwe.CriticalKey,
59 Value: []string{"crit blah"},
60 Method: "Critical",
61 },
62 {
63 Key: jwe.EphemeralPublicKeyKey,
64 Value: pubKey,
65 Method: "EphemeralPublicKey",
66 },
67 {
68 Key: jwe.JWKKey,
69 Value: privKey,
70 Method: "JWK",
71 },
72 {
73 Key: jwe.JWKSetURLKey,
74 Value: "http://github.com/lestrrat-go/jwx",
75 Method: "JWKSetURL",
76 },
77 {
78 Key: jwe.KeyIDKey,
79 Value: "kid blah",
80 Method: "KeyID",
81 },
82 {
83 Key: jwe.TypeKey,
84 Value: "typ blah",
85 Method: "Type",
86 },
87 {
88 Key: jwe.X509CertChainKey,
89 Value: certs,
90 Method: "X509CertChain",
91 },
92 {
93 Key: jwe.X509CertThumbprintKey,
94 Value: "x5t blah",
95 Method: "X509CertThumbprint",
96 },
97 {
98 Key: jwe.X509CertThumbprintS256Key,
99 Value: "x5t#256 blah",
100 Method: "X509CertThumbprintS256",
101 },
102 {
103 Key: jwe.X509URLKey,
104 Value: "http://github.com/lestrrat-go/jwx",
105 Method: "X509URL",
106 },
107 {Key: "private", Value: "boofoo"},
108 }
109
110 base := jwe.NewHeaders()
111
112 t.Run("Set values", func(t *testing.T) {
113
114 for _, tc := range data {
115 if !assert.NoError(t, base.Set(tc.Key, tc.Value), "Headers.Set should succeed") {
116 return
117 }
118 }
119 })
120
121 t.Run("Set/Get", func(t *testing.T) {
122 h := jwe.NewHeaders()
123 ctx := context.Background()
124
125 for iter := base.Iterate(ctx); iter.Next(ctx); {
126 pair := iter.Pair()
127 if !assert.NoError(t, h.Set(pair.Key.(string), pair.Value), `h.Set should be successful`) {
128 return
129 }
130 }
131 for _, tc := range data {
132 var values []interface{}
133 viaGet, ok := h.Get(tc.Key)
134 if !assert.True(t, ok, "value for %s should exist", tc.Key) {
135 return
136 }
137 values = append(values, viaGet)
138
139 if method := tc.Method; method != "" {
140 m := reflect.ValueOf(h).MethodByName(method)
141 if !assert.NotEqual(t, m, zeroval, "method %s should be available", method) {
142 return
143 }
144
145 ret := m.Call(nil)
146 if !assert.Len(t, ret, 1, `should get exactly 1 value as return value`) {
147 return
148 }
149 values = append(values, ret[0].Interface())
150 }
151
152 expected := tc.Expected
153 if expected == nil {
154 expected = tc.Value
155 }
156 for i, got := range values {
157 if !assert.Equal(t, expected, got, "value %d should match", i) {
158 return
159 }
160 }
161 }
162 })
163 t.Run("PrivateParams", func(t *testing.T) {
164 h := base
165 pp, err := h.AsMap(context.Background())
166 if !assert.NoError(t, err, `h.AsMap should succeed`) {
167 return
168 }
169
170 v, ok := pp["private"]
171 if !assert.True(t, ok, "key 'private' should exists") {
172 return
173 }
174
175 if !assert.Equal(t, v, "boofoo", "value for 'private' should match") {
176 return
177 }
178 })
179 t.Run("Encode", func(t *testing.T) {
180 h1 := jwe.NewHeaders()
181 h1.Set(jwe.AlgorithmKey, jwa.A128GCMKW)
182 h1.Set("foo", "bar")
183
184 buf, err := h1.Encode()
185 if !assert.NoError(t, err, `h1.Encode should succeed`) {
186 return
187 }
188
189 h2 := jwe.NewHeaders()
190 if !assert.NoError(t, h2.Decode(buf), `h2.Decode should succeed`) {
191 return
192 }
193
194 if !assert.Equal(t, h1, h2, `objects should match`) {
195 return
196 }
197 })
198
199 t.Run("Iterator", func(t *testing.T) {
200 expected := map[string]interface{}{}
201 for _, tc := range data {
202 v := tc.Value
203 if expected := tc.Expected; expected != nil {
204 v = expected
205 }
206 expected[tc.Key] = v
207 }
208
209 v := base
210 t.Run("Iterate", func(t *testing.T) {
211 seen := make(map[string]interface{})
212 for iter := v.Iterate(context.TODO()); iter.Next(context.TODO()); {
213 pair := iter.Pair()
214 seen[pair.Key.(string)] = pair.Value
215
216 getV, ok := v.Get(pair.Key.(string))
217 if !assert.True(t, ok, `v.Get should succeed for key %#v`, pair.Key) {
218 return
219 }
220 if !assert.Equal(t, pair.Value, getV, `pair.Value should match value from v.Get()`) {
221 return
222 }
223 }
224 if !assert.Equal(t, expected, seen, `values should match`) {
225 return
226 }
227 })
228 t.Run("Walk", func(t *testing.T) {
229 seen := make(map[string]interface{})
230 v.Walk(context.TODO(), jwk.HeaderVisitorFunc(func(key string, value interface{}) error {
231 seen[key] = value
232 return nil
233 }))
234 if !assert.Equal(t, expected, seen, `values should match`) {
235 return
236 }
237 })
238 t.Run("AsMap", func(t *testing.T) {
239 m, err := v.AsMap(context.TODO())
240 if !assert.NoError(t, err, `v.AsMap should succeed`) {
241 return
242 }
243 if !assert.Equal(t, expected, m, `values should match`) {
244 return
245 }
246 })
247 t.Run("Remove", func(t *testing.T) {
248 h := base
249 for iter := h.Iterate(context.TODO()); iter.Next(context.TODO()); {
250 pair := iter.Pair()
251 h.Remove(pair.Key.(string))
252 }
253
254 m, err := h.AsMap(context.TODO())
255 if !assert.NoError(t, err, `h.AsMap should succeed`) {
256 return
257 }
258 if !assert.Len(t, m, 0, `len should be zero`) {
259 return
260 }
261 })
262 })
263 }
264
View as plain text