1
16
17 package jose
18
19 import (
20 "bytes"
21 "crypto/ecdsa"
22 "crypto/rsa"
23 "encoding/base64"
24 "errors"
25 "fmt"
26
27 "golang.org/x/crypto/ed25519"
28
29 "gopkg.in/square/go-jose.v2/json"
30 )
31
32
33 type NonceSource interface {
34 Nonce() (string, error)
35 }
36
37
38 type Signer interface {
39 Sign(payload []byte) (*JSONWebSignature, error)
40 Options() SignerOptions
41 }
42
43
44 type SigningKey struct {
45 Algorithm SignatureAlgorithm
46 Key interface{}
47 }
48
49
50 type SignerOptions struct {
51 NonceSource NonceSource
52 EmbedJWK bool
53
54
55
56
57 ExtraHeaders map[HeaderKey]interface{}
58 }
59
60
61
62 func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
63 if so.ExtraHeaders == nil {
64 so.ExtraHeaders = map[HeaderKey]interface{}{}
65 }
66 so.ExtraHeaders[k] = v
67 return so
68 }
69
70
71
72 func (so *SignerOptions) WithContentType(contentType ContentType) *SignerOptions {
73 return so.WithHeader(HeaderContentType, contentType)
74 }
75
76
77 func (so *SignerOptions) WithType(typ ContentType) *SignerOptions {
78 return so.WithHeader(HeaderType, typ)
79 }
80
81
82
83 func (so *SignerOptions) WithCritical(names ...string) *SignerOptions {
84 if so.ExtraHeaders[headerCritical] == nil {
85 so.WithHeader(headerCritical, make([]string, 0, len(names)))
86 }
87 crit := so.ExtraHeaders[headerCritical].([]string)
88 so.ExtraHeaders[headerCritical] = append(crit, names...)
89 return so
90 }
91
92
93
94 func (so *SignerOptions) WithBase64(b64 bool) *SignerOptions {
95 if !b64 {
96 so.WithHeader(headerB64, b64)
97 so.WithCritical(headerB64)
98 }
99 return so
100 }
101
102 type payloadSigner interface {
103 signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error)
104 }
105
106 type payloadVerifier interface {
107 verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
108 }
109
110 type genericSigner struct {
111 recipients []recipientSigInfo
112 nonceSource NonceSource
113 embedJWK bool
114 extraHeaders map[HeaderKey]interface{}
115 }
116
117 type recipientSigInfo struct {
118 sigAlg SignatureAlgorithm
119 publicKey func() *JSONWebKey
120 signer payloadSigner
121 }
122
123 func staticPublicKey(jwk *JSONWebKey) func() *JSONWebKey {
124 return func() *JSONWebKey {
125 return jwk
126 }
127 }
128
129
130 func NewSigner(sig SigningKey, opts *SignerOptions) (Signer, error) {
131 return NewMultiSigner([]SigningKey{sig}, opts)
132 }
133
134
135 func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
136 signer := &genericSigner{recipients: []recipientSigInfo{}}
137
138 if opts != nil {
139 signer.nonceSource = opts.NonceSource
140 signer.embedJWK = opts.EmbedJWK
141 signer.extraHeaders = opts.ExtraHeaders
142 }
143
144 for _, sig := range sigs {
145 err := signer.addRecipient(sig.Algorithm, sig.Key)
146 if err != nil {
147 return nil, err
148 }
149 }
150
151 return signer, nil
152 }
153
154
155 func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
156 switch verificationKey := verificationKey.(type) {
157 case ed25519.PublicKey:
158 return &edEncrypterVerifier{
159 publicKey: verificationKey,
160 }, nil
161 case *rsa.PublicKey:
162 return &rsaEncrypterVerifier{
163 publicKey: verificationKey,
164 }, nil
165 case *ecdsa.PublicKey:
166 return &ecEncrypterVerifier{
167 publicKey: verificationKey,
168 }, nil
169 case []byte:
170 return &symmetricMac{
171 key: verificationKey,
172 }, nil
173 case JSONWebKey:
174 return newVerifier(verificationKey.Key)
175 case *JSONWebKey:
176 return newVerifier(verificationKey.Key)
177 }
178 if ov, ok := verificationKey.(OpaqueVerifier); ok {
179 return &opaqueVerifier{verifier: ov}, nil
180 }
181 return nil, ErrUnsupportedKeyType
182 }
183
184 func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
185 recipient, err := makeJWSRecipient(alg, signingKey)
186 if err != nil {
187 return err
188 }
189
190 ctx.recipients = append(ctx.recipients, recipient)
191 return nil
192 }
193
194 func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) {
195 switch signingKey := signingKey.(type) {
196 case ed25519.PrivateKey:
197 return newEd25519Signer(alg, signingKey)
198 case *rsa.PrivateKey:
199 return newRSASigner(alg, signingKey)
200 case *ecdsa.PrivateKey:
201 return newECDSASigner(alg, signingKey)
202 case []byte:
203 return newSymmetricSigner(alg, signingKey)
204 case JSONWebKey:
205 return newJWKSigner(alg, signingKey)
206 case *JSONWebKey:
207 return newJWKSigner(alg, *signingKey)
208 }
209 if signer, ok := signingKey.(OpaqueSigner); ok {
210 return newOpaqueSigner(alg, signer)
211 }
212 return recipientSigInfo{}, ErrUnsupportedKeyType
213 }
214
215 func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
216 recipient, err := makeJWSRecipient(alg, signingKey.Key)
217 if err != nil {
218 return recipientSigInfo{}, err
219 }
220 if recipient.publicKey != nil && recipient.publicKey() != nil {
221
222
223
224 publicKey := signingKey
225 publicKey.Key = recipient.publicKey().Key
226 recipient.publicKey = staticPublicKey(&publicKey)
227
228
229 if !recipient.publicKey().IsPublic() {
230 return recipientSigInfo{}, errors.New("square/go-jose: public key was unexpectedly not public")
231 }
232 }
233 return recipient, nil
234 }
235
236 func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
237 obj := &JSONWebSignature{}
238 obj.payload = payload
239 obj.Signatures = make([]Signature, len(ctx.recipients))
240
241 for i, recipient := range ctx.recipients {
242 protected := map[HeaderKey]interface{}{
243 headerAlgorithm: string(recipient.sigAlg),
244 }
245
246 if recipient.publicKey != nil && recipient.publicKey() != nil {
247
248
249
250
251
252
253
254
255 if ctx.embedJWK {
256 protected[headerJWK] = recipient.publicKey()
257 } else {
258 keyID := recipient.publicKey().KeyID
259 if keyID != "" {
260 protected[headerKeyID] = keyID
261 }
262 }
263 }
264
265 if ctx.nonceSource != nil {
266 nonce, err := ctx.nonceSource.Nonce()
267 if err != nil {
268 return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err)
269 }
270 protected[headerNonce] = nonce
271 }
272
273 for k, v := range ctx.extraHeaders {
274 protected[k] = v
275 }
276
277 serializedProtected := mustSerializeJSON(protected)
278 needsBase64 := true
279
280 if b64, ok := protected[headerB64]; ok {
281 if needsBase64, ok = b64.(bool); !ok {
282 return nil, errors.New("square/go-jose: Invalid b64 header parameter")
283 }
284 }
285
286 var input bytes.Buffer
287
288 input.WriteString(base64.RawURLEncoding.EncodeToString(serializedProtected))
289 input.WriteByte('.')
290
291 if needsBase64 {
292 input.WriteString(base64.RawURLEncoding.EncodeToString(payload))
293 } else {
294 input.Write(payload)
295 }
296
297 signatureInfo, err := recipient.signer.signPayload(input.Bytes(), recipient.sigAlg)
298 if err != nil {
299 return nil, err
300 }
301
302 signatureInfo.protected = &rawHeader{}
303 for k, v := range protected {
304 b, err := json.Marshal(v)
305 if err != nil {
306 return nil, fmt.Errorf("square/go-jose: Error marshalling item %#v: %v", k, err)
307 }
308 (*signatureInfo.protected)[k] = makeRawMessage(b)
309 }
310 obj.Signatures[i] = signatureInfo
311 }
312
313 return obj, nil
314 }
315
316 func (ctx *genericSigner) Options() SignerOptions {
317 return SignerOptions{
318 NonceSource: ctx.nonceSource,
319 EmbedJWK: ctx.embedJWK,
320 ExtraHeaders: ctx.extraHeaders,
321 }
322 }
323
324
325
326
327
328
329
330
331 func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
332 err := obj.DetachedVerify(obj.payload, verificationKey)
333 if err != nil {
334 return nil, err
335 }
336 return obj.payload, nil
337 }
338
339
340
341
342 func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
343 return obj.payload
344 }
345
346
347
348
349
350 func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
351 verifier, err := newVerifier(verificationKey)
352 if err != nil {
353 return err
354 }
355
356 if len(obj.Signatures) > 1 {
357 return errors.New("square/go-jose: too many signatures in payload; expecting only one")
358 }
359
360 signature := obj.Signatures[0]
361 headers := signature.mergedHeaders()
362 critical, err := headers.getCritical()
363 if err != nil {
364 return err
365 }
366
367 for _, name := range critical {
368 if !supportedCritical[name] {
369 return ErrCryptoFailure
370 }
371 }
372
373 input, err := obj.computeAuthData(payload, &signature)
374 if err != nil {
375 return ErrCryptoFailure
376 }
377
378 alg := headers.getSignatureAlgorithm()
379 err = verifier.verifyPayload(input, signature.Signature, alg)
380 if err == nil {
381 return nil
382 }
383
384 return ErrCryptoFailure
385 }
386
387
388
389
390
391 func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
392 idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
393 if err != nil {
394 return -1, Signature{}, nil, err
395 }
396 return idx, sig, obj.payload, nil
397 }
398
399
400
401
402
403
404
405
406
407
408 func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
409 verifier, err := newVerifier(verificationKey)
410 if err != nil {
411 return -1, Signature{}, err
412 }
413
414 outer:
415 for i, signature := range obj.Signatures {
416 headers := signature.mergedHeaders()
417 critical, err := headers.getCritical()
418 if err != nil {
419 continue
420 }
421
422 for _, name := range critical {
423 if !supportedCritical[name] {
424 continue outer
425 }
426 }
427
428 input, err := obj.computeAuthData(payload, &signature)
429 if err != nil {
430 continue
431 }
432
433 alg := headers.getSignatureAlgorithm()
434 err = verifier.verifyPayload(input, signature.Signature, alg)
435 if err == nil {
436 return i, signature, nil
437 }
438 }
439
440 return -1, Signature{}, ErrCryptoFailure
441 }
442
View as plain text