From ace954224d0fdbf80f5c9be8455c3b5f8eed72fe Mon Sep 17 00:00:00 2001 From: Matthew McPherrin Date: Tue, 27 Feb 2024 14:37:10 -0500 Subject: [PATCH] Switch to go-jose v4 (#445) Switch to go-jose v4 This required a change to specify the supported signing algorithms, as part of go-jose/v4's breaking changes to defend against some attacks on JWS. Because Pebble already limited the supported algorithms, it was easy to see what the supported algorithms are. --- core/types.go | 3 +- db/memorystore.go | 2 +- go.mod | 2 +- go.sum | 4 +- .../go-jose/go-jose/v4}/.gitignore | 6 - .../go-jose/go-jose/v4/.golangci.yml | 53 ++++++ .../github.com/go-jose/go-jose/v4/.travis.yml | 33 ++++ .../go-jose/go-jose/v4/CHANGELOG.md | 61 +++++++ .../go-jose/go-jose/v4}/CONTRIBUTING.md | 5 +- .../go-jose/go-jose/v4}/LICENSE | 0 .../go-jose/go-jose/v4}/README.md | 60 ++++--- .../github.com/go-jose/go-jose/v4/SECURITY.md | 13 ++ .../go-jose/go-jose/v4}/asymmetric.go | 29 ++-- .../go-jose/go-jose/v4}/cipher/cbc_hmac.go | 14 +- .../go-jose/go-jose/v4}/cipher/concat_kdf.go | 0 .../go-jose/go-jose/v4}/cipher/ecdh_es.go | 0 .../go-jose/go-jose/v4}/cipher/key_wrap.go | 10 +- .../go-jose/go-jose/v4}/crypter.go | 125 +++++++++----- .../go-jose/go-jose/v4}/doc.go | 8 +- .../go-jose/go-jose/v4}/encoding.go | 39 ++++- .../go-jose/go-jose/v4}/json/LICENSE | 0 .../go-jose/go-jose/v4}/json/README.md | 0 .../go-jose/go-jose/v4}/json/decode.go | 3 +- .../go-jose/go-jose/v4}/json/encode.go | 30 ++-- .../go-jose/go-jose/v4}/json/indent.go | 0 .../go-jose/go-jose/v4}/json/scanner.go | 0 .../go-jose/go-jose/v4}/json/stream.go | 1 - .../go-jose/go-jose/v4}/json/tags.go | 0 .../go-jose/go-jose/v4}/jwe.go | 143 ++++++++++++---- .../go-jose/go-jose/v4}/jwk.go | 152 ++++++++++++------ .../go-jose/go-jose/v4}/jws.go | 103 +++++++++--- .../go-jose/go-jose/v4}/opaque.go | 2 +- .../go-jose/go-jose/v4}/shared.go | 41 ++--- .../go-jose/go-jose/v4}/signing.go | 100 +++++++++--- .../go-jose/go-jose/v4}/symmetric.go | 77 ++++++--- vendor/golang.org/x/crypto/ed25519/ed25519.go | 71 -------- .../square/go-jose.v2/.gitcookies.sh.enc | 1 - vendor/gopkg.in/square/go-jose.v2/.travis.yml | 45 ------ .../gopkg.in/square/go-jose.v2/BUG-BOUNTY.md | 10 -- vendor/modules.txt | 11 +- wfe/jose.go | 6 +- wfe/wfe.go | 6 +- 42 files changed, 832 insertions(+), 437 deletions(-) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/.gitignore (50%) create mode 100644 vendor/github.com/go-jose/go-jose/v4/.golangci.yml create mode 100644 vendor/github.com/go-jose/go-jose/v4/.travis.yml create mode 100644 vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/CONTRIBUTING.md (75%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/LICENSE (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/README.md (55%) create mode 100644 vendor/github.com/go-jose/go-jose/v4/SECURITY.md rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/asymmetric.go (92%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/cipher/cbc_hmac.go (91%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/cipher/concat_kdf.go (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/cipher/ecdh_es.go (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/cipher/key_wrap.go (88%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/crypter.go (78%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/doc.go (84%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/encoding.go (84%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/LICENSE (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/README.md (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/decode.go (99%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/encode.go (98%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/indent.go (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/scanner.go (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/stream.go (99%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/json/tags.go (100%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/jwe.go (61%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/jwk.go (77%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/jws.go (76%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/opaque.go (97%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/shared.go (91%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/signing.go (80%) rename vendor/{gopkg.in/square/go-jose.v2 => github.com/go-jose/go-jose/v4}/symmetric.go (83%) delete mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519.go delete mode 100644 vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc delete mode 100644 vendor/gopkg.in/square/go-jose.v2/.travis.yml delete mode 100644 vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md diff --git a/core/types.go b/core/types.go index 4452e8ee..b94d5a77 100644 --- a/core/types.go +++ b/core/types.go @@ -11,8 +11,9 @@ import ( "sync" "time" + "github.com/go-jose/go-jose/v4" + "github.com/letsencrypt/pebble/v2/acme" - "gopkg.in/square/go-jose.v2" ) type Order struct { diff --git a/db/memorystore.go b/db/memorystore.go index 7b836509..bf45796d 100644 --- a/db/memorystore.go +++ b/db/memorystore.go @@ -16,7 +16,7 @@ import ( "sync" "time" - "gopkg.in/square/go-jose.v2" + "github.com/go-jose/go-jose/v4" "github.com/letsencrypt/pebble/v2/acme" "github.com/letsencrypt/pebble/v2/core" diff --git a/go.mod b/go.mod index a3afc366..5800bed2 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/letsencrypt/pebble/v2 go 1.21 require ( + github.com/go-jose/go-jose/v4 v4.0.0 github.com/letsencrypt/challtestsrv v1.3.2 github.com/miekg/dns v1.1.58 - gopkg.in/square/go-jose.v2 v2.6.0 ) require ( diff --git a/go.sum b/go.sum index 8bf7a295..c39d800a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-jose/go-jose/v4 v4.0.0 h1:gHOVQyfrqsagdy/Yj9PTz5HMYzr3UpYh1CcFpktmRoY= +github.com/go-jose/go-jose/v4 v4.0.0/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/letsencrypt/challtestsrv v1.3.2 h1:pIDLBCLXR3B1DLmOmkkqg29qVa7DDozBnsOpL9PxmAY= @@ -30,7 +32,5 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/gopkg.in/square/go-jose.v2/.gitignore b/vendor/github.com/go-jose/go-jose/v4/.gitignore similarity index 50% rename from vendor/gopkg.in/square/go-jose.v2/.gitignore rename to vendor/github.com/go-jose/go-jose/v4/.gitignore index 95a85158..eb29ebae 100644 --- a/vendor/gopkg.in/square/go-jose.v2/.gitignore +++ b/vendor/github.com/go-jose/go-jose/v4/.gitignore @@ -1,8 +1,2 @@ -*~ -.*.swp -*.out -*.test -*.pem -*.cov jose-util/jose-util jose-util.t.err \ No newline at end of file diff --git a/vendor/github.com/go-jose/go-jose/v4/.golangci.yml b/vendor/github.com/go-jose/go-jose/v4/.golangci.yml new file mode 100644 index 00000000..2a577a8f --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/.golangci.yml @@ -0,0 +1,53 @@ +# https://github.com/golangci/golangci-lint + +run: + skip-files: + - doc_test.go + modules-download-mode: readonly + +linters: + enable-all: true + disable: + - gochecknoglobals + - goconst + - lll + - maligned + - nakedret + - scopelint + - unparam + - funlen # added in 1.18 (requires go-jose changes before it can be enabled) + +linters-settings: + gocyclo: + min-complexity: 35 + +issues: + exclude-rules: + - text: "don't use ALL_CAPS in Go names" + linters: + - golint + - text: "hardcoded credentials" + linters: + - gosec + - text: "weak cryptographic primitive" + linters: + - gosec + - path: json/ + linters: + - dupl + - errcheck + - gocritic + - gocyclo + - golint + - govet + - ineffassign + - staticcheck + - structcheck + - stylecheck + - unused + - path: _test\.go + linters: + - scopelint + - path: jwk.go + linters: + - gocyclo diff --git a/vendor/github.com/go-jose/go-jose/v4/.travis.yml b/vendor/github.com/go-jose/go-jose/v4/.travis.yml new file mode 100644 index 00000000..48de631b --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/.travis.yml @@ -0,0 +1,33 @@ +language: go + +matrix: + fast_finish: true + allow_failures: + - go: tip + +go: + - "1.13.x" + - "1.14.x" + - tip + +before_script: + - export PATH=$HOME/.local/bin:$PATH + +before_install: + - go get -u github.com/mattn/goveralls github.com/wadey/gocovmerge + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0 + - pip install cram --user + +script: + - go test -v -covermode=count -coverprofile=profile.cov . + - go test -v -covermode=count -coverprofile=cryptosigner/profile.cov ./cryptosigner + - go test -v -covermode=count -coverprofile=cipher/profile.cov ./cipher + - go test -v -covermode=count -coverprofile=jwt/profile.cov ./jwt + - go test -v ./json # no coverage for forked encoding/json package + - golangci-lint run + - cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util + - cd .. + +after_success: + - gocovmerge *.cov */*.cov > merged.coverprofile + - goveralls -coverprofile merged.coverprofile -service=travis-ci diff --git a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md new file mode 100644 index 00000000..08e43ab1 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md @@ -0,0 +1,61 @@ +# 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.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 + +## Fixed + + - Security issue: an attacker specifying a large "p2c" value can cause + JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large + amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the + disclosure and to Tom Tervoort for originally publishing the category of attack. + https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf diff --git a/vendor/gopkg.in/square/go-jose.v2/CONTRIBUTING.md b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md similarity index 75% rename from vendor/gopkg.in/square/go-jose.v2/CONTRIBUTING.md rename to vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md index 61b18365..b63e1f8f 100644 --- a/vendor/gopkg.in/square/go-jose.v2/CONTRIBUTING.md +++ b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md @@ -9,6 +9,7 @@ sure all tests pass by running `go test`, and format your code with `go fmt`. We also recommend using `golint` and `errcheck`. Before your code can be accepted into the project you must also sign the -[Individual Contributor License Agreement][1]. +Individual Contributor License Agreement. We use [cla-assistant.io][1] and you +will be prompted to sign once a pull request is opened. - [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1 +[1]: https://cla-assistant.io/ diff --git a/vendor/gopkg.in/square/go-jose.v2/LICENSE b/vendor/github.com/go-jose/go-jose/v4/LICENSE similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/LICENSE rename to vendor/github.com/go-jose/go-jose/v4/LICENSE diff --git a/vendor/gopkg.in/square/go-jose.v2/README.md b/vendor/github.com/go-jose/go-jose/v4/README.md similarity index 55% rename from vendor/gopkg.in/square/go-jose.v2/README.md rename to vendor/github.com/go-jose/go-jose/v4/README.md index 1791bfa8..64a86849 100644 --- a/vendor/gopkg.in/square/go-jose.v2/README.md +++ b/vendor/github.com/go-jose/go-jose/v4/README.md @@ -1,10 +1,9 @@ -# Go JOSE +# Go JOSE -[![godoc](http://img.shields.io/badge/godoc-version_1-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v1) -[![godoc](http://img.shields.io/badge/godoc-version_2-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v2) -[![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/square/go-jose/master/LICENSE) -[![build](https://travis-ci.org/square/go-jose.svg?branch=v2)](https://travis-ci.org/square/go-jose) -[![coverage](https://coveralls.io/repos/github/square/go-jose/badge.svg?branch=v2)](https://coveralls.io/r/square/go-jose) +[![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](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) +[![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE) +[![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v3)](https://github.com/go-jose/go-jose/actions) Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. This includes support for JSON Web Encryption, @@ -21,13 +20,13 @@ US maintained blocked list. ## Overview The implementation follows the -[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516), -[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and -[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519). +[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516), +[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and +[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications. Tables of supported algorithms are shown below. The library supports both -the compact and full 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 -([`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util)) +([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util)) for dealing with JOSE messages in a shell. **Note**: We use a forked version of the `encoding/json` package from the Go @@ -38,25 +37,22 @@ libraries in other languages. ### Versions -We use [gopkg.in](https://gopkg.in) for versioning. +[Version 4](https://github.com/go-jose/go-jose) +([branch](https://github.com/go-jose/go-jose/tree/main), +[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: -[Version 2](https://gopkg.in/square/go-jose.v2) -([branch](https://github.com/square/go-jose/tree/v2), -[doc](https://godoc.org/gopkg.in/square/go-jose.v2)) is the current version: + import "github.com/go-jose/go-jose/v4" - import "gopkg.in/square/go-jose.v2" +The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which +are still useable but not actively developed anymore. -The old `v1` branch ([go-jose.v1](https://gopkg.in/square/go-jose.v1)) will -still receive backported bug fixes and security fixes, but otherwise -development is frozen. All new feature development takes place on the `v2` -branch. Version 2 also contains additional sub-packages such as the -[jwt](https://godoc.org/gopkg.in/square/go-jose.v2/jwt) implementation -contributed by [@shaxbee](https://github.com/shaxbee). +Version 3, in this repo, is still receiving security fixes but not functionality +updates. ### Supported algorithms 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. Key encryption | Algorithm identifier(s) @@ -84,7 +80,7 @@ standard where possible. The Godoc reference has a list of constants. Content encryption | Algorithm identifier(s) :------------------------- | :------------------------------ AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 - AES-GCM | A128GCM, A192GCM, A256GCM + AES-GCM | A128GCM, A192GCM, A256GCM Compression | Algorithm identifiers(s) :------------------------- | ------------------------------- @@ -99,20 +95,20 @@ allows attaching a key id. Algorithm(s) | Corresponding types :------------------------- | ------------------------------- - RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey) - ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey) - EdDSA1 | [ed25519.PublicKey](https://godoc.org/golang.org/x/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/golang.org/x/crypto/ed25519#PrivateKey) + RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey) + ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey) + EdDSA1 | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey) AES, HMAC | []byte -1. Only available in version 2 of the package +1. Only available in version 2 or later of the package ## Examples -[![godoc](http://img.shields.io/badge/godoc-version_1-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v1) -[![godoc](http://img.shields.io/badge/godoc-version_2-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/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](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 reference for this package. The -[`jose-util`](https://github.com/square/go-jose/tree/v2/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 -as an example. +as an example as well. diff --git a/vendor/github.com/go-jose/go-jose/v4/SECURITY.md b/vendor/github.com/go-jose/go-jose/v4/SECURITY.md new file mode 100644 index 00000000..2f18a75a --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/SECURITY.md @@ -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 | ✓ | +| v2 | ✗ | +| v1 | ✗ | + +## 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. diff --git a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go b/vendor/github.com/go-jose/go-jose/v4/asymmetric.go similarity index 92% rename from vendor/gopkg.in/square/go-jose.v2/asymmetric.go rename to vendor/github.com/go-jose/go-jose/v4/asymmetric.go index b69aa036..f8d5774e 100644 --- a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go +++ b/vendor/github.com/go-jose/go-jose/v4/asymmetric.go @@ -20,6 +20,7 @@ import ( "crypto" "crypto/aes" "crypto/ecdsa" + "crypto/ed25519" "crypto/rand" "crypto/rsa" "crypto/sha1" @@ -28,9 +29,8 @@ import ( "fmt" "math/big" - "golang.org/x/crypto/ed25519" - josecipher "gopkg.in/square/go-jose.v2/cipher" - "gopkg.in/square/go-jose.v2/json" + josecipher "github.com/go-jose/go-jose/v4/cipher" + "github.com/go-jose/go-jose/v4/json" ) // A generic RSA-based encrypter/verifier @@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm switch alg { 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) case PS256, PS384, PS512: out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ @@ -413,28 +416,28 @@ func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) { func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { epk, err := headers.getEPK() if err != nil { - return nil, errors.New("square/go-jose: invalid epk header") + return nil, errors.New("go-jose/go-jose: invalid epk header") } if epk == nil { - return nil, errors.New("square/go-jose: missing epk header") + return nil, errors.New("go-jose/go-jose: missing epk header") } publicKey, ok := epk.Key.(*ecdsa.PublicKey) if publicKey == nil || !ok { - return nil, errors.New("square/go-jose: invalid epk header") + return nil, errors.New("go-jose/go-jose: invalid epk header") } if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { - return nil, errors.New("square/go-jose: invalid public key in epk header") + return nil, errors.New("go-jose/go-jose: invalid public key in epk header") } apuData, err := headers.getAPU() if err != nil { - return nil, errors.New("square/go-jose: invalid apu header") + return nil, errors.New("go-jose/go-jose: invalid apu header") } apvData, err := headers.getAPV() if err != nil { - return nil, errors.New("square/go-jose: invalid apv header") + return nil, errors.New("go-jose/go-jose: invalid apv header") } deriveKey := func(algID string, size int) []byte { @@ -489,7 +492,7 @@ func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a } ok := ed25519.Verify(ctx.publicKey, payload, signature) if !ok { - return errors.New("square/go-jose: ed25519 signature failed to verify") + return errors.New("go-jose/go-jose: ed25519 signature failed to verify") } return nil } @@ -513,7 +516,7 @@ func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) curveBits := ctx.privateKey.Curve.Params().BitSize if expectedBitSize != curveBits { - return Signature{}, fmt.Errorf("square/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits) + return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits) } hasher := hash.New() @@ -571,7 +574,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a } if len(signature) != 2*keySize { - return fmt.Errorf("square/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize) + return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize) } hasher := hash.New() @@ -585,7 +588,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a match := ecdsa.Verify(ctx.publicKey, hashed, r, s) if !match { - return errors.New("square/go-jose: ecdsa signature failed to verify") + return errors.New("go-jose/go-jose: ecdsa signature failed to verify") } return nil diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go b/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go similarity index 91% rename from vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go rename to vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go index f6465c04..af029cec 100644 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go @@ -101,23 +101,23 @@ func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { // Open decrypts and authenticates the ciphertext. func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(ciphertext) < ctx.authtagBytes { - return nil, errors.New("square/go-jose: invalid ciphertext (too short)") + return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)") } offset := len(ciphertext) - ctx.authtagBytes expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) if match != 1 { - return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)") + return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)") } cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) // Make copy of ciphertext buffer, don't want to modify in place - buffer := append([]byte{}, []byte(ciphertext[:offset])...) + buffer := append([]byte{}, ciphertext[:offset]...) if len(buffer)%ctx.blockCipher.BlockSize() > 0 { - return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)") + return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)") } cbc.CryptBlocks(buffer, buffer) @@ -177,19 +177,19 @@ func padBuffer(buffer []byte, blockSize int) []byte { // Remove padding func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) { if len(buffer)%blockSize != 0 { - return nil, errors.New("square/go-jose: invalid padding") + return nil, errors.New("go-jose/go-jose: invalid padding") } last := buffer[len(buffer)-1] count := int(last) if count == 0 || count > blockSize || count > len(buffer) { - return nil, errors.New("square/go-jose: invalid padding") + return nil, errors.New("go-jose/go-jose: invalid padding") } padding := bytes.Repeat([]byte{last}, count) if !bytes.HasSuffix(buffer, padding) { - return nil, errors.New("square/go-jose: invalid padding") + return nil, errors.New("go-jose/go-jose: invalid padding") } return buffer[:len(buffer)-count], nil diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go b/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go rename to vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go b/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go rename to vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go b/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go similarity index 88% rename from vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go rename to vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go index 1d36d501..b9effbca 100644 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go @@ -28,7 +28,7 @@ var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} // KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { if len(cek)%8 != 0 { - return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") + return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") } n := len(cek) / 8 @@ -51,7 +51,7 @@ func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { binary.BigEndian.PutUint64(tBytes, uint64(t+1)) for i := 0; i < 8; i++ { - buffer[i] = buffer[i] ^ tBytes[i] + buffer[i] ^= tBytes[i] } copy(r[t%n], buffer[8:]) } @@ -68,7 +68,7 @@ func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { // KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher. func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { if len(ciphertext)%8 != 0 { - return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") + return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") } n := (len(ciphertext) / 8) - 1 @@ -87,7 +87,7 @@ func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { binary.BigEndian.PutUint64(tBytes, uint64(t+1)) for i := 0; i < 8; i++ { - buffer[i] = buffer[i] ^ tBytes[i] + buffer[i] ^= tBytes[i] } copy(buffer[8:], r[t%n]) @@ -97,7 +97,7 @@ func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { } if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 { - return nil, errors.New("square/go-jose: failed to unwrap key") + return nil, errors.New("go-jose/go-jose: failed to unwrap key") } out := make([]byte, n*8) diff --git a/vendor/gopkg.in/square/go-jose.v2/crypter.go b/vendor/github.com/go-jose/go-jose/v4/crypter.go similarity index 78% rename from vendor/gopkg.in/square/go-jose.v2/crypter.go rename to vendor/github.com/go-jose/go-jose/v4/crypter.go index be7433e2..073767f6 100644 --- a/vendor/gopkg.in/square/go-jose.v2/crypter.go +++ b/vendor/github.com/go-jose/go-jose/v4/crypter.go @@ -21,9 +21,8 @@ import ( "crypto/rsa" "errors" "fmt" - "reflect" - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // Encrypter represents an encrypter which produces an encrypted JWE object. @@ -76,14 +75,24 @@ type recipientKeyInfo struct { type EncrypterOptions struct { Compression CompressionAlgorithm - // 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 - // additional values here. All values must be JSON-serializable. + // Optional map of name/value pairs to be inserted into the protected + // header of a JWS object. Some specifications which make use of + // 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{} } // 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 { if eo.ExtraHeaders == nil { 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 // be generated. 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{} KeyID string PBES2Count int @@ -150,16 +169,17 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) switch rcpt.Algorithm { case DIRECT: // Direct encryption mode must be treated differently - if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) { + keyBytes, ok := rawKey.([]byte) + if !ok { return nil, ErrUnsupportedKeyType } - if encrypter.cipher.keySize() != len(rawKey.([]byte)) { + if encrypter.cipher.keySize() != len(keyBytes) { return nil, ErrInvalidKeySize } encrypter.keyGenerator = staticKeyGenerator{ - key: rawKey.([]byte), + key: keyBytes, } - recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte)) + recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes) recipientInfo.keyID = keyID if rcpt.KeyID != "" { recipientInfo.keyID = rcpt.KeyID @@ -168,16 +188,16 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) return encrypter, nil case ECDH_ES: // ECDH-ES (w/o key wrapping) is similar to DIRECT mode - typeOf := reflect.TypeOf(rawKey) - if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) { + keyDSA, ok := rawKey.(*ecdsa.PublicKey) + if !ok { return nil, ErrUnsupportedKeyType } encrypter.keyGenerator = ecKeyGenerator{ size: encrypter.cipher.keySize(), algID: string(enc), - publicKey: rawKey.(*ecdsa.PublicKey), + publicKey: keyDSA, } - recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey)) + recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA) recipientInfo.keyID = keyID if rcpt.KeyID != "" { recipientInfo.keyID = rcpt.KeyID @@ -201,8 +221,8 @@ func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *Encrypter if cipher == nil { return nil, ErrUnsupportedAlgorithm } - if rcpts == nil || len(rcpts) == 0 { - return nil, fmt.Errorf("square/go-jose: recipients is nil or empty") + if len(rcpts) == 0 { + return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty") } encrypter := &genericEncrypter{ @@ -234,7 +254,7 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) { switch recipient.Algorithm { case DIRECT, ECDH_ES: - return fmt.Errorf("square/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm) + return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm) } recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key) @@ -270,9 +290,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey recipient, err := makeJWERecipient(alg, encryptionKey.Key) recipient.keyID = encryptionKey.KeyID return recipient, err - } - if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok { - return newOpaqueKeyEncrypter(alg, encrypter) + case OpaqueKeyEncrypter: + return newOpaqueKeyEncrypter(alg, encryptionKey) } return recipientKeyInfo{}, ErrUnsupportedKeyType } @@ -300,11 +319,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) { return newDecrypter(decryptionKey.Key) case *JSONWebKey: 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. @@ -326,7 +345,7 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe obj.recipients = make([]recipientInfo, len(ctx.recipients)) if len(ctx.recipients) == 0 { - return nil, fmt.Errorf("square/go-jose: no recipients to encrypt to") + return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to") } cek, headers, err := ctx.keyGenerator.genKey() @@ -403,33 +422,49 @@ func (ctx *genericEncrypter) Options() EncrypterOptions { } } -// Decrypt and validate the object and return the plaintext. Note that this -// function does not support multi-recipient, if you desire multi-recipient +// Decrypt and validate the object and return the plaintext. This +// function does not support multi-recipient. If you desire multi-recipient // 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. func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) { headers := obj.mergedHeaders(nil) if len(obj.recipients) > 1 { - return nil, errors.New("square/go-jose: too many recipients in payload; expecting only one") + return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one") } critical, err := headers.getCritical() if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid crit header") + return nil, fmt.Errorf("go-jose/go-jose: invalid crit header") } if len(critical) > 0 { - return nil, fmt.Errorf("square/go-jose: unsupported crit header") + return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") } - decrypter, err := newDecrypter(decryptionKey) + key := tryJWKS(decryptionKey, obj.Header) + decrypter, err := newDecrypter(key) if err != nil { return nil, err } cipher := getContentCipher(headers.getEncryption()) if cipher == nil { - return nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(headers.getEncryption())) + return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption())) } generator := randomKeyGenerator{ @@ -461,28 +496,35 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) // The "zip" header parameter may only be present in the protected header. if comp := obj.protected.getCompression(); comp != "" { 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, // with support for multiple recipients. It returns the index of the recipient // for which the decryption was successful, the merged headers for that recipient, // and the plaintext. +// +// The decryptionKey argument must have one of the types allowed for the +// decryptionKey argument of Decrypt(). func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { globalHeaders := obj.mergedHeaders(nil) critical, err := globalHeaders.getCritical() if err != nil { - return -1, Header{}, nil, fmt.Errorf("square/go-jose: invalid crit header") + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header") } if len(critical) > 0 { - return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header") + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") } - decrypter, err := newDecrypter(decryptionKey) + key := tryJWKS(decryptionKey, obj.Header) + decrypter, err := newDecrypter(key) if err != nil { return -1, Header{}, nil, err } @@ -490,7 +532,7 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade encryption := globalHeaders.getEncryption() cipher := getContentCipher(encryption) if cipher == nil { - return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(encryption)) + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption)) } generator := randomKeyGenerator{ @@ -524,18 +566,21 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade } } - if plaintext == nil || err != nil { + if plaintext == nil { return -1, Header{}, nil, ErrCryptoFailure } // The "zip" header parameter may only be present in the protected header. if comp := obj.protected.getCompression(); comp != "" { 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() if err != nil { - return -1, Header{}, nil, fmt.Errorf("square/go-jose: failed to sanitize header: %v", err) + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err) } return index, sanitized, plaintext, err diff --git a/vendor/gopkg.in/square/go-jose.v2/doc.go b/vendor/github.com/go-jose/go-jose/v4/doc.go similarity index 84% rename from vendor/gopkg.in/square/go-jose.v2/doc.go rename to vendor/github.com/go-jose/go-jose/v4/doc.go index dd1387f3..0ad40ca0 100644 --- a/vendor/gopkg.in/square/go-jose.v2/doc.go +++ b/vendor/github.com/go-jose/go-jose/v4/doc.go @@ -15,13 +15,11 @@ */ /* - Package jose aims to provide an implementation of the Javascript Object Signing 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 Token support available in a sub-package. The library supports both the -compact and full serialization formats, and has optional support for multiple +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 +and JWS/JWE JSON Serialization formats, and has optional support for multiple recipients. - */ package jose diff --git a/vendor/gopkg.in/square/go-jose.v2/encoding.go b/vendor/github.com/go-jose/go-jose/v4/encoding.go similarity index 84% rename from vendor/gopkg.in/square/go-jose.v2/encoding.go rename to vendor/github.com/go-jose/go-jose/v4/encoding.go index 70f7385c..bc714048 100644 --- a/vendor/gopkg.in/square/go-jose.v2/encoding.go +++ b/vendor/github.com/go-jose/go-jose/v4/encoding.go @@ -26,7 +26,7 @@ import ( "strings" "unicode" - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // Helper function to serialize known-good objects. @@ -41,7 +41,7 @@ func mustSerializeJSON(value interface{}) []byte { // MarshalJSON will happily serialize it as the top-level value "null". If // that value is then embedded in another operation, for instance by being // base64-encoded and fed as input to a signing algorithm - // (https://github.com/square/go-jose/issues/22), the result will be + // (https://github.com/go-jose/go-jose/issues/22), the result will be // incorrect. Because this method is intended for known-good objects, and a nil // pointer is not a known-good object, we are free to panic in this case. // Note: It's not possible to directly check whether the data pointed at by an @@ -127,7 +127,7 @@ func newBuffer(data []byte) *byteBuffer { func newFixedSizeBuffer(data []byte, length int) *byteBuffer { if len(data) > length { - panic("square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") + panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") } pad := make([]byte, length-len(data)) return newBuffer(append(pad, data...)) @@ -183,3 +183,36 @@ func (b byteBuffer) bigInt() *big.Int { func (b byteBuffer) toInt() int { return int(b.bigInt().Int64()) } + +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) +} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/LICENSE b/vendor/github.com/go-jose/go-jose/v4/json/LICENSE similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/json/LICENSE rename to vendor/github.com/go-jose/go-jose/v4/json/LICENSE diff --git a/vendor/gopkg.in/square/go-jose.v2/json/README.md b/vendor/github.com/go-jose/go-jose/v4/json/README.md similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/json/README.md rename to vendor/github.com/go-jose/go-jose/v4/json/README.md diff --git a/vendor/gopkg.in/square/go-jose.v2/json/decode.go b/vendor/github.com/go-jose/go-jose/v4/json/decode.go similarity index 99% rename from vendor/gopkg.in/square/go-jose.v2/json/decode.go rename to vendor/github.com/go-jose/go-jose/v4/json/decode.go index 4dbc4146..50634dd8 100644 --- a/vendor/gopkg.in/square/go-jose.v2/json/decode.go +++ b/vendor/github.com/go-jose/go-jose/v4/json/decode.go @@ -75,14 +75,13 @@ import ( // // 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 -// ``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. // // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement // character U+FFFD. -// func Unmarshal(data []byte, v interface{}) error { // Check for well-formedness. // Avoids filling out half a data structure diff --git a/vendor/gopkg.in/square/go-jose.v2/json/encode.go b/vendor/github.com/go-jose/go-jose/v4/json/encode.go similarity index 98% rename from vendor/gopkg.in/square/go-jose.v2/json/encode.go rename to vendor/github.com/go-jose/go-jose/v4/json/encode.go index 1dae8bb7..98de68ce 100644 --- a/vendor/gopkg.in/square/go-jose.v2/json/encode.go +++ b/vendor/github.com/go-jose/go-jose/v4/json/encode.go @@ -58,6 +58,7 @@ import ( // becomes a member of the object unless // - the field's tag is "-", or // - the field is empty and its tag specifies the "omitempty" option. +// // The empty values are false, 0, any // 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 @@ -65,28 +66,28 @@ import ( // the struct field's tag value is the key name, followed by an optional comma // and options. Examples: // -// // Field is ignored by this package. -// Field int `json:"-"` +// // Field is ignored by this package. +// Field int `json:"-"` // -// // Field appears in JSON as key "myName". -// Field int `json:"myName"` +// // Field appears in JSON as key "myName". +// Field int `json:"myName"` // -// // Field appears in JSON as key "myName" and -// // the field is omitted from the object if its value is empty, -// // as defined above. -// Field int `json:"myName,omitempty"` +// // Field appears in JSON as key "myName" and +// // the field is omitted from the object if its value is empty, +// // as defined above. +// Field int `json:"myName,omitempty"` // -// // Field appears in JSON as key "Field" (the default), but -// // the field is skipped if empty. -// // Note the leading comma. -// Field int `json:",omitempty"` +// // Field appears in JSON as key "Field" (the default), but +// // the field is skipped if empty. +// // Note the leading comma. +// Field int `json:",omitempty"` // // 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, // integer, or boolean types. This extra level of encoding is sometimes used // 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 // only Unicode letters, digits, dollar signs, percent signs, hyphens, @@ -133,7 +134,6 @@ import ( // JSON cannot represent cyclic data structures and Marshal does not // handle them. Passing cyclic structures to Marshal will result in // an infinite recursion. -// func Marshal(v interface{}) ([]byte, error) { e := &encodeState{} err := e.marshal(v) @@ -648,7 +648,7 @@ func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) { // for large buffers, avoid unnecessary extra temporary // buffer space. enc := base64.NewEncoder(base64.StdEncoding, e) - enc.Write(s) + _, _ = enc.Write(s) enc.Close() } e.WriteByte('"') diff --git a/vendor/gopkg.in/square/go-jose.v2/json/indent.go b/vendor/github.com/go-jose/go-jose/v4/json/indent.go similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/json/indent.go rename to vendor/github.com/go-jose/go-jose/v4/json/indent.go diff --git a/vendor/gopkg.in/square/go-jose.v2/json/scanner.go b/vendor/github.com/go-jose/go-jose/v4/json/scanner.go similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/json/scanner.go rename to vendor/github.com/go-jose/go-jose/v4/json/scanner.go diff --git a/vendor/gopkg.in/square/go-jose.v2/json/stream.go b/vendor/github.com/go-jose/go-jose/v4/json/stream.go similarity index 99% rename from vendor/gopkg.in/square/go-jose.v2/json/stream.go rename to vendor/github.com/go-jose/go-jose/v4/json/stream.go index 9b2b926b..f03b171e 100644 --- a/vendor/gopkg.in/square/go-jose.v2/json/stream.go +++ b/vendor/github.com/go-jose/go-jose/v4/json/stream.go @@ -240,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil) // Number, for JSON numbers // string, for JSON string literals // nil, for JSON null -// type Token interface{} const ( diff --git a/vendor/gopkg.in/square/go-jose.v2/json/tags.go b/vendor/github.com/go-jose/go-jose/v4/json/tags.go similarity index 100% rename from vendor/gopkg.in/square/go-jose.v2/json/tags.go rename to vendor/github.com/go-jose/go-jose/v4/json/tags.go diff --git a/vendor/gopkg.in/square/go-jose.v2/jwe.go b/vendor/github.com/go-jose/go-jose/v4/jwe.go similarity index 61% rename from vendor/gopkg.in/square/go-jose.v2/jwe.go rename to vendor/github.com/go-jose/go-jose/v4/jwe.go index b5a6dcdf..89f03ee3 100644 --- a/vendor/gopkg.in/square/go-jose.v2/jwe.go +++ b/vendor/github.com/go-jose/go-jose/v4/jwe.go @@ -18,10 +18,11 @@ package jose import ( "encoding/base64" + "errors" "fmt" "strings" - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing. @@ -86,11 +87,12 @@ func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader { func (obj JSONWebEncryption) computeAuthData() []byte { var protected string - if obj.original != nil && obj.original.Protected != nil { + switch { + case obj.original != nil && obj.original.Protected != nil: protected = obj.original.Protected.base64() - } else if obj.protected != nil { + case obj.protected != nil: protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected))) - } else { + default: protected = "" } @@ -103,29 +105,75 @@ func (obj JSONWebEncryption) computeAuthData() []byte { return output } -// ParseEncrypted parses an encrypted message in compact or full serialization format. -func ParseEncrypted(input string) (*JSONWebEncryption, error) { +func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool { + for _, algorithm := range haystack { + if algorithm == needle { + return true + } + } + return false +} + +func containsContentEncryption(haystack []ContentEncryption, needle ContentEncryption) bool { + for _, algorithm := range haystack { + if algorithm == needle { + return true + } + } + return false +} + +// ParseEncrypted parses an encrypted message in JWE Compact or JWE JSON Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1 +// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2 +// +// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" +// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in +// parsed data must contain a value that is present in the corresponding parameter. That +// includes the protected and unprotected headers as well as all recipients. To accept +// multiple algorithms, pass a slice of all the algorithms you want to accept. +func ParseEncrypted(input string, + keyEncryptionAlgorithms []KeyAlgorithm, + contentEncryption []ContentEncryption, +) (*JSONWebEncryption, error) { input = stripWhitespace(input) if strings.HasPrefix(input, "{") { - return parseEncryptedFull(input) + return ParseEncryptedJSON(input, keyEncryptionAlgorithms, contentEncryption) } - return parseEncryptedCompact(input) + return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption) } -// parseEncryptedFull parses a message in compact format. -func parseEncryptedFull(input string) (*JSONWebEncryption, error) { +// ParseEncryptedJSON parses a message in JWE JSON Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2 +func ParseEncryptedJSON( + input string, + keyEncryptionAlgorithms []KeyAlgorithm, + contentEncryption []ContentEncryption, +) (*JSONWebEncryption, error) { var parsed rawJSONWebEncryption err := json.Unmarshal([]byte(input), &parsed) if err != nil { return nil, err } - return parsed.sanitized() + return parsed.sanitized(keyEncryptionAlgorithms, contentEncryption) } // sanitized produces a cleaned-up JWE object from the raw JSON. -func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { +func (parsed *rawJSONWebEncryption) sanitized( + keyEncryptionAlgorithms []KeyAlgorithm, + contentEncryption []ContentEncryption, +) (*JSONWebEncryption, error) { + if len(keyEncryptionAlgorithms) == 0 { + return nil, errors.New("go-jose/go-jose: no key algorithms provided") + } + if len(contentEncryption) == 0 { + return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided") + } + obj := &JSONWebEncryption{ original: parsed, unprotected: parsed.Unprotected, @@ -146,7 +194,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected) if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64()) + return nil, fmt.Errorf("go-jose/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64()) } } @@ -156,7 +204,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { mergedHeaders := obj.mergedHeaders(nil) obj.Header, err = mergedHeaders.sanitized() if err != nil { - return nil, fmt.Errorf("square/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders) + return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders) } if len(parsed.Recipients) == 0 { @@ -184,10 +232,31 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { } } - for _, recipient := range obj.recipients { + for i, recipient := range obj.recipients { headers := obj.mergedHeaders(&recipient) - if headers.getAlgorithm() == "" || headers.getEncryption() == "" { - return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers") + if headers.getAlgorithm() == "" { + return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "alg"`, i) + } + if headers.getEncryption() == "" { + return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "enc"`, i) + } + err := validateAlgEnc(headers, keyEncryptionAlgorithms, contentEncryption) + if err != nil { + return nil, fmt.Errorf("go-jose/go-jose: recipient %d: %s", i, err) + } + + } + + if obj.protected != nil { + err := validateAlgEnc(*obj.protected, keyEncryptionAlgorithms, contentEncryption) + if err != nil { + return nil, fmt.Errorf("go-jose/go-jose: protected header: %s", err) + } + } + if obj.unprotected != nil { + err := validateAlgEnc(*obj.unprotected, keyEncryptionAlgorithms, contentEncryption) + if err != nil { + return nil, fmt.Errorf("go-jose/go-jose: unprotected header: %s", err) } } @@ -199,11 +268,29 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { return obj, nil } -// parseEncryptedCompact parses a message in compact format. -func parseEncryptedCompact(input string) (*JSONWebEncryption, error) { +func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncryption []ContentEncryption) error { + alg := headers.getAlgorithm() + enc := headers.getEncryption() + if alg != "" && !containsKeyAlgorithm(keyAlgorithms, alg) { + return fmt.Errorf("unexpected key algorithm %q; expected %q", alg, keyAlgorithms) + } + if alg != "" && !containsContentEncryption(contentEncryption, enc) { + return fmt.Errorf("unexpected content encryption algorithm %q; expected %q", enc, contentEncryption) + } + return nil +} + +// ParseEncryptedCompact parses a message in JWE Compact Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1 +func ParseEncryptedCompact( + input string, + keyAlgorithms []KeyAlgorithm, + contentEncryption []ContentEncryption, +) (*JSONWebEncryption, error) { parts := strings.Split(input, ".") if len(parts) != 5 { - return nil, fmt.Errorf("square/go-jose: compact JWE format must have five parts") + return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts") } rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0]) @@ -239,7 +326,7 @@ func parseEncryptedCompact(input string) (*JSONWebEncryption, error) { Tag: newBuffer(tag), } - return raw.sanitized() + return raw.sanitized(keyAlgorithms, contentEncryption) } // CompactSerialize serializes an object using the compact serialization format. @@ -251,13 +338,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) { serializedProtected := mustSerializeJSON(obj.protected) - return fmt.Sprintf( - "%s.%s.%s.%s.%s", - base64.RawURLEncoding.EncodeToString(serializedProtected), - base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey), - base64.RawURLEncoding.EncodeToString(obj.iv), - base64.RawURLEncoding.EncodeToString(obj.ciphertext), - base64.RawURLEncoding.EncodeToString(obj.tag)), nil + return base64JoinWithDots( + serializedProtected, + obj.recipients[0].encryptedKey, + obj.iv, + obj.ciphertext, + obj.tag, + ), nil } // FullSerialize serializes an object using the full JSON serialization format. diff --git a/vendor/gopkg.in/square/go-jose.v2/jwk.go b/vendor/github.com/go-jose/go-jose/v4/jwk.go similarity index 77% rename from vendor/gopkg.in/square/go-jose.v2/jwk.go rename to vendor/github.com/go-jose/go-jose/v4/jwk.go index 222e260c..a565aaab 100644 --- a/vendor/gopkg.in/square/go-jose.v2/jwk.go +++ b/vendor/github.com/go-jose/go-jose/v4/jwk.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto" "crypto/ecdsa" + "crypto/ed25519" "crypto/elliptic" "crypto/rsa" "crypto/sha1" @@ -34,9 +35,7 @@ import ( "reflect" "strings" - "golang.org/x/crypto/ed25519" - - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing. @@ -63,14 +62,26 @@ type rawJSONWebKey struct { Qi *byteBuffer `json:"qi,omitempty"` // Certificates X5c []string `json:"x5c,omitempty"` - X5u *url.URL `json:"x5u,omitempty"` + X5u string `json:"x5u,omitempty"` X5tSHA1 string `json:"x5t,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 { - // 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 identifier, parsed from `kid` header. KeyID string @@ -110,7 +121,7 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) { case []byte: raw, err = fromSymmetricKey(key) default: - return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key)) + return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key)) } if err != nil { @@ -129,13 +140,13 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) { x5tSHA256Len := len(k.CertificateThumbprintSHA256) if x5tSHA1Len > 0 { if x5tSHA1Len != sha1.Size { - return nil, fmt.Errorf("square/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len) + return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len) } raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1) } if x5tSHA256Len > 0 { if x5tSHA256Len != sha256.Size { - return nil, fmt.Errorf("square/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len) + return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len) } raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256) } @@ -149,14 +160,16 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) { expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw) if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) { - return nil, errors.New("square/go-jose: invalid SHA-1 thumbprint, does not match cert chain") + return nil, errors.New("go-jose/go-jose: invalid SHA-1 thumbprint, does not match cert chain") } if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) { - return nil, errors.New("square/go-jose: invalid or SHA-256 thumbprint, does not match cert chain") + return nil, errors.New("go-jose/go-jose: invalid or SHA-256 thumbprint, does not match cert chain") } } - raw.X5u = k.CertificatesURL + if k.CertificatesURL != nil { + raw.X5u = k.CertificatesURL.String() + } return json.Marshal(raw) } @@ -171,7 +184,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { certs, err := parseCertificateChain(raw.X5c) if err != nil { - return fmt.Errorf("square/go-jose: failed to unmarshal x5c field: %s", err) + return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err) } var key interface{} @@ -211,7 +224,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { } case "oct": if certPub != nil { - return errors.New("square/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain") + return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain") } key, err = raw.symmetricKey() case "OKP": @@ -226,10 +239,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { keyPub = key } } else { - err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv) + err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv) } default: - err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty) + err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty) } if err != nil { @@ -238,19 +251,24 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { if certPub != nil && keyPub != nil { if !reflect.DeepEqual(certPub, keyPub) { - return errors.New("square/go-jose: invalid JWK, public keys in key and x5c fields do not match") + return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match") } } *k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs} - k.CertificatesURL = raw.X5u + if raw.X5u != "" { + k.CertificatesURL, err = url.Parse(raw.X5u) + if err != nil { + return fmt.Errorf("go-jose/go-jose: invalid JWK, x5u header is invalid URL: %w", err) + } + } // x5t parameters are base64url-encoded SHA thumbprints // See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8 x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1) if err != nil { - return errors.New("square/go-jose: invalid JWK, x5t header has invalid encoding") + return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding") } // RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex, @@ -260,7 +278,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { if len(x5tSHA1bytes) == 2*sha1.Size { hx, err := hex.DecodeString(string(x5tSHA1bytes)) if err != nil { - return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t: %v", err) + return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t: %v", err) } x5tSHA1bytes = hx @@ -270,13 +288,13 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256) if err != nil { - return errors.New("square/go-jose: invalid JWK, x5t#S256 header has invalid encoding") + return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding") } if len(x5tSHA256bytes) == 2*sha256.Size { hx256, err := hex.DecodeString(string(x5tSHA256bytes)) if err != nil { - return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err) + return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err) } x5tSHA256bytes = hx256 } @@ -286,10 +304,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { x5tSHA1Len := len(k.CertificateThumbprintSHA1) x5tSHA256Len := len(k.CertificateThumbprintSHA256) if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size { - return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size") + return errors.New("go-jose/go-jose: invalid JWK, x5t header is of incorrect size") } if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size { - return errors.New("square/go-jose: invalid JWK, x5t#S256 header is of incorrect size") + return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header is of incorrect size") } // If certificate chain *and* thumbprints are set, verify correctness. @@ -299,11 +317,11 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { sha256sum := sha256.Sum256(leaf.Raw) if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) { - return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t value") + return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t value") } if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) { - return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value") + return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value") } } @@ -342,7 +360,7 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) { } if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength { - return "", errors.New("square/go-jose: invalid elliptic key (too large)") + return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)") } return fmt.Sprintf(ecThumbprintTemplate, crv, @@ -359,7 +377,7 @@ func rsaThumbprintInput(n *big.Int, e int) (string, error) { func edThumbprintInput(ed ed25519.PublicKey) (string, error) { crv := "Ed25519" if len(ed) > 32 { - return "", errors.New("square/go-jose: invalid elliptic key (too large)") + return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)") } return fmt.Sprintf(edThumbprintTemplate, crv, newFixedSizeBuffer(ed, 32).base64()), nil @@ -383,8 +401,10 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) { input, err = rsaThumbprintInput(key.N, key.E) case ed25519.PrivateKey: input, err = edThumbprintInput(ed25519.PublicKey(key[32:])) + case OpaqueSigner: + return key.Public().Thumbprint(hash) default: - return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key)) + return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key)) } if err != nil { @@ -392,7 +412,7 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) { } h := hash.New() - h.Write([]byte(input)) + _, _ = h.Write([]byte(input)) return h.Sum(nil), nil } @@ -463,7 +483,7 @@ func (k *JSONWebKey) Valid() bool { func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) { if key.N == nil || key.E == nil { - return nil, fmt.Errorf("square/go-jose: invalid RSA key, missing n/e values") + return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values") } return &rsa.PublicKey{ @@ -498,29 +518,29 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) { case "P-521": curve = elliptic.P521() default: - return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv) + return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv) } if key.X == nil || key.Y == nil { - return nil, errors.New("square/go-jose: invalid EC key, missing x/y values") + return nil, errors.New("go-jose/go-jose: invalid EC key, missing x/y values") } // The length of this octet string MUST be the full size of a coordinate for // the curve specified in the "crv" parameter. // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 if curveSize(curve) != len(key.X.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for x") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x") } if curveSize(curve) != len(key.Y.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for y") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y") } x := key.X.bigInt() y := key.Y.bigInt() if !curve.IsOnCurve(x, y) { - return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve") + return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve") } return &ecdsa.PublicKey{ @@ -532,7 +552,7 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) { func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) { if pub == nil || pub.X == nil || pub.Y == nil { - return nil, fmt.Errorf("square/go-jose: invalid EC key (nil, or X/Y missing)") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (nil, or X/Y missing)") } name, err := curveName(pub.Curve) @@ -546,7 +566,7 @@ func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) { yBytes := pub.Y.Bytes() if len(xBytes) > size || len(yBytes) > size { - return nil, fmt.Errorf("square/go-jose: invalid EC key (X/Y too large)") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (X/Y too large)") } key := &rawJSONWebKey{ @@ -569,7 +589,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) { } if len(missing) > 0 { - return nil, fmt.Errorf("square/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", ")) + return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", ")) } privateKey := make([]byte, ed25519.PrivateKeySize) @@ -581,7 +601,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) { func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) { if key.X == nil { - return nil, fmt.Errorf("square/go-jose: invalid Ed key, missing x value") + return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value") } publicKey := make([]byte, ed25519.PublicKeySize) copy(publicKey[0:32], key.X.bytes()) @@ -605,7 +625,7 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) { } if len(missing) > 0 { - return nil, fmt.Errorf("square/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", ")) + return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", ")) } rv := &rsa.PrivateKey{ @@ -675,34 +695,34 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) { case "P-521": curve = elliptic.P521() default: - return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv) + return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv) } if key.X == nil || key.Y == nil || key.D == nil { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, missing x/y/d values") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values") } // The length of this octet string MUST be the full size of a coordinate for // the curve specified in the "crv" parameter. // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 if curveSize(curve) != len(key.X.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x") } if curveSize(curve) != len(key.Y.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y") } // https://tools.ietf.org/html/rfc7518#section-6.2.2.1 if dSize(curve) != len(key.D.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for d") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d") } x := key.X.bigInt() y := key.Y.bigInt() if !curve.IsOnCurve(x, y) { - return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve") + return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve") } return &ecdsa.PrivateKey{ @@ -722,7 +742,7 @@ func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) { } if ec.D == nil { - return nil, fmt.Errorf("square/go-jose: invalid EC private key") + return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key") } raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve)) @@ -740,7 +760,7 @@ func dSize(curve elliptic.Curve) int { bitLen := order.BitLen() size := bitLen / 8 if bitLen%8 != 0 { - size = size + 1 + size++ } return size } @@ -754,7 +774,39 @@ func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) { func (key rawJSONWebKey) symmetricKey() ([]byte, error) { if key.K == nil { - return nil, fmt.Errorf("square/go-jose: invalid OCT (symmetric) key, missing k value") + return nil, fmt.Errorf("go-jose/go-jose: invalid OCT (symmetric) key, missing k value") } return key.K.bytes(), nil } + +func tryJWKS(key interface{}, headers ...Header) interface{} { + var jwks JSONWebKeySet + + switch jwksType := key.(type) { + case *JSONWebKeySet: + jwks = *jwksType + case JSONWebKeySet: + jwks = jwksType + default: + return key + } + + var kid string + for _, header := range headers { + if header.KeyID != "" { + kid = header.KeyID + break + } + } + + if kid == "" { + return key + } + + keys := jwks.Key(kid) + if len(keys) == 0 { + return key + } + + return keys[0].Key +} diff --git a/vendor/gopkg.in/square/go-jose.v2/jws.go b/vendor/github.com/go-jose/go-jose/v4/jws.go similarity index 76% rename from vendor/gopkg.in/square/go-jose.v2/jws.go rename to vendor/github.com/go-jose/go-jose/v4/jws.go index 7e261f93..3a912301 100644 --- a/vendor/gopkg.in/square/go-jose.v2/jws.go +++ b/vendor/github.com/go-jose/go-jose/v4/jws.go @@ -23,7 +23,7 @@ import ( "fmt" "strings" - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing. @@ -75,22 +75,41 @@ type Signature struct { original *rawSignatureInfo } -// ParseSigned parses a signed message in compact or full serialization format. -func ParseSigned(signature string) (*JSONWebSignature, error) { +// ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7515#section-7 +func ParseSigned( + signature string, + signatureAlgorithms []SignatureAlgorithm, +) (*JSONWebSignature, error) { signature = stripWhitespace(signature) if strings.HasPrefix(signature, "{") { - return parseSignedFull(signature) + return ParseSignedJSON(signature, signatureAlgorithms) } - return parseSignedCompact(signature, nil) + return parseSignedCompact(signature, nil, signatureAlgorithms) +} + +// ParseSignedCompact parses a message in JWS Compact Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1 +func ParseSignedCompact( + signature string, + signatureAlgorithms []SignatureAlgorithm, +) (*JSONWebSignature, error) { + return parseSignedCompact(signature, nil, signatureAlgorithms) } // ParseDetached parses a signed message in compact serialization format with detached payload. -func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) { +func ParseDetached( + signature string, + payload []byte, + signatureAlgorithms []SignatureAlgorithm, +) (*JSONWebSignature, error) { if payload == nil { - return nil, errors.New("square/go-jose: nil payload") + return nil, errors.New("go-jose/go-jose: nil payload") } - return parseSignedCompact(stripWhitespace(signature), payload) + return parseSignedCompact(stripWhitespace(signature), payload, signatureAlgorithms) } // Get a header value @@ -137,21 +156,38 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature return authData.Bytes(), nil } -// parseSignedFull parses a message in full format. -func parseSignedFull(input string) (*JSONWebSignature, error) { +// ParseSignedJSON parses a message in JWS JSON Serialization. +// +// https://datatracker.ietf.org/doc/html/rfc7515#section-7.2 +func ParseSignedJSON( + input string, + signatureAlgorithms []SignatureAlgorithm, +) (*JSONWebSignature, error) { var parsed rawJSONWebSignature err := json.Unmarshal([]byte(input), &parsed) if err != nil { return nil, err } - return parsed.sanitized() + return parsed.sanitized(signatureAlgorithms) +} + +func containsSignatureAlgorithm(haystack []SignatureAlgorithm, needle SignatureAlgorithm) bool { + for _, algorithm := range haystack { + if algorithm == needle { + return true + } + } + return false } // sanitized produces a cleaned-up JWS object from the raw JSON. -func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { +func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgorithm) (*JSONWebSignature, error) { + if len(signatureAlgorithms) == 0 { + return nil, errors.New("go-jose/go-jose: no signature algorithms specified") + } if parsed.Payload == nil { - return nil, fmt.Errorf("square/go-jose: missing payload in JWS message") + return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message") } obj := &JSONWebSignature{ @@ -198,6 +234,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { return nil, err } + alg := SignatureAlgorithm(signature.Header.Algorithm) + if !containsSignatureAlgorithm(signatureAlgorithms, alg) { + return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q", + alg, signatureAlgorithms) + } + if signature.header != nil { signature.Unprotected, err = signature.header.sanitized() if err != nil { @@ -215,7 +257,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. jwk := signature.Header.JSONWebKey if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { - return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") + return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key") } obj.Signatures = append(obj.Signatures, signature) @@ -241,6 +283,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { return nil, err } + alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm) + if !containsSignatureAlgorithm(signatureAlgorithms, alg) { + return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q", + alg, signatureAlgorithms) + } + if obj.Signatures[i].header != nil { obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized() if err != nil { @@ -260,7 +308,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. jwk := obj.Signatures[i].Header.JSONWebKey if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { - return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") + return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key") } // Copy value of sig @@ -274,14 +322,18 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { } // parseSignedCompact parses a message in compact format. -func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) { +func parseSignedCompact( + input string, + payload []byte, + signatureAlgorithms []SignatureAlgorithm, +) (*JSONWebSignature, error) { parts := strings.Split(input, ".") if len(parts) != 3 { - return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts") + return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts") } if parts[1] != "" && payload != nil { - return nil, fmt.Errorf("square/go-jose: payload is not detached") + return nil, fmt.Errorf("go-jose/go-jose: payload is not detached") } rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0]) @@ -306,7 +358,7 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) Protected: newBuffer(rawProtected), Signature: newBuffer(signature), } - return raw.sanitized() + return raw.sanitized(signatureAlgorithms) } func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) { @@ -314,15 +366,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) { return "", ErrNotSupported } - serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected)) - payload := "" - signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature) + serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) + var payload []byte 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. diff --git a/vendor/gopkg.in/square/go-jose.v2/opaque.go b/vendor/github.com/go-jose/go-jose/v4/opaque.go similarity index 97% rename from vendor/gopkg.in/square/go-jose.v2/opaque.go rename to vendor/github.com/go-jose/go-jose/v4/opaque.go index fc3e8d2e..68db085e 100644 --- a/vendor/gopkg.in/square/go-jose.v2/opaque.go +++ b/vendor/github.com/go-jose/go-jose/v4/opaque.go @@ -121,7 +121,7 @@ func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipie 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 { DecryptKey(encryptedKey []byte, header Header) ([]byte, error) } diff --git a/vendor/gopkg.in/square/go-jose.v2/shared.go b/vendor/github.com/go-jose/go-jose/v4/shared.go similarity index 91% rename from vendor/gopkg.in/square/go-jose.v2/shared.go rename to vendor/github.com/go-jose/go-jose/v4/shared.go index f72e5a53..b485e43b 100644 --- a/vendor/gopkg.in/square/go-jose.v2/shared.go +++ b/vendor/github.com/go-jose/go-jose/v4/shared.go @@ -23,7 +23,7 @@ import ( "errors" "fmt" - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // KeyAlgorithm represents a key management algorithm. @@ -45,32 +45,32 @@ var ( // ErrCryptoFailure represents an error in cryptographic primitive. This // occurs when, for example, a message had an invalid authentication tag or // could not be decrypted. - ErrCryptoFailure = errors.New("square/go-jose: error in cryptographic primitive") + ErrCryptoFailure = errors.New("go-jose/go-jose: error in cryptographic primitive") // ErrUnsupportedAlgorithm indicates that a selected algorithm is not // supported. This occurs when trying to instantiate an encrypter for an // algorithm that is not yet implemented. - ErrUnsupportedAlgorithm = errors.New("square/go-jose: unknown/unsupported algorithm") + ErrUnsupportedAlgorithm = errors.New("go-jose/go-jose: unknown/unsupported algorithm") // ErrUnsupportedKeyType indicates that the given key type/format is not // supported. This occurs when trying to instantiate an encrypter and passing // it a key of an unrecognized type or with unsupported parameters, such as // an RSA private key with more than two primes. - ErrUnsupportedKeyType = errors.New("square/go-jose: unsupported key type/format") + ErrUnsupportedKeyType = errors.New("go-jose/go-jose: unsupported key type/format") // ErrInvalidKeySize indicates that the given key is not the correct size // for the selected algorithm. This can occur, for example, when trying to // encrypt with AES-256 but passing only a 128-bit key as input. - ErrInvalidKeySize = errors.New("square/go-jose: invalid key size for algorithm") + ErrInvalidKeySize = errors.New("go-jose/go-jose: invalid key size for algorithm") // ErrNotSupported serialization of object is not supported. This occurs when // trying to compact-serialize an object which can't be represented in // compact form. - ErrNotSupported = errors.New("square/go-jose: compact serialization not supported for object") + ErrNotSupported = errors.New("go-jose/go-jose: compact serialization not supported for object") // ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a // nonce header parameter was included in an unprotected header object. - ErrUnprotectedNonce = errors.New("square/go-jose: Nonce parameter included in unprotected header") + ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header") ) // Key management algorithms @@ -133,8 +133,8 @@ const ( type HeaderKey string const ( - HeaderType HeaderKey = "typ" // string - HeaderContentType = "cty" // string + HeaderType = "typ" // string + HeaderContentType = "cty" // string // These are set by go-jose and shouldn't need to be set by consumers of the // library. @@ -183,8 +183,13 @@ type Header struct { // Unverified certificate chain parsed from x5c header. certificates []*x509.Certificate - // Any headers not recognised above get unmarshalled - // from JSON in a generic manner and placed in this map. + // At parse time, each header parameter with a name other than "kid", + // "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{} } @@ -194,7 +199,7 @@ type Header struct { // not be validated with the given verify options. func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) { if len(h.certificates) == 0 { - return nil, errors.New("square/go-jose: no x5c header present in message") + return nil, errors.New("go-jose/go-jose: no x5c header present in message") } leaf := h.certificates[0] @@ -452,8 +457,8 @@ func parseCertificateChain(chain []string) ([]*x509.Certificate, error) { return out, nil } -func (dst rawHeader) isSet(k HeaderKey) bool { - dvr := dst[k] +func (parsed rawHeader) isSet(k HeaderKey) bool { + dvr := parsed[k] if dvr == nil { return false } @@ -472,17 +477,17 @@ func (dst rawHeader) isSet(k HeaderKey) bool { } // Merge headers from src into dst, giving precedence to headers from l. -func (dst rawHeader) merge(src *rawHeader) { +func (parsed rawHeader) merge(src *rawHeader) { if src == nil { return } for k, v := range *src { - if dst.isSet(k) { + if parsed.isSet(k) { continue } - dst[k] = v + parsed[k] = v } } @@ -496,7 +501,7 @@ func curveName(crv elliptic.Curve) (string, error) { case elliptic.P521(): return "P-521", nil default: - return "", fmt.Errorf("square/go-jose: unsupported/unknown elliptic curve") + return "", fmt.Errorf("go-jose/go-jose: unsupported/unknown elliptic curve") } } diff --git a/vendor/gopkg.in/square/go-jose.v2/signing.go b/vendor/github.com/go-jose/go-jose/v4/signing.go similarity index 80% rename from vendor/gopkg.in/square/go-jose.v2/signing.go rename to vendor/github.com/go-jose/go-jose/v4/signing.go index bad820ce..f0b0294f 100644 --- a/vendor/gopkg.in/square/go-jose.v2/signing.go +++ b/vendor/github.com/go-jose/go-jose/v4/signing.go @@ -19,14 +19,13 @@ package jose import ( "bytes" "crypto/ecdsa" + "crypto/ed25519" "crypto/rsa" "encoding/base64" "errors" "fmt" - "golang.org/x/crypto/ed25519" - - "gopkg.in/square/go-jose.v2/json" + "github.com/go-jose/go-jose/v4/json" ) // NonceSource represents a source of random nonces to go into JWS objects @@ -41,6 +40,20 @@ type Signer interface { } // 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 +// +// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output: +// - HS256: 32 bytes +// - HS384: 48 bytes +// - HS512: 64 bytes type SigningKey struct { Algorithm SignatureAlgorithm Key interface{} @@ -53,12 +66,22 @@ type SignerOptions struct { // 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 - // 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{} } // 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 { if so.ExtraHeaders == nil { so.ExtraHeaders = map[HeaderKey]interface{}{} @@ -174,11 +197,11 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) { return newVerifier(verificationKey.Key) case *JSONWebKey: 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 { @@ -205,11 +228,11 @@ func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipient return newJWKSigner(alg, signingKey) case *JSONWebKey: 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) { @@ -227,7 +250,7 @@ func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigIn // This should be impossible, but let's check anyway. if !recipient.publicKey().IsPublic() { - return recipientSigInfo{}, errors.New("square/go-jose: public key was unexpectedly not public") + return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public") } } return recipient, nil @@ -251,7 +274,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { // result of the JOSE spec. We've decided that this library will only include one or // the other to avoid this confusion. // - // See https://github.com/square/go-jose/issues/157 for more context. + // See https://github.com/go-jose/go-jose/issues/157 for more context. if ctx.embedJWK { protected[headerJWK] = recipient.publicKey() } else { @@ -265,7 +288,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { if ctx.nonceSource != nil { nonce, err := ctx.nonceSource.Nonce() if err != nil { - return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err) + return nil, fmt.Errorf("go-jose/go-jose: Error generating nonce: %v", err) } protected[headerNonce] = nonce } @@ -279,7 +302,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { if b64, ok := protected[headerB64]; ok { if needsBase64, ok = b64.(bool); !ok { - return nil, errors.New("square/go-jose: Invalid b64 header parameter") + return nil, errors.New("go-jose/go-jose: Invalid b64 header parameter") } } @@ -303,7 +326,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { for k, v := range protected { b, err := json.Marshal(v) if err != nil { - return nil, fmt.Errorf("square/go-jose: Error marshalling item %#v: %v", k, err) + return nil, fmt.Errorf("go-jose/go-jose: Error marshalling item %#v: %v", k, err) } (*signatureInfo.protected)[k] = makeRawMessage(b) } @@ -322,12 +345,26 @@ func (ctx *genericSigner) Options() SignerOptions { } // 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. // // Be careful when verifying signatures based on embedded JWKs inside the // payload header. You cannot assume that the key received in a payload is // 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. +// +// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output: +// - HS256: 32 bytes +// - HS384: 48 bytes +// - HS512: 64 bytes func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) { err := obj.DetachedVerify(obj.payload, verificationKey) if err != nil { @@ -347,14 +384,18 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte { // 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 // 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 { - verifier, err := newVerifier(verificationKey) + key := tryJWKS(verificationKey, obj.headers()...) + verifier, err := newVerifier(key) if err != nil { return err } if len(obj.Signatures) > 1 { - return errors.New("square/go-jose: too many signatures in payload; expecting only one") + return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one") } signature := obj.Signatures[0] @@ -388,6 +429,9 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter // 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 // 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) { idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey) if err != nil { @@ -405,8 +449,12 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa // 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 // 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) { - verifier, err := newVerifier(verificationKey) + key := tryJWKS(verificationKey, obj.headers()...) + verifier, err := newVerifier(key) if err != nil { return -1, Signature{}, err } @@ -439,3 +487,11 @@ outer: return -1, Signature{}, ErrCryptoFailure } + +func (obj JSONWebSignature) headers() []Header { + headers := make([]Header, len(obj.Signatures)) + for i, sig := range obj.Signatures { + headers[i] = sig.Header + } + return headers +} diff --git a/vendor/gopkg.in/square/go-jose.v2/symmetric.go b/vendor/github.com/go-jose/go-jose/v4/symmetric.go similarity index 83% rename from vendor/gopkg.in/square/go-jose.v2/symmetric.go rename to vendor/github.com/go-jose/go-jose/v4/symmetric.go index 264a0fe3..a69103b0 100644 --- a/vendor/gopkg.in/square/go-jose.v2/symmetric.go +++ b/vendor/github.com/go-jose/go-jose/v4/symmetric.go @@ -31,20 +31,26 @@ import ( "io" "golang.org/x/crypto/pbkdf2" - "gopkg.in/square/go-jose.v2/cipher" + + josecipher "github.com/go-jose/go-jose/v4/cipher" ) -// Random reader (stubbed out in tests) +// RandReader is a cryptographically secure random number generator (stubbed out in tests). var RandReader = rand.Reader const ( // 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: - // https://pages.nist.gov/800-63-3/sp800-63b.html - // 1Password uses 100,000: - // https://support.1password.com/pbkdf2/ - defaultP2C = 100000 + // - https://pages.nist.gov/800-63-3/sp800-63b.html + // + // 1Password increased in 2023 from 100,000 to 650,000: + // - 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 defaultP2SSize = 16 ) @@ -278,8 +284,14 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie } header := &rawHeader{} - header.set(headerIV, newBuffer(parts.iv)) - header.set(headerTag, newBuffer(parts.tag)) + + if err = header.set(headerIV, newBuffer(parts.iv)); err != nil { + return recipientInfo{}, err + } + + if err = header.set(headerTag, newBuffer(parts.tag)); err != nil { + return recipientInfo{}, err + } return recipientInfo{ header: header, @@ -332,8 +344,14 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie } header := &rawHeader{} - header.set(headerP2C, ctx.p2c) - header.set(headerP2S, newBuffer(ctx.p2s)) + + if err = header.set(headerP2C, ctx.p2c); err != nil { + return recipientInfo{}, err + } + + if err = header.set(headerP2S, newBuffer(ctx.p2s)); err != nil { + return recipientInfo{}, err + } return recipientInfo{ encryptedKey: jek, @@ -356,11 +374,11 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien iv, err := headers.getIV() if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid IV: %v", err) + return nil, fmt.Errorf("go-jose/go-jose: invalid IV: %v", err) } tag, err := headers.getTag() if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid tag: %v", err) + return nil, fmt.Errorf("go-jose/go-jose: invalid tag: %v", err) } parts := &aeadParts{ @@ -389,18 +407,23 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW: p2s, err := headers.getP2S() if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid P2S: %v", err) + return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err) } if p2s == nil || len(p2s.data) == 0 { - return nil, fmt.Errorf("square/go-jose: invalid P2S: must be present") + return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present") } p2c, err := headers.getP2C() if err != nil { - return nil, fmt.Errorf("square/go-jose: invalid P2C: %v", err) + return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: %v", err) } if p2c <= 0 { - return nil, fmt.Errorf("square/go-jose: invalid P2C: must be a positive integer") + return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer") + } + if p2c > 1000000 { + // An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid + // DoS attacks. + return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high") } // salt is UTF8(Alg) || 0x00 || Salt Input @@ -431,7 +454,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { mac, err := ctx.hmac(payload, alg) if err != nil { - return Signature{}, errors.New("square/go-jose: failed to compute hmac") + return Signature{}, err } return Signature{ @@ -444,16 +467,16 @@ func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Sig func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error { expected, err := ctx.hmac(payload, alg) if err != nil { - return errors.New("square/go-jose: failed to compute hmac") + return errors.New("go-jose/go-jose: failed to compute hmac") } if len(mac) != len(expected) { - return errors.New("square/go-jose: invalid hmac") + return errors.New("go-jose/go-jose: invalid hmac") } match := subtle.ConstantTimeCompare(mac, expected) if match != 1 { - return errors.New("square/go-jose: invalid hmac") + return errors.New("go-jose/go-jose: invalid hmac") } return nil @@ -463,12 +486,24 @@ func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureA func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) { var hash func() hash.Hash + // https://datatracker.ietf.org/doc/html/rfc7518#section-3.2 + // A key of the same size as the hash output (for instance, 256 bits for + // "HS256") or larger MUST be used switch alg { case HS256: + if len(ctx.key)*8 < 256 { + return nil, ErrInvalidKeySize + } hash = sha256.New case HS384: + if len(ctx.key)*8 < 384 { + return nil, ErrInvalidKeySize + } hash = sha512.New384 case HS512: + if len(ctx.key)*8 < 512 { + return nil, ErrInvalidKeySize + } hash = sha512.New default: return nil, ErrUnsupportedAlgorithm diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go deleted file mode 100644 index a7828345..00000000 --- a/vendor/golang.org/x/crypto/ed25519/ed25519.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ed25519 implements the Ed25519 signature algorithm. See -// https://ed25519.cr.yp.to/. -// -// These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. However, unlike RFC 8032's formulation, this package's private key -// representation includes a public key suffix to make multiple signing -// operations with the same key more efficient. This package refers to the RFC -// 8032 private key as the “seed”. -// -// Beginning with Go 1.13, the functionality of this package was moved to the -// standard library as crypto/ed25519. This package only acts as a compatibility -// wrapper. -package ed25519 - -import ( - "crypto/ed25519" - "io" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 32 -) - -// PublicKey is the type of Ed25519 public keys. -// -// This type is an alias for crypto/ed25519's PublicKey type. -// See the crypto/ed25519 package for the methods on this type. -type PublicKey = ed25519.PublicKey - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -// -// This type is an alias for crypto/ed25519's PrivateKey type. -// See the crypto/ed25519 package for the methods on this type. -type PrivateKey = ed25519.PrivateKey - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - return ed25519.GenerateKey(rand) -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - return ed25519.NewKeyFromSeed(seed) -} - -// Sign signs the message with privateKey and returns a signature. It will -// panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - return ed25519.Sign(privateKey, message) -} - -// Verify reports whether sig is a valid signature of message by publicKey. It -// will panic if len(publicKey) is not PublicKeySize. -func Verify(publicKey PublicKey, message, sig []byte) bool { - return ed25519.Verify(publicKey, message, sig) -} diff --git a/vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc b/vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc deleted file mode 100644 index 730e569b..00000000 --- a/vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc +++ /dev/null @@ -1 +0,0 @@ -'|&{tU|gG(Cy=+c:u:/p#~["4!nADK merged.coverprofile -- $HOME/gopath/bin/goveralls -coverprofile merged.coverprofile -service=travis-ci diff --git a/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md b/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md deleted file mode 100644 index 3305db0f..00000000 --- a/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md +++ /dev/null @@ -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 . - diff --git a/vendor/modules.txt b/vendor/modules.txt index 730ebde8..4eb71c43 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,3 +1,8 @@ +# github.com/go-jose/go-jose/v4 v4.0.0 +## explicit; go 1.21 +github.com/go-jose/go-jose/v4 +github.com/go-jose/go-jose/v4/cipher +github.com/go-jose/go-jose/v4/json # github.com/google/go-cmp v0.6.0 ## explicit; go 1.13 # github.com/letsencrypt/challtestsrv v1.3.2 @@ -10,7 +15,6 @@ github.com/miekg/dns ## explicit; go 1.20 # golang.org/x/crypto v0.19.0 ## explicit; go 1.18 -golang.org/x/crypto/ed25519 golang.org/x/crypto/pbkdf2 # golang.org/x/mod v0.15.0 ## explicit; go 1.18 @@ -45,8 +49,3 @@ golang.org/x/tools/internal/tokeninternal golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# gopkg.in/square/go-jose.v2 v2.6.0 -## explicit -gopkg.in/square/go-jose.v2 -gopkg.in/square/go-jose.v2/cipher -gopkg.in/square/go-jose.v2/json diff --git a/wfe/jose.go b/wfe/jose.go index 3d7acb6e..6de7a41c 100644 --- a/wfe/jose.go +++ b/wfe/jose.go @@ -12,9 +12,13 @@ import ( "github.com/letsencrypt/pebble/v2/acme" - "gopkg.in/square/go-jose.v2" + jose "github.com/go-jose/go-jose/v4" ) +var goodJWSSignatureAlgorithms = []jose.SignatureAlgorithm{ + jose.RS256, jose.ES256, jose.ES384, jose.ES512, +} + func algorithmForKey(key *jose.JSONWebKey) (string, error) { switch k := key.Key.(type) { case *rsa.PublicKey: diff --git a/wfe/wfe.go b/wfe/wfe.go index 97c5be0a..a627d53f 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -26,7 +26,7 @@ import ( "time" "unicode" - "gopkg.in/square/go-jose.v2" + "github.com/go-jose/go-jose/v4" "github.com/letsencrypt/pebble/v2/acme" "github.com/letsencrypt/pebble/v2/ca" @@ -680,7 +680,7 @@ func (wfe *WebFrontEndImpl) parseJWS(body string) (*jose.JSONWebSignature, error "JWS \"signatures\" field not allowed. Only the \"signature\" field should contain a signature") } - parsedJWS, err := jose.ParseSigned(body) + parsedJWS, err := jose.ParseSigned(body, goodJWSSignatureAlgorithms) if err != nil { return nil, fmt.Errorf("Parse error reading JWS: %w", err) } @@ -2782,7 +2782,7 @@ func (wfe *WebFrontEndImpl) verifyEAB( fmt.Sprintf("failed to encode external account binding JSON structure: %s", err)) } - eab, err := jose.ParseSigned(string(eabBytes)) + eab, err := jose.ParseSigned(string(eabBytes), goodJWSSignatureAlgorithms) if err != nil { return nil, acme.MalformedProblem( fmt.Sprintf("failed to decode external account binding: %s", err))