rebase: bump github.com/go-jose/go-jose/v3 from 3.0.1 to 3.0.3

Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.1 to 3.0.3.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/v3.0.3/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v3.0.1...v3.0.3)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2024-03-07 23:02:07 +00:00 committed by mergify[bot]
parent f12b6064d6
commit 5298762c4c
23 changed files with 354 additions and 136 deletions

2
go.mod
View File

@ -75,7 +75,7 @@ require (
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gemalto/flume v0.13.0 // indirect github.com/gemalto/flume v0.13.0 // indirect
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect

7
go.sum
View File

@ -987,8 +987,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@ -1739,6 +1739,7 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -2055,6 +2056,7 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@ -2074,6 +2076,7 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -1,10 +0,0 @@
Serious about security
======================
Square recognizes the important contributions the security research community
can make. We therefore encourage reporting security issues with the code
contained in this repository.
If you believe you have discovered a security vulnerability, please follow the
guidelines at <https://bugcrowd.com/squareopensource>.

View File

@ -1,6 +1,76 @@
# v4.0.1
## Fixed
- An attacker could send a JWE containing compressed data that used large
amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
Those functions now return an error if the decompressed data would exceed
250kB or 10x the compressed size (whichever is larger). Thanks to
Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
for reporting.
# v4.0.0
This release makes some breaking changes in order to more thoroughly
address the vulnerabilities discussed in [Three New Attacks Against JSON Web
Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
token".
## Changed
- Limit JWT encryption types (exclude password or public key types) (#78)
- Enforce minimum length for HMAC keys (#85)
- jwt: match any audience in a list, rather than requiring all audiences (#81)
- jwt: accept only Compact Serialization (#75)
- jws: Add expected algorithms for signatures (#74)
- Require specifying expected algorithms for ParseEncrypted,
ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
jwt.ParseSignedAndEncrypted (#69, #74)
- Usually there is a small, known set of appropriate algorithms for a program
to use and it's a mistake to allow unexpected algorithms. For instance the
"billion hash attack" relies in part on programs accepting the PBES2
encryption algorithm and doing the necessary work even if they weren't
specifically configured to allow PBES2.
- Revert "Strip padding off base64 strings" (#82)
- The specs require base64url encoding without padding.
- Minimum supported Go version is now 1.21
## Added
- ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
- These allow parsing a specific serialization, as opposed to ParseSigned and
ParseEncrypted, which try to automatically detect which serialization was
provided. It's common to require a specific serialization for a specific
protocol - for instance JWT requires Compact serialization.
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
# v3.0.3
## Fixed
- Limit decompression output size to prevent a DoS. Backport from v4.0.1.
# v3.0.2
## Fixed
- DecryptMulti: handle decompression error (#19)
## Changed
- jwe/CompactSerialize: improve performance (#67)
- Increase the default number of PBKDF2 iterations to 600k (#48)
- Return the proper algorithm for ECDSA keys (#45)
## Added
- Add Thumbprint support for opaque signers (#38)
# v3.0.1 # v3.0.1
Fixed: ## Fixed
- Security issue: an attacker specifying a large "p2c" value can cause - Security issue: an attacker specifying a large "p2c" value can cause
JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the

View File

@ -1,10 +1,17 @@
# Go JOSE # Go JOSE
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2) ### Versions
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt)
[![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE) [Version 4](https://github.com/go-jose/go-jose)
[![build](https://travis-ci.org/go-jose/go-jose.svg?branch=master)](https://travis-ci.org/go-jose/go-jose) ([branch](https://github.com/go-jose/go-jose/),
[![coverage](https://coveralls.io/repos/github/go-jose/go-jose/badge.svg?branch=master)](https://coveralls.io/r/go-jose/go-jose) [doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
import "github.com/go-jose/go-jose/v4"
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
are deprecated.
### Summary
Package jose aims to provide an implementation of the Javascript Object Signing Package jose aims to provide an implementation of the Javascript Object Signing
and Encryption set of standards. This includes support for JSON Web Encryption, and Encryption set of standards. This includes support for JSON Web Encryption,
@ -21,13 +28,13 @@ US maintained blocked list.
## Overview ## Overview
The implementation follows the The implementation follows the
[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516), [JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516),
[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and [JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications. [JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
Tables of supported algorithms are shown below. The library supports both Tables of supported algorithms are shown below. The library supports both
the compact and JWS/JWE JSON Serialization formats, and has optional support for the compact and JWS/JWE JSON Serialization formats, and has optional support for
multiple recipients. It also comes with a small command-line utility multiple recipients. It also comes with a small command-line utility
([`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util)) ([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util))
for dealing with JOSE messages in a shell. for dealing with JOSE messages in a shell.
**Note**: We use a forked version of the `encoding/json` package from the Go **Note**: We use a forked version of the `encoding/json` package from the Go
@ -36,31 +43,10 @@ of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/curren
This is to avoid differences in interpretation of messages between go-jose and This is to avoid differences in interpretation of messages between go-jose and
libraries in other languages. libraries in other languages.
### Versions
[Version 2](https://gopkg.in/go-jose/go-jose.v2)
([branch](https://github.com/go-jose/go-jose/tree/v2),
[doc](https://godoc.org/gopkg.in/go-jose/go-jose.v2)) is the current stable version:
import "gopkg.in/go-jose/go-jose.v2"
[Version 3](https://github.com/go-jose/go-jose)
([branch](https://github.com/go-jose/go-jose/tree/master),
[doc](https://godoc.org/github.com/go-jose/go-jose)) is the under development/unstable version (not released yet):
import "github.com/go-jose/go-jose/v3"
All new feature development takes place on the `master` branch, which we are
preparing to release as version 3 soon. Version 2 will continue to receive
critical bug and security fixes. Note that starting with version 3 we are
using Go modules for versioning instead of `gopkg.in` as before. Version 3 also will require Go version 1.13 or higher.
Version 1 (on the `v1` branch) is frozen and not supported anymore.
### Supported algorithms ### Supported algorithms
See below for a table of supported algorithms. Algorithm identifiers match See below for a table of supported algorithms. Algorithm identifiers match
the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518) the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
standard where possible. The Godoc reference has a list of constants. standard where possible. The Godoc reference has a list of constants.
Key encryption | Algorithm identifier(s) Key encryption | Algorithm identifier(s)
@ -103,20 +89,20 @@ allows attaching a key id.
Algorithm(s) | Corresponding types Algorithm(s) | Corresponding types
:------------------------- | ------------------------------- :------------------------- | -------------------------------
RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey) RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey) ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://godoc.org/pkg/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/pkg/crypto/ed25519#PrivateKey) EdDSA<sup>1</sup> | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
AES, HMAC | []byte AES, HMAC | []byte
<sup>1. Only available in version 2 or later of the package</sup> <sup>1. Only available in version 2 or later of the package</sup>
## Examples ## Examples
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2) [![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3)
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt) [![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3/jwt)
Examples can be found in the Godoc Examples can be found in the Godoc
reference for this package. The reference for this package. The
[`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util) [`jose-util`](https://github.com/go-jose/go-jose/tree/v3/jose-util)
subdirectory also contains a small command-line utility which might be useful subdirectory also contains a small command-line utility which might be useful
as an example as well. as an example as well.

13
vendor/github.com/go-jose/go-jose/v3/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,13 @@
# Security Policy
This document explains how to contact the Let's Encrypt security team to report security vulnerabilities.
## Supported Versions
| Version | Supported |
| ------- | ----------|
| >= v3 | &check; |
| v2 | &cross; |
| v1 | &cross; |
## Reporting a vulnerability
Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email.

View File

@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
switch alg { switch alg {
case RS256, RS384, RS512: case RS256, RS384, RS512:
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
// random parameter is legacy and ignored, and it can be nil.
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed) out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
case PS256, PS384, PS512: case PS256, PS384, PS512:
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{

View File

@ -21,7 +21,6 @@ import (
"crypto/rsa" "crypto/rsa"
"errors" "errors"
"fmt" "fmt"
"reflect"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v3/json"
) )
@ -76,14 +75,24 @@ type recipientKeyInfo struct {
type EncrypterOptions struct { type EncrypterOptions struct {
Compression CompressionAlgorithm Compression CompressionAlgorithm
// Optional map of additional keys to be inserted into the protected header // Optional map of name/value pairs to be inserted into the protected
// of a JWS object. Some specifications which make use of JWS like to insert // header of a JWS object. Some specifications which make use of
// additional values here. All values must be JSON-serializable. // JWS require additional values here.
//
// Values will be serialized by [json.Marshal] and must be valid inputs to
// that function.
//
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
ExtraHeaders map[HeaderKey]interface{} ExtraHeaders map[HeaderKey]interface{}
} }
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it // WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
// if necessary. It returns itself and so can be used in a fluent style. // if necessary, and returns the updated EncrypterOptions.
//
// The v parameter will be serialized by [json.Marshal] and must be a valid
// input to that function.
//
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions { func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
if eo.ExtraHeaders == nil { if eo.ExtraHeaders == nil {
eo.ExtraHeaders = map[HeaderKey]interface{}{} eo.ExtraHeaders = map[HeaderKey]interface{}{}
@ -111,7 +120,17 @@ func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
// default of 100000 will be used for the count and a 128-bit random salt will // default of 100000 will be used for the count and a 128-bit random salt will
// be generated. // be generated.
type Recipient struct { type Recipient struct {
Algorithm KeyAlgorithm Algorithm KeyAlgorithm
// Key must have one of these types:
// - ed25519.PublicKey
// - *ecdsa.PublicKey
// - *rsa.PublicKey
// - *JSONWebKey
// - JSONWebKey
// - []byte (a symmetric key)
// - Any type that satisfies the OpaqueKeyEncrypter interface
//
// The type of Key must match the value of Algorithm.
Key interface{} Key interface{}
KeyID string KeyID string
PBES2Count int PBES2Count int
@ -150,16 +169,17 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
switch rcpt.Algorithm { switch rcpt.Algorithm {
case DIRECT: case DIRECT:
// Direct encryption mode must be treated differently // Direct encryption mode must be treated differently
if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) { keyBytes, ok := rawKey.([]byte)
if !ok {
return nil, ErrUnsupportedKeyType return nil, ErrUnsupportedKeyType
} }
if encrypter.cipher.keySize() != len(rawKey.([]byte)) { if encrypter.cipher.keySize() != len(keyBytes) {
return nil, ErrInvalidKeySize return nil, ErrInvalidKeySize
} }
encrypter.keyGenerator = staticKeyGenerator{ encrypter.keyGenerator = staticKeyGenerator{
key: rawKey.([]byte), key: keyBytes,
} }
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte)) recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes)
recipientInfo.keyID = keyID recipientInfo.keyID = keyID
if rcpt.KeyID != "" { if rcpt.KeyID != "" {
recipientInfo.keyID = rcpt.KeyID recipientInfo.keyID = rcpt.KeyID
@ -168,16 +188,16 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
return encrypter, nil return encrypter, nil
case ECDH_ES: case ECDH_ES:
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode // ECDH-ES (w/o key wrapping) is similar to DIRECT mode
typeOf := reflect.TypeOf(rawKey) keyDSA, ok := rawKey.(*ecdsa.PublicKey)
if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) { if !ok {
return nil, ErrUnsupportedKeyType return nil, ErrUnsupportedKeyType
} }
encrypter.keyGenerator = ecKeyGenerator{ encrypter.keyGenerator = ecKeyGenerator{
size: encrypter.cipher.keySize(), size: encrypter.cipher.keySize(),
algID: string(enc), algID: string(enc),
publicKey: rawKey.(*ecdsa.PublicKey), publicKey: keyDSA,
} }
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey)) recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA)
recipientInfo.keyID = keyID recipientInfo.keyID = keyID
if rcpt.KeyID != "" { if rcpt.KeyID != "" {
recipientInfo.keyID = rcpt.KeyID recipientInfo.keyID = rcpt.KeyID
@ -270,9 +290,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
recipient, err := makeJWERecipient(alg, encryptionKey.Key) recipient, err := makeJWERecipient(alg, encryptionKey.Key)
recipient.keyID = encryptionKey.KeyID recipient.keyID = encryptionKey.KeyID
return recipient, err return recipient, err
} case OpaqueKeyEncrypter:
if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok { return newOpaqueKeyEncrypter(alg, encryptionKey)
return newOpaqueKeyEncrypter(alg, encrypter)
} }
return recipientKeyInfo{}, ErrUnsupportedKeyType return recipientKeyInfo{}, ErrUnsupportedKeyType
} }
@ -300,11 +319,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
return newDecrypter(decryptionKey.Key) return newDecrypter(decryptionKey.Key)
case *JSONWebKey: case *JSONWebKey:
return newDecrypter(decryptionKey.Key) return newDecrypter(decryptionKey.Key)
case OpaqueKeyDecrypter:
return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil
default:
return nil, ErrUnsupportedKeyType
} }
if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok {
return &opaqueKeyDecrypter{decrypter: okd}, nil
}
return nil, ErrUnsupportedKeyType
} }
// Implementation of encrypt method producing a JWE object. // Implementation of encrypt method producing a JWE object.
@ -403,9 +422,27 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
} }
} }
// Decrypt and validate the object and return the plaintext. Note that this // Decrypt and validate the object and return the plaintext. This
// function does not support multi-recipient, if you desire multi-recipient // function does not support multi-recipient. If you desire multi-recipient
// decryption use DecryptMulti instead. // decryption use DecryptMulti instead.
//
// The decryptionKey argument must contain a private or symmetric key
// and must have one of these types:
// - *ecdsa.PrivateKey
// - *rsa.PrivateKey
// - *JSONWebKey
// - JSONWebKey
// - *JSONWebKeySet
// - JSONWebKeySet
// - []byte (a symmetric key)
// - string (a symmetric key)
// - Any type that satisfies the OpaqueKeyDecrypter interface.
//
// Note that ed25519 is only available for signatures, not encryption, so is
// not an option here.
//
// Automatically decompresses plaintext, but returns an error if the decompressed
// data would be >250kB or >10x the size of the compressed data, whichever is larger.
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) { func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
headers := obj.mergedHeaders(nil) headers := obj.mergedHeaders(nil)
@ -462,15 +499,24 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
// The "zip" header parameter may only be present in the protected header. // The "zip" header parameter may only be present in the protected header.
if comp := obj.protected.getCompression(); comp != "" { if comp := obj.protected.getCompression(); comp != "" {
plaintext, err = decompress(comp, plaintext) plaintext, err = decompress(comp, plaintext)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
}
} }
return plaintext, err return plaintext, nil
} }
// DecryptMulti decrypts and validates the object and returns the plaintexts, // DecryptMulti decrypts and validates the object and returns the plaintexts,
// with support for multiple recipients. It returns the index of the recipient // with support for multiple recipients. It returns the index of the recipient
// for which the decryption was successful, the merged headers for that recipient, // for which the decryption was successful, the merged headers for that recipient,
// and the plaintext. // and the plaintext.
//
// The decryptionKey argument must have one of the types allowed for the
// decryptionKey argument of Decrypt().
//
// Automatically decompresses plaintext, but returns an error if the decompressed
// data would be >250kB or >3x the size of the compressed data, whichever is larger.
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
globalHeaders := obj.mergedHeaders(nil) globalHeaders := obj.mergedHeaders(nil)
@ -532,7 +578,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
// The "zip" header parameter may only be present in the protected header. // The "zip" header parameter may only be present in the protected header.
if comp := obj.protected.getCompression(); comp != "" { if comp := obj.protected.getCompression(); comp != "" {
plaintext, _ = decompress(comp, plaintext) plaintext, err = decompress(comp, plaintext)
if err != nil {
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
}
} }
sanitized, err := headers.sanitized() sanitized, err := headers.sanitized()

View File

@ -15,13 +15,11 @@
*/ */
/* /*
Package jose aims to provide an implementation of the Javascript Object Signing Package jose aims to provide an implementation of the Javascript Object Signing
and Encryption set of standards. It implements encryption and signing based on and Encryption set of standards. It implements encryption and signing based on
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
Token support available in a sub-package. The library supports both the compact Token support available in a sub-package. The library supports both the compact
and JWS/JWE JSON Serialization formats, and has optional support for multiple and JWS/JWE JSON Serialization formats, and has optional support for multiple
recipients. recipients.
*/ */
package jose package jose

View File

@ -21,6 +21,7 @@ import (
"compress/flate" "compress/flate"
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"math/big" "math/big"
"strings" "strings"
@ -85,7 +86,7 @@ func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
} }
} }
// Compress with DEFLATE // deflate compresses the input.
func deflate(input []byte) ([]byte, error) { func deflate(input []byte) ([]byte, error) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
@ -97,15 +98,27 @@ func deflate(input []byte) ([]byte, error) {
return output.Bytes(), err return output.Bytes(), err
} }
// Decompress with DEFLATE // inflate decompresses the input.
//
// Errors if the decompressed data would be >250kB or >10x the size of the
// compressed data, whichever is larger.
func inflate(input []byte) ([]byte, error) { func inflate(input []byte) ([]byte, error) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
reader := flate.NewReader(bytes.NewBuffer(input)) reader := flate.NewReader(bytes.NewBuffer(input))
_, err := io.Copy(output, reader) maxCompressedSize := 10 * int64(len(input))
if err != nil { if maxCompressedSize < 250000 {
maxCompressedSize = 250000
}
limit := maxCompressedSize + 1
n, err := io.CopyN(output, reader, limit)
if err != nil && err != io.EOF {
return nil, err return nil, err
} }
if n == limit {
return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
}
err = reader.Close() err = reader.Close()
return output.Bytes(), err return output.Bytes(), err
@ -189,3 +202,36 @@ func base64URLDecode(value string) ([]byte, error) {
value = strings.TrimRight(value, "=") value = strings.TrimRight(value, "=")
return base64.RawURLEncoding.DecodeString(value) return base64.RawURLEncoding.DecodeString(value)
} }
func base64EncodeLen(sl []byte) int {
return base64.RawURLEncoding.EncodedLen(len(sl))
}
func base64JoinWithDots(inputs ...[]byte) string {
if len(inputs) == 0 {
return ""
}
// Count of dots.
totalCount := len(inputs) - 1
for _, input := range inputs {
totalCount += base64EncodeLen(input)
}
out := make([]byte, totalCount)
startEncode := 0
for i, input := range inputs {
base64.RawURLEncoding.Encode(out[startEncode:], input)
if i == len(inputs)-1 {
continue
}
startEncode += base64EncodeLen(input)
out[startEncode] = '.'
startEncode++
}
return string(out)
}

View File

@ -75,14 +75,13 @@ import (
// //
// The JSON null value unmarshals into an interface, map, pointer, or slice // The JSON null value unmarshals into an interface, map, pointer, or slice
// by setting that Go value to nil. Because null is often used in JSON to mean // by setting that Go value to nil. Because null is often used in JSON to mean
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect // “not present,” unmarshaling a JSON null into any other Go type has no effect
// on the value and produces no error. // on the value and produces no error.
// //
// When unmarshaling quoted strings, invalid UTF-8 or // When unmarshaling quoted strings, invalid UTF-8 or
// invalid UTF-16 surrogate pairs are not treated as an error. // invalid UTF-16 surrogate pairs are not treated as an error.
// Instead, they are replaced by the Unicode replacement // Instead, they are replaced by the Unicode replacement
// character U+FFFD. // character U+FFFD.
//
func Unmarshal(data []byte, v interface{}) error { func Unmarshal(data []byte, v interface{}) error {
// Check for well-formedness. // Check for well-formedness.
// Avoids filling out half a data structure // Avoids filling out half a data structure

View File

@ -58,6 +58,7 @@ import (
// becomes a member of the object unless // becomes a member of the object unless
// - the field's tag is "-", or // - the field's tag is "-", or
// - the field is empty and its tag specifies the "omitempty" option. // - the field is empty and its tag specifies the "omitempty" option.
//
// The empty values are false, 0, any // The empty values are false, 0, any
// nil pointer or interface value, and any array, slice, map, or string of // nil pointer or interface value, and any array, slice, map, or string of
// length zero. The object's default key string is the struct field name // length zero. The object's default key string is the struct field name
@ -65,28 +66,28 @@ import (
// the struct field's tag value is the key name, followed by an optional comma // the struct field's tag value is the key name, followed by an optional comma
// and options. Examples: // and options. Examples:
// //
// // Field is ignored by this package. // // Field is ignored by this package.
// Field int `json:"-"` // Field int `json:"-"`
// //
// // Field appears in JSON as key "myName". // // Field appears in JSON as key "myName".
// Field int `json:"myName"` // Field int `json:"myName"`
// //
// // Field appears in JSON as key "myName" and // // Field appears in JSON as key "myName" and
// // the field is omitted from the object if its value is empty, // // the field is omitted from the object if its value is empty,
// // as defined above. // // as defined above.
// Field int `json:"myName,omitempty"` // Field int `json:"myName,omitempty"`
// //
// // Field appears in JSON as key "Field" (the default), but // // Field appears in JSON as key "Field" (the default), but
// // the field is skipped if empty. // // the field is skipped if empty.
// // Note the leading comma. // // Note the leading comma.
// Field int `json:",omitempty"` // Field int `json:",omitempty"`
// //
// The "string" option signals that a field is stored as JSON inside a // The "string" option signals that a field is stored as JSON inside a
// JSON-encoded string. It applies only to fields of string, floating point, // JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used // integer, or boolean types. This extra level of encoding is sometimes used
// when communicating with JavaScript programs: // when communicating with JavaScript programs:
// //
// Int64String int64 `json:",string"` // Int64String int64 `json:",string"`
// //
// The key name will be used if it's a non-empty string consisting of // The key name will be used if it's a non-empty string consisting of
// only Unicode letters, digits, dollar signs, percent signs, hyphens, // only Unicode letters, digits, dollar signs, percent signs, hyphens,
@ -133,7 +134,6 @@ import (
// JSON cannot represent cyclic data structures and Marshal does not // JSON cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in // handle them. Passing cyclic structures to Marshal will result in
// an infinite recursion. // an infinite recursion.
//
func Marshal(v interface{}) ([]byte, error) { func Marshal(v interface{}) ([]byte, error) {
e := &encodeState{} e := &encodeState{}
err := e.marshal(v) err := e.marshal(v)

View File

@ -240,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil)
// Number, for JSON numbers // Number, for JSON numbers
// string, for JSON string literals // string, for JSON string literals
// nil, for JSON null // nil, for JSON null
//
type Token interface{} type Token interface{}
const ( const (

View File

@ -252,13 +252,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
serializedProtected := mustSerializeJSON(obj.protected) serializedProtected := mustSerializeJSON(obj.protected)
return fmt.Sprintf( return base64JoinWithDots(
"%s.%s.%s.%s.%s", serializedProtected,
base64.RawURLEncoding.EncodeToString(serializedProtected), obj.recipients[0].encryptedKey,
base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey), obj.iv,
base64.RawURLEncoding.EncodeToString(obj.iv), obj.ciphertext,
base64.RawURLEncoding.EncodeToString(obj.ciphertext), obj.tag,
base64.RawURLEncoding.EncodeToString(obj.tag)), nil ), nil
} }
// FullSerialize serializes an object using the full JSON serialization format. // FullSerialize serializes an object using the full JSON serialization format.

View File

@ -67,9 +67,21 @@ type rawJSONWebKey struct {
X5tSHA256 string `json:"x5t#S256,omitempty"` X5tSHA256 string `json:"x5t#S256,omitempty"`
} }
// JSONWebKey represents a public or private key in JWK format. // JSONWebKey represents a public or private key in JWK format. It can be
// marshaled into JSON and unmarshaled from JSON.
type JSONWebKey struct { type JSONWebKey struct {
// Cryptographic key, can be a symmetric or asymmetric key. // Key is the Go in-memory representation of this key. It must have one
// of these types:
// - ed25519.PublicKey
// - ed25519.PrivateKey
// - *ecdsa.PublicKey
// - *ecdsa.PrivateKey
// - *rsa.PublicKey
// - *rsa.PrivateKey
// - []byte (a symmetric key)
//
// When marshaling this JSONWebKey into JSON, the "kty" header parameter
// will be automatically set based on the type of this field.
Key interface{} Key interface{}
// Key identifier, parsed from `kid` header. // Key identifier, parsed from `kid` header.
KeyID string KeyID string
@ -389,6 +401,8 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
input, err = rsaThumbprintInput(key.N, key.E) input, err = rsaThumbprintInput(key.N, key.E)
case ed25519.PrivateKey: case ed25519.PrivateKey:
input, err = edThumbprintInput(ed25519.PublicKey(key[32:])) input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
case OpaqueSigner:
return key.Public().Thumbprint(hash)
default: default:
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key)) return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
} }

View File

@ -314,15 +314,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
return "", ErrNotSupported return "", ErrNotSupported
} }
serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected)) serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
payload := ""
signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
var payload []byte
if !detached { if !detached {
payload = base64.RawURLEncoding.EncodeToString(obj.payload) payload = obj.payload
} }
return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil return base64JoinWithDots(
serializedProtected,
payload,
obj.Signatures[0].Signature,
), nil
} }
// CompactSerialize serializes an object using the compact serialization format. // CompactSerialize serializes an object using the compact serialization format.

View File

@ -119,7 +119,7 @@ func (s Audience) MarshalJSON() ([]byte, error) {
return json.Marshal([]string(s)) return json.Marshal([]string(s))
} }
//Contains checks whether a given string is included in the Audience // Contains checks whether a given string is included in the Audience
func (s Audience) Contains(v string) bool { func (s Audience) Contains(v string) bool {
for _, a := range s { for _, a := range s {
if a == v { if a == v {

View File

@ -15,8 +15,6 @@
*/ */
/* /*
Package jwt provides an implementation of the JSON Web Token standard. Package jwt provides an implementation of the JSON Web Token standard.
*/ */
package jwt package jwt

View File

@ -121,7 +121,7 @@ func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
return oke.encrypter.encryptKey(cek, alg) return oke.encrypter.encryptKey(cek, alg)
} }
//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key. // OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
type OpaqueKeyDecrypter interface { type OpaqueKeyDecrypter interface {
DecryptKey(encryptedKey []byte, header Header) ([]byte, error) DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
} }

View File

@ -183,8 +183,13 @@ type Header struct {
// Unverified certificate chain parsed from x5c header. // Unverified certificate chain parsed from x5c header.
certificates []*x509.Certificate certificates []*x509.Certificate
// Any headers not recognised above get unmarshalled // At parse time, each header parameter with a name other than "kid",
// from JSON in a generic manner and placed in this map. // "jwk", "alg", "nonce", or "x5c" will have its value passed to
// [json.Unmarshal] to unmarshal it into an interface value.
// The resulting value will be stored in this map, with the header
// parameter name as the key.
//
// [json.Unmarshal]: https://pkg.go.dev/encoding/json#Unmarshal
ExtraHeaders map[HeaderKey]interface{} ExtraHeaders map[HeaderKey]interface{}
} }

View File

@ -40,6 +40,15 @@ type Signer interface {
} }
// SigningKey represents an algorithm/key used to sign a message. // SigningKey represents an algorithm/key used to sign a message.
//
// Key must have one of these types:
// - ed25519.PrivateKey
// - *ecdsa.PrivateKey
// - *rsa.PrivateKey
// - *JSONWebKey
// - JSONWebKey
// - []byte (an HMAC key)
// - Any type that satisfies the OpaqueSigner interface
type SigningKey struct { type SigningKey struct {
Algorithm SignatureAlgorithm Algorithm SignatureAlgorithm
Key interface{} Key interface{}
@ -52,12 +61,22 @@ type SignerOptions struct {
// Optional map of additional keys to be inserted into the protected header // Optional map of additional keys to be inserted into the protected header
// of a JWS object. Some specifications which make use of JWS like to insert // of a JWS object. Some specifications which make use of JWS like to insert
// additional values here. All values must be JSON-serializable. // additional values here.
//
// Values will be serialized by [json.Marshal] and must be valid inputs to
// that function.
//
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
ExtraHeaders map[HeaderKey]interface{} ExtraHeaders map[HeaderKey]interface{}
} }
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it // WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
// if necessary. It returns itself and so can be used in a fluent style. // if necessary, and returns the updated SignerOptions.
//
// The v argument will be serialized by [json.Marshal] and must be a valid
// input to that function.
//
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions { func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
if so.ExtraHeaders == nil { if so.ExtraHeaders == nil {
so.ExtraHeaders = map[HeaderKey]interface{}{} so.ExtraHeaders = map[HeaderKey]interface{}{}
@ -173,11 +192,11 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
return newVerifier(verificationKey.Key) return newVerifier(verificationKey.Key)
case *JSONWebKey: case *JSONWebKey:
return newVerifier(verificationKey.Key) return newVerifier(verificationKey.Key)
case OpaqueVerifier:
return &opaqueVerifier{verifier: verificationKey}, nil
default:
return nil, ErrUnsupportedKeyType
} }
if ov, ok := verificationKey.(OpaqueVerifier); ok {
return &opaqueVerifier{verifier: ov}, nil
}
return nil, ErrUnsupportedKeyType
} }
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error { func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
@ -204,11 +223,11 @@ func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipient
return newJWKSigner(alg, signingKey) return newJWKSigner(alg, signingKey)
case *JSONWebKey: case *JSONWebKey:
return newJWKSigner(alg, *signingKey) return newJWKSigner(alg, *signingKey)
case OpaqueSigner:
return newOpaqueSigner(alg, signingKey)
default:
return recipientSigInfo{}, ErrUnsupportedKeyType
} }
if signer, ok := signingKey.(OpaqueSigner); ok {
return newOpaqueSigner(alg, signer)
}
return recipientSigInfo{}, ErrUnsupportedKeyType
} }
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) { func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
@ -321,12 +340,21 @@ func (ctx *genericSigner) Options() SignerOptions {
} }
// Verify validates the signature on the object and returns the payload. // Verify validates the signature on the object and returns the payload.
// This function does not support multi-signature, if you desire multi-sig // This function does not support multi-signature. If you desire multi-signature
// verification use VerifyMulti instead. // verification use VerifyMulti instead.
// //
// Be careful when verifying signatures based on embedded JWKs inside the // Be careful when verifying signatures based on embedded JWKs inside the
// payload header. You cannot assume that the key received in a payload is // payload header. You cannot assume that the key received in a payload is
// trusted. // trusted.
//
// The verificationKey argument must have one of these types:
// - ed25519.PublicKey
// - *ecdsa.PublicKey
// - *rsa.PublicKey
// - *JSONWebKey
// - JSONWebKey
// - []byte (an HMAC key)
// - Any type that implements the OpaqueVerifier interface.
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) { func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
err := obj.DetachedVerify(obj.payload, verificationKey) err := obj.DetachedVerify(obj.payload, verificationKey)
if err != nil { if err != nil {
@ -346,6 +374,9 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
// most cases, you will probably want to use Verify instead. DetachedVerify // most cases, you will probably want to use Verify instead. DetachedVerify
// is only useful if you have a payload and signature that are separated from // is only useful if you have a payload and signature that are separated from
// each other. // each other.
//
// The verificationKey argument must have one of the types allowed for the
// verificationKey argument of JSONWebSignature.Verify().
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error { func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
key := tryJWKS(verificationKey, obj.headers()...) key := tryJWKS(verificationKey, obj.headers()...)
verifier, err := newVerifier(key) verifier, err := newVerifier(key)
@ -388,6 +419,9 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
// returns the index of the signature that was verified, along with the signature // returns the index of the signature that was verified, along with the signature
// object and the payload. We return the signature and index to guarantee that // object and the payload. We return the signature and index to guarantee that
// callers are getting the verified value. // callers are getting the verified value.
//
// The verificationKey argument must have one of the types allowed for the
// verificationKey argument of JSONWebSignature.Verify().
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) { func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey) idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
if err != nil { if err != nil {
@ -405,6 +439,9 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
// DetachedVerifyMulti is only useful if you have a payload and signature that are // DetachedVerifyMulti is only useful if you have a payload and signature that are
// separated from each other, and the signature can have multiple signers at the // separated from each other, and the signature can have multiple signers at the
// same time. // same time.
//
// The verificationKey argument must have one of the types allowed for the
// verificationKey argument of JSONWebSignature.Verify().
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) { func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
key := tryJWKS(verificationKey, obj.headers()...) key := tryJWKS(verificationKey, obj.headers()...)
verifier, err := newVerifier(key) verifier, err := newVerifier(key)

View File

@ -40,12 +40,17 @@ var RandReader = rand.Reader
const ( const (
// RFC7518 recommends a minimum of 1,000 iterations: // RFC7518 recommends a minimum of 1,000 iterations:
// https://tools.ietf.org/html/rfc7518#section-4.8.1.2 // - https://tools.ietf.org/html/rfc7518#section-4.8.1.2
//
// NIST recommends a minimum of 10,000: // NIST recommends a minimum of 10,000:
// https://pages.nist.gov/800-63-3/sp800-63b.html // - https://pages.nist.gov/800-63-3/sp800-63b.html
// 1Password uses 100,000: //
// https://support.1password.com/pbkdf2/ // 1Password increased in 2023 from 100,000 to 650,000:
defaultP2C = 100000 // - https://support.1password.com/pbkdf2/
//
// OWASP recommended 600,000 in Dec 2022:
// - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
defaultP2C = 600000
// Default salt size: 128 bits // Default salt size: 128 bits
defaultP2SSize = 16 defaultP2SSize = 16
) )

2
vendor/modules.txt vendored
View File

@ -211,7 +211,7 @@ github.com/gemalto/kmip-go/ttlv
# github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 # github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
## explicit ## explicit
github.com/ghodss/yaml github.com/ghodss/yaml
# github.com/go-jose/go-jose/v3 v3.0.1 # github.com/go-jose/go-jose/v3 v3.0.3
## explicit; go 1.12 ## explicit; go 1.12
github.com/go-jose/go-jose/v3 github.com/go-jose/go-jose/v3
github.com/go-jose/go-jose/v3/cipher github.com/go-jose/go-jose/v3/cipher