vendor: revendor
This commit is contained in:
4
vendor/gopkg.in/square/go-jose.v2/.travis.yml
generated
vendored
4
vendor/gopkg.in/square/go-jose.v2/.travis.yml
generated
vendored
@@ -10,9 +10,10 @@ matrix:
|
||||
go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- tip
|
||||
|
||||
go_import_path: gopkg.in/square/go-jose.v1
|
||||
go_import_path: gopkg.in/square/go-jose.v2
|
||||
|
||||
before_script:
|
||||
- export PATH=$HOME/.local/bin:$PATH
|
||||
@@ -32,7 +33,6 @@ before_install:
|
||||
|
||||
script:
|
||||
- go test . -v -covermode=count -coverprofile=profile.cov
|
||||
- go test . -tags std_json -v -covermode=count -coverprofile=profile-std-json.cov
|
||||
- go test ./cipher -v -covermode=count -coverprofile=cipher/profile.cov
|
||||
- go test ./jwt -v -covermode=count -coverprofile=jwt/profile.cov
|
||||
- go test ./json -v # no coverage for forked encoding/json package
|
||||
|
184
vendor/gopkg.in/square/go-jose.v2/README.md
generated
vendored
184
vendor/gopkg.in/square/go-jose.v2/README.md
generated
vendored
@@ -1,16 +1,14 @@
|
||||
# Go JOSE
|
||||
|
||||
**Please note that this branch is still under active development.**
|
||||
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v2)
|
||||
[](https://raw.githubusercontent.com/square/go-jose/master/LICENSE)
|
||||
[](https://travis-ci.org/square/go-jose)
|
||||
[](https://coveralls.io/r/square/go-jose)
|
||||
[](https://goreportcard.com/report/github.com/square/go-jose)
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v1)
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v2)
|
||||
[](https://raw.githubusercontent.com/square/go-jose/master/LICENSE)
|
||||
[](https://travis-ci.org/square/go-jose)
|
||||
[](https://coveralls.io/r/square/go-jose)
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. For the moment, it mainly focuses on encryption
|
||||
and signing based on the JSON Web Encryption and JSON Web Signature standards.
|
||||
and Encryption set of standards. This includes support for JSON Web Encryption,
|
||||
JSON Web Signature, and JSON Web Token standards.
|
||||
|
||||
**Disclaimer**: This library contains encryption software that is subject to
|
||||
the U.S. Export Administration Regulations. You may not export, re-export,
|
||||
@@ -23,44 +21,50 @@ US maintained blocked list.
|
||||
## Overview
|
||||
|
||||
The implementation follows the
|
||||
[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516)
|
||||
standard (RFC 7516) and
|
||||
[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515)
|
||||
standard (RFC 7515). Tables of supported algorithms are shown below.
|
||||
The library supports both the compact and full 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/master/jose-util))
|
||||
[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).
|
||||
Tables of supported algorithms are shown below. The library supports both
|
||||
the compact and full 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))
|
||||
for dealing with JOSE messages in a shell.
|
||||
|
||||
**Note**: We use a forked version of the `encoding/json` package from the Go
|
||||
standard library which uses case-sensitive matching for member names (instead
|
||||
of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)).
|
||||
This is to avoid differences in interpretation of messages between go-jose and
|
||||
libraries in other languages. If you do not like this behavior, you can use the
|
||||
`std_json` build tag to disable it (though we do not recommend doing so).
|
||||
libraries in other languages.
|
||||
|
||||
### Versions
|
||||
|
||||
We use [gopkg.in](https://gopkg.in) for versioning.
|
||||
|
||||
[Version 1](https://gopkg.in/square/go-jose.v1) is the current stable version:
|
||||
[Version 1](https://gopkg.in/square/go-jose.v1) is the old stable version:
|
||||
|
||||
import "gopkg.in/square/go-jose.v1"
|
||||
|
||||
[Version 2](https://gopkg.in/square/go-jose.v2) is for new development:
|
||||
|
||||
import "gopkg.in/square/go-jose.v2"
|
||||
|
||||
The interface for [go-jose.v1](https://gopkg.in/square/go-jose.v1) will remain
|
||||
backwards compatible. We're currently sketching out ideas for a new version, to
|
||||
clean up the interface a bit. If you have ideas or feature requests [please let
|
||||
us know](https://github.com/square/go-jose/issues/64)!
|
||||
backwards compatible. No new feature development will take place on the `v1` branch,
|
||||
however bug fixes and security fixes will be backported.
|
||||
|
||||
The interface for [go-jose.v2](https://gopkg.in/square/go-jose.v2) is mostly
|
||||
stable, but we suggest pinning to a particular revision for now as we still reserve
|
||||
the right to make changes. New feature development happens on this branch.
|
||||
|
||||
New in [go-jose.v2](https://gopkg.in/square/go-jose.v2) is a
|
||||
[jwt](https://godoc.org/gopkg.in/square/go-jose.v2/jwt) sub-package
|
||||
contributed by [@shaxbee](https://github.com/shaxbee).
|
||||
|
||||
### 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)
|
||||
standard where possible. The
|
||||
[Godoc reference](https://godoc.org/github.com/square/go-jose#pkg-constants)
|
||||
has a list of constants.
|
||||
the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518)
|
||||
standard where possible. The Godoc reference has a list of constants.
|
||||
|
||||
Key encryption | Algorithm identifier(s)
|
||||
:------------------------- | :------------------------------
|
||||
@@ -94,122 +98,22 @@ has a list of constants.
|
||||
|
||||
See below for a table of supported key types. These are understood by the
|
||||
library, and can be passed to corresponding functions such as `NewEncrypter` or
|
||||
`NewSigner`. Note that if you are creating a new encrypter or signer with a
|
||||
JSONWebKey, the key id of the JSONWebKey (if present) will be added to any
|
||||
resulting messages.
|
||||
`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which
|
||||
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), *[jose.JSONWebKey](https://godoc.org/gopkg.in/square/go-jose.v2#JSONWebKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey), *[jose.JSONWebKey](https://godoc.org/gopkg.in/square/go-jose.v2#JSONWebKey)
|
||||
AES, HMAC | []byte, *[jose.JSONWebKey](https://godoc.org/gopkg.in/square/go-jose.v2#JSONWebKey)
|
||||
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)
|
||||
AES, HMAC | []byte
|
||||
|
||||
## Examples
|
||||
|
||||
Encryption/decryption example using RSA:
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v1)
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v2)
|
||||
|
||||
```Go
|
||||
// Generate a public/private key pair to use for this example. The library
|
||||
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
|
||||
// that can be used to load keys from PEM/DER-encoded data.
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Instantiate an encrypter using RSA-OAEP with AES128-GCM. An error would
|
||||
// indicate that the selected algorithm(s) are not currently supported.
|
||||
publicKey := &privateKey.PublicKey
|
||||
encrypter, err := NewEncrypter(A128GCM, Recipient{Algorithm: RSA_OAEP, Key: publicKey}, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encrypt a sample plaintext. Calling the encrypter returns an encrypted
|
||||
// JWE object, which can then be serialized for output afterwards. An error
|
||||
// would indicate a problem in an underlying cryptographic primitive.
|
||||
var plaintext = []byte("Lorem ipsum dolor sit amet")
|
||||
object, err := encrypter.Encrypt(plaintext)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Serialize the encrypted object using the full serialization format.
|
||||
// Alternatively you can also use the compact format here by calling
|
||||
// object.CompactSerialize() instead.
|
||||
serialized := object.FullSerialize()
|
||||
|
||||
// Parse the serialized, encrypted JWE object. An error would indicate that
|
||||
// the given input did not represent a valid message.
|
||||
object, err = ParseEncrypted(serialized)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Now we can decrypt and get back our original plaintext. An error here
|
||||
// would indicate the the message failed to decrypt, e.g. because the auth
|
||||
// tag was broken or the message was tampered with.
|
||||
decrypted, err := object.Decrypt(privateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf(string(decrypted))
|
||||
// output: Lorem ipsum dolor sit amet
|
||||
```
|
||||
|
||||
Signing/verification example using RSA:
|
||||
|
||||
```Go
|
||||
// Generate a public/private key pair to use for this example. The library
|
||||
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
|
||||
// that can be used to load keys from PEM/DER-encoded data.
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Instantiate a signer using RSASSA-PSS (SHA512) with the given private key.
|
||||
signer, err := NewSigner(SigningKey{Algorithm: PS512, Key: privateKey}, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Sign a sample payload. Calling the signer returns a protected JWS object,
|
||||
// which can then be serialized for output afterwards. An error would
|
||||
// indicate a problem in an underlying cryptographic primitive.
|
||||
var payload = []byte("Lorem ipsum dolor sit amet")
|
||||
object, err := signer.Sign(payload)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Serialize the encrypted object using the full serialization format.
|
||||
// Alternatively you can also use the compact format here by calling
|
||||
// object.CompactSerialize() instead.
|
||||
serialized := object.FullSerialize()
|
||||
|
||||
// Parse the serialized, protected JWS object. An error would indicate that
|
||||
// the given input did not represent a valid message.
|
||||
object, err = ParseSigned(serialized)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Now we can verify the signature on the payload. An error here would
|
||||
// indicate the the message failed to verify, e.g. because the signature was
|
||||
// broken or the message was tampered with.
|
||||
output, err := object.Verify(&privateKey.PublicKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf(string(output))
|
||||
// output: Lorem ipsum dolor sit amet
|
||||
```
|
||||
|
||||
More examples can be found in the [Godoc
|
||||
reference](https://godoc.org/github.com/square/go-jose) for this package. The
|
||||
[`jose-util`](https://github.com/square/go-jose/tree/master/jose-util)
|
||||
subdirectory also contains a small command-line utility which might
|
||||
be useful as an example.
|
||||
Examples can be found in the Godoc
|
||||
reference for this package. The
|
||||
[`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util)
|
||||
subdirectory also contains a small command-line utility which might be useful
|
||||
as an example.
|
||||
|
22
vendor/gopkg.in/square/go-jose.v2/asymmetric.go
generated
vendored
22
vendor/gopkg.in/square/go-jose.v2/asymmetric.go
generated
vendored
@@ -67,6 +67,10 @@ func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKe
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if publicKey == nil {
|
||||
return recipientKeyInfo{}, errors.New("invalid public key")
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyAlg: keyAlg,
|
||||
keyEncrypter: &rsaEncrypterVerifier{
|
||||
@@ -84,6 +88,10 @@ func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipi
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if privateKey == nil {
|
||||
return recipientSigInfo{}, errors.New("invalid private key")
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
publicKey: &JSONWebKey{
|
||||
@@ -104,6 +112,10 @@ func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipien
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
|
||||
return recipientKeyInfo{}, errors.New("invalid public key")
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyAlg: keyAlg,
|
||||
keyEncrypter: &ecEncrypterVerifier{
|
||||
@@ -121,6 +133,10 @@ func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (re
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if privateKey == nil {
|
||||
return recipientSigInfo{}, errors.New("invalid private key")
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
publicKey: &JSONWebKey{
|
||||
@@ -370,6 +386,10 @@ func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientI
|
||||
return nil, errors.New("square/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")
|
||||
}
|
||||
|
||||
apuData := headers.Apu.bytes()
|
||||
apvData := headers.Apv.bytes()
|
||||
|
||||
@@ -474,6 +494,8 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
|
||||
case ES512:
|
||||
keySize = 66
|
||||
hash = crypto.SHA512
|
||||
default:
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if len(signature) != 2*keySize {
|
||||
|
37
vendor/gopkg.in/square/go-jose.v2/asymmetric_test.go
generated
vendored
37
vendor/gopkg.in/square/go-jose.v2/asymmetric_test.go
generated
vendored
@@ -18,6 +18,8 @@ package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
@@ -429,3 +431,38 @@ func TestInvalidEllipticCurve(t *testing.T) {
|
||||
t.Error("should not generate ES384 signature with P-521 key")
|
||||
}
|
||||
}
|
||||
|
||||
func estInvalidECPublicKey(t *testing.T) {
|
||||
// Invalid key
|
||||
invalid := &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: fromBase64Int("MTEx"),
|
||||
Y: fromBase64Int("MTEx"),
|
||||
},
|
||||
D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo"),
|
||||
}
|
||||
|
||||
headers := rawHeader{
|
||||
Alg: string(ECDH_ES),
|
||||
Epk: &JSONWebKey{
|
||||
Key: &invalid.PublicKey,
|
||||
},
|
||||
}
|
||||
|
||||
dec := ecDecrypterSigner{
|
||||
privateKey: ecTestKey256,
|
||||
}
|
||||
|
||||
_, err := dec.decryptKey(headers, nil, randomKeyGenerator{size: 16})
|
||||
if err == nil {
|
||||
t.Fatal("decrypter accepted JWS with invalid ECDH public key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidAlgorithmEC(t *testing.T) {
|
||||
err := ecEncrypterVerifier{publicKey: &ecTestKey256.PublicKey}.verifyPayload([]byte{}, []byte{}, "XYZ")
|
||||
if err != ErrUnsupportedAlgorithm {
|
||||
t.Fatal("should not accept invalid/unsupported algorithm")
|
||||
}
|
||||
}
|
||||
|
16
vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go
generated
vendored
16
vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go
generated
vendored
@@ -82,7 +82,7 @@ func (ctx *cbcAEAD) Overhead() int {
|
||||
// Seal encrypts and authenticates the plaintext.
|
||||
func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
// Output buffer -- must take care not to mangle plaintext input.
|
||||
ciphertext := make([]byte, len(plaintext)+ctx.Overhead())[:len(plaintext)]
|
||||
ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)]
|
||||
copy(ciphertext, plaintext)
|
||||
ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize())
|
||||
|
||||
@@ -91,7 +91,7 @@ func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
||||
authtag := ctx.computeAuthTag(data, nonce, ciphertext)
|
||||
|
||||
ret, out := resize(dst, len(dst)+len(ciphertext)+len(authtag))
|
||||
ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag)))
|
||||
copy(out, ciphertext)
|
||||
copy(out[len(ciphertext):], authtag)
|
||||
|
||||
@@ -128,7 +128,7 @@ func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, out := resize(dst, len(dst)+len(plaintext))
|
||||
ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext)))
|
||||
copy(out, plaintext)
|
||||
|
||||
return ret, nil
|
||||
@@ -136,12 +136,12 @@ func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
|
||||
// Compute an authentication tag
|
||||
func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
|
||||
buffer := make([]byte, len(aad)+len(nonce)+len(ciphertext)+8)
|
||||
buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8)
|
||||
n := 0
|
||||
n += copy(buffer, aad)
|
||||
n += copy(buffer[n:], nonce)
|
||||
n += copy(buffer[n:], ciphertext)
|
||||
binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad)*8))
|
||||
binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8)
|
||||
|
||||
// According to documentation, Write() on hash.Hash never fails.
|
||||
hmac := hmac.New(ctx.hash, ctx.integrityKey)
|
||||
@@ -153,8 +153,8 @@ func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
|
||||
// resize ensures the the given slice has a capacity of at least n bytes.
|
||||
// If the capacity of the slice is less than n, a new slice is allocated
|
||||
// and the existing data will be copied.
|
||||
func resize(in []byte, n int) (head, tail []byte) {
|
||||
if cap(in) >= n {
|
||||
func resize(in []byte, n uint64) (head, tail []byte) {
|
||||
if uint64(cap(in)) >= n {
|
||||
head = in[:n]
|
||||
} else {
|
||||
head = make([]byte, n)
|
||||
@@ -168,7 +168,7 @@ func resize(in []byte, n int) (head, tail []byte) {
|
||||
// Apply padding
|
||||
func padBuffer(buffer []byte, blockSize int) []byte {
|
||||
missing := blockSize - (len(buffer) % blockSize)
|
||||
ret, out := resize(buffer, len(buffer)+missing)
|
||||
ret, out := resize(buffer, uint64(len(buffer))+uint64(missing))
|
||||
padding := bytes.Repeat([]byte{byte(missing)}, missing)
|
||||
copy(out, padding)
|
||||
return ret
|
||||
|
6
vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac_test.go
generated
vendored
6
vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac_test.go
generated
vendored
@@ -283,7 +283,7 @@ func TestTruncatedCiphertext(t *testing.T) {
|
||||
ct := aead.Seal(nil, nonce, data, nil)
|
||||
|
||||
// Truncated ciphertext, but with correct auth tag
|
||||
truncated, tail := resize(ct[:len(ct)-ctx.authtagBytes-2], len(ct)-2)
|
||||
truncated, tail := resize(ct[:len(ct)-ctx.authtagBytes-2], uint64(len(ct))-2)
|
||||
copy(tail, ctx.computeAuthTag(nil, nonce, truncated[:len(truncated)-ctx.authtagBytes]))
|
||||
|
||||
// Open should fail
|
||||
@@ -313,8 +313,8 @@ func TestInvalidPaddingOpen(t *testing.T) {
|
||||
ctx := aead.(*cbcAEAD)
|
||||
|
||||
// Mutated ciphertext, but with correct auth tag
|
||||
size := len(buffer)
|
||||
ciphertext, tail := resize(buffer, size+(len(key)/2))
|
||||
size := uint64(len(buffer))
|
||||
ciphertext, tail := resize(buffer, size+(uint64(len(key))/2))
|
||||
copy(tail, ctx.computeAuthTag(nil, nonce, ciphertext[:size]))
|
||||
|
||||
// Open should fail (b/c of invalid padding, even though tag matches)
|
||||
|
2
vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go
generated
vendored
2
vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go
generated
vendored
@@ -32,7 +32,7 @@ type concatKDF struct {
|
||||
|
||||
// NewConcatKDF builds a KDF reader based on the given inputs.
|
||||
func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
|
||||
buffer := make([]byte, len(algID)+len(ptyUInfo)+len(ptyVInfo)+len(supPubInfo)+len(supPrivInfo))
|
||||
buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
|
||||
n := 0
|
||||
n += copy(buffer, algID)
|
||||
n += copy(buffer[n:], ptyUInfo)
|
||||
|
11
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go
generated
vendored
11
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go
generated
vendored
@@ -23,7 +23,14 @@ import (
|
||||
)
|
||||
|
||||
// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA.
|
||||
// It is an error to call this function with a private/public key that are not on the same
|
||||
// curve. Callers must ensure that the keys are valid before calling this function. Output
|
||||
// size may be at most 1<<16 bytes (64 KiB).
|
||||
func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte {
|
||||
if size > 1<<16 {
|
||||
panic("ECDH-ES output size too large, must be less than 1<<16")
|
||||
}
|
||||
|
||||
// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
|
||||
algID := lengthPrefixed([]byte(alg))
|
||||
ptyUInfo := lengthPrefixed(apuData)
|
||||
@@ -33,6 +40,10 @@ func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, p
|
||||
supPubInfo := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8)
|
||||
|
||||
if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) {
|
||||
panic("public key not on same curve as private key")
|
||||
}
|
||||
|
||||
z, _ := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes())
|
||||
reader := NewConcatKDF(crypto.SHA256, z.Bytes(), algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{})
|
||||
|
||||
|
19
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es_test.go
generated
vendored
19
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es_test.go
generated
vendored
@@ -48,7 +48,7 @@ var bobKey = &ecdsa.PrivateKey{
|
||||
func fromBase64Int(data string) *big.Int {
|
||||
val, err := base64.URLEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
panic("Invalid test data")
|
||||
panic("Invalid test data: " + err.Error())
|
||||
}
|
||||
return new(big.Int).SetBytes(val)
|
||||
}
|
||||
@@ -67,6 +67,23 @@ func TestVectorECDHES(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidECPublicKey(t *testing.T) {
|
||||
defer func() { recover() }()
|
||||
|
||||
// Invalid key
|
||||
invalid := &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: fromBase64Int("MTEx"),
|
||||
Y: fromBase64Int("MTEx"),
|
||||
},
|
||||
D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo="),
|
||||
}
|
||||
|
||||
DeriveECDHES("A128GCM", []byte{}, []byte{}, bobKey, &invalid.PublicKey, 16)
|
||||
t.Fatal("should panic if public key was invalid")
|
||||
}
|
||||
|
||||
func BenchmarkECDHES_128(b *testing.B) {
|
||||
apuData := []byte("APU")
|
||||
apvData := []byte("APV")
|
||||
|
89
vendor/gopkg.in/square/go-jose.v2/crypter.go
generated
vendored
89
vendor/gopkg.in/square/go-jose.v2/crypter.go
generated
vendored
@@ -19,6 +19,7 @@ package jose
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
@@ -308,10 +309,16 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// Decrypt and validate the object and return the plaintext.
|
||||
// Decrypt and validate the object and return the plaintext. Note that this
|
||||
// function does not support multi-recipient, if you desire multi-recipient
|
||||
// decryption use DecryptMulti instead.
|
||||
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")
|
||||
}
|
||||
|
||||
if len(headers.Crit) > 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||
}
|
||||
@@ -339,17 +346,13 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||
authData := obj.computeAuthData()
|
||||
|
||||
var plaintext []byte
|
||||
for _, recipient := range obj.recipients {
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
recipient := obj.recipients[0]
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
}
|
||||
|
||||
if plaintext == nil {
|
||||
@@ -363,3 +366,67 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||
|
||||
return plaintext, err
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||
globalHeaders := obj.mergedHeaders(nil)
|
||||
|
||||
if len(globalHeaders.Crit) > 0 {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||
}
|
||||
|
||||
decrypter, err := newDecrypter(decryptionKey)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, err
|
||||
}
|
||||
|
||||
cipher := getContentCipher(globalHeaders.Enc)
|
||||
if cipher == nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(globalHeaders.Enc))
|
||||
}
|
||||
|
||||
generator := randomKeyGenerator{
|
||||
size: cipher.keySize(),
|
||||
}
|
||||
|
||||
parts := &aeadParts{
|
||||
iv: obj.iv,
|
||||
ciphertext: obj.ciphertext,
|
||||
tag: obj.tag,
|
||||
}
|
||||
|
||||
authData := obj.computeAuthData()
|
||||
|
||||
index := -1
|
||||
var plaintext []byte
|
||||
var headers rawHeader
|
||||
|
||||
for i, recipient := range obj.recipients {
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err == nil {
|
||||
index = i
|
||||
headers = recipientHeaders
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if plaintext == nil || err != nil {
|
||||
return -1, Header{}, nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if obj.protected.Zip != "" {
|
||||
plaintext, err = decompress(obj.protected.Zip, plaintext)
|
||||
}
|
||||
|
||||
return index, headers.sanitized(), plaintext, err
|
||||
}
|
||||
|
30
vendor/gopkg.in/square/go-jose.v2/crypter_test.go
generated
vendored
30
vendor/gopkg.in/square/go-jose.v2/crypter_test.go
generated
vendored
@@ -279,38 +279,40 @@ func TestMultiRecipientJWE(t *testing.T) {
|
||||
input := []byte("Lorem ipsum dolor sit amet")
|
||||
obj, err := enc.Encrypt(input)
|
||||
if err != nil {
|
||||
t.Error("error in encrypt: ", err)
|
||||
return
|
||||
t.Fatal("error in encrypt: ", err)
|
||||
}
|
||||
|
||||
msg := obj.FullSerialize()
|
||||
|
||||
parsed, err := ParseEncrypted(msg)
|
||||
if err != nil {
|
||||
t.Error("error in parse: ", err)
|
||||
return
|
||||
t.Fatal("error in parse: ", err)
|
||||
}
|
||||
|
||||
output, err := parsed.Decrypt(rsaTestKey)
|
||||
i, _, output, err := parsed.DecryptMulti(rsaTestKey)
|
||||
if err != nil {
|
||||
t.Error("error on decrypt with RSA: ", err)
|
||||
return
|
||||
t.Fatal("error on decrypt with RSA: ", err)
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
t.Fatal("recipient index should be 0 for RSA key")
|
||||
}
|
||||
|
||||
if bytes.Compare(input, output) != 0 {
|
||||
t.Error("Decrypted output does not match input: ", output, input)
|
||||
return
|
||||
t.Fatal("Decrypted output does not match input: ", output, input)
|
||||
}
|
||||
|
||||
output, err = parsed.Decrypt(sharedKey)
|
||||
i, _, output, err = parsed.DecryptMulti(sharedKey)
|
||||
if err != nil {
|
||||
t.Error("error on decrypt with AES: ", err)
|
||||
return
|
||||
t.Fatal("error on decrypt with AES: ", err)
|
||||
}
|
||||
|
||||
if i != 1 {
|
||||
t.Fatal("recipient index should be 1 for shared key")
|
||||
}
|
||||
|
||||
if bytes.Compare(input, output) != 0 {
|
||||
t.Error("Decrypted output does not match input", output, input)
|
||||
return
|
||||
t.Fatal("Decrypted output does not match input", output, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
7
vendor/gopkg.in/square/go-jose.v2/encoding.go
generated
vendored
7
vendor/gopkg.in/square/go-jose.v2/encoding.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"compress/flate"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/big"
|
||||
"regexp"
|
||||
@@ -31,7 +32,7 @@ var stripWhitespaceRegex = regexp.MustCompile("\\s")
|
||||
// Helper function to serialize known-good objects.
|
||||
// Precondition: value is not a nil pointer.
|
||||
func mustSerializeJSON(value interface{}) []byte {
|
||||
out, err := MarshalJSON(value)
|
||||
out, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -132,12 +133,12 @@ func newBufferFromInt(num uint64) *byteBuffer {
|
||||
}
|
||||
|
||||
func (b *byteBuffer) MarshalJSON() ([]byte, error) {
|
||||
return MarshalJSON(b.base64())
|
||||
return json.Marshal(b.base64())
|
||||
}
|
||||
|
||||
func (b *byteBuffer) UnmarshalJSON(data []byte) error {
|
||||
var encoded string
|
||||
err := UnmarshalJSON(data, &encoded)
|
||||
err := json.Unmarshal(data, &encoded)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
6
vendor/gopkg.in/square/go-jose.v2/jose-util/jose-util.t
generated
vendored
6
vendor/gopkg.in/square/go-jose.v2/jose-util/jose-util.t
generated
vendored
@@ -86,3 +86,9 @@ Sign and verify a test message (EC).
|
||||
> jose-util sign --alg ES384 --key ec.key |
|
||||
> jose-util verify --key ec.pub
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
Expand a compact message to full format.
|
||||
|
||||
$ echo "eyJhbGciOiJFUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQK.QPU35XY913Im7ZEaN2yHykfbtPqjHZvYp-lV8OcTAJZs67bJFSdTSkQhQWE9ch6tvYrj_7py6HKaWVFLll_s_Rm6bmwq3JszsHrIvFFm1NydruYHhvAnx7rjYiqwOu0W" |
|
||||
> jose-util expand --format JWS
|
||||
{"payload":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQK","protected":"eyJhbGciOiJFUzM4NCJ9","signature":"QPU35XY913Im7ZEaN2yHykfbtPqjHZvYp-lV8OcTAJZs67bJFSdTSkQhQWE9ch6tvYrj_7py6HKaWVFLll_s_Rm6bmwq3JszsHrIvFFm1NydruYHhvAnx7rjYiqwOu0W"}
|
||||
|
11
vendor/gopkg.in/square/go-jose.v2/jose-util/main.go
generated
vendored
11
vendor/gopkg.in/square/go-jose.v2/jose-util/main.go
generated
vendored
@@ -28,7 +28,7 @@ import (
|
||||
var (
|
||||
app = kingpin.New("jose-util", "A command-line utility for dealing with JOSE objects.")
|
||||
|
||||
keyFile = app.Flag("key", "Path to key file (PEM or DER-encoded)").Required().ExistingFile()
|
||||
keyFile = app.Flag("key", "Path to key file (PEM or DER-encoded)").ExistingFile()
|
||||
inFile = app.Flag("in", "Path to input file (stdin if missing)").ExistingFile()
|
||||
outFile = app.Flag("out", "Path to output file (stdout if missing)").ExistingFile()
|
||||
|
||||
@@ -54,8 +54,12 @@ func main() {
|
||||
|
||||
command := kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
|
||||
keyBytes, err := ioutil.ReadFile(*keyFile)
|
||||
exitOnError(err, "unable to read key file")
|
||||
var keyBytes []byte
|
||||
var err error
|
||||
if command != "expand" {
|
||||
keyBytes, err = ioutil.ReadFile(*keyFile)
|
||||
exitOnError(err, "unable to read key file")
|
||||
}
|
||||
|
||||
switch command {
|
||||
case "encrypt":
|
||||
@@ -144,6 +148,7 @@ func main() {
|
||||
|
||||
exitOnError(err, "unable to expand message")
|
||||
writeOutput(*outFile, []byte(serialized))
|
||||
writeOutput(*outFile, []byte("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
|
2
vendor/gopkg.in/square/go-jose.v2/json/decode_test.go
generated
vendored
2
vendor/gopkg.in/square/go-jose.v2/json/decode_test.go
generated
vendored
@@ -1258,7 +1258,7 @@ func TestSliceOfCustomByte(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(a, b) {
|
||||
t.Fatal("expected %v == %v", a, b)
|
||||
t.Fatalf("expected %v == %v", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
|
31
vendor/gopkg.in/square/go-jose.v2/json_fork.go
generated
vendored
31
vendor/gopkg.in/square/go-jose.v2/json_fork.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
// +build !std_json
|
||||
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
func MarshalJSON(v interface{}) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
func UnmarshalJSON(data []byte, v interface{}) error {
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
105
vendor/gopkg.in/square/go-jose.v2/json_fork_test.go
generated
vendored
105
vendor/gopkg.in/square/go-jose.v2/json_fork_test.go
generated
vendored
@@ -1,105 +0,0 @@
|
||||
// +build !std_json
|
||||
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type CaseSensitive struct {
|
||||
A int `json:"Test"`
|
||||
B int `json:"test"`
|
||||
C int `json:"TEST"`
|
||||
}
|
||||
|
||||
type UnicodeTest struct {
|
||||
Sig string `json:"sig"`
|
||||
}
|
||||
|
||||
func TestUnicodeComparison(t *testing.T) {
|
||||
// Some tests from RFC 7515, Section 10.13
|
||||
raw := []byte(`{"\u0073ig":"foo"}`)
|
||||
var ut UnicodeTest
|
||||
err := UnmarshalJSON(raw, &ut)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ut.Sig != "foo" {
|
||||
t.Error("strings 'sig' and '\\u0073ig' should be equal")
|
||||
}
|
||||
|
||||
raw = []byte(`{"si\u0047":"bar"}`)
|
||||
var ut2 UnicodeTest
|
||||
err = UnmarshalJSON(raw, &ut2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ut2.Sig != "" {
|
||||
t.Error("strings 'sig' and 'si\\u0047' should not be equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaseSensitiveJSON(t *testing.T) {
|
||||
raw := []byte(`{"test":42}`)
|
||||
var cs CaseSensitive
|
||||
err := UnmarshalJSON(raw, &cs)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if cs.A != 0 || cs.B != 42 || cs.C != 0 {
|
||||
t.Errorf("parsing JSON should be case-sensitive (got %v)", cs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectDuplicateKeysObject(t *testing.T) {
|
||||
raw := []byte(`{"test":42,"test":43}`)
|
||||
var cs CaseSensitive
|
||||
err := UnmarshalJSON(raw, &cs)
|
||||
if err == nil {
|
||||
t.Error("should reject JSON with duplicate keys, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectDuplicateKeysInterface(t *testing.T) {
|
||||
raw := []byte(`{"test":42,"test":43}`)
|
||||
var m interface{}
|
||||
err := UnmarshalJSON(raw, &m)
|
||||
if err == nil {
|
||||
t.Error("should reject JSON with duplicate keys, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaseSensitiveJWE(t *testing.T) {
|
||||
invalidJWE := `{"protected":"eyJlbmMiOiJYWVoiLCJBTEciOiJYWVoifQo","encrypted_key":"QUJD","iv":"QUJD","ciphertext":"QUJD","tag":"QUJD"}`
|
||||
_, err := ParseEncrypted(invalidJWE)
|
||||
if err == nil {
|
||||
t.Error("Able to parse message with case-invalid headers", invalidJWE)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaseSensitiveJWS(t *testing.T) {
|
||||
invalidJWS := `{"PAYLOAD":"CUJD","signatures":[{"protected":"e30","signature":"CUJD"}]}`
|
||||
_, err := ParseSigned(invalidJWS)
|
||||
if err == nil {
|
||||
t.Error("Able to parse message with case-invalid headers", invalidJWS)
|
||||
}
|
||||
}
|
31
vendor/gopkg.in/square/go-jose.v2/json_std.go
generated
vendored
31
vendor/gopkg.in/square/go-jose.v2/json_std.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
// +build std_json
|
||||
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func MarshalJSON(v interface{}) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
func UnmarshalJSON(data []byte, v interface{}) error {
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
124
vendor/gopkg.in/square/go-jose.v2/json_std_test.go
generated
vendored
124
vendor/gopkg.in/square/go-jose.v2/json_std_test.go
generated
vendored
@@ -1,124 +0,0 @@
|
||||
// +build std_json
|
||||
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type CaseInsensitive struct {
|
||||
A int `json:"TEST"`
|
||||
}
|
||||
|
||||
type UnicodeTest struct {
|
||||
Sig string `json:"sig"`
|
||||
}
|
||||
|
||||
func TestUnicodeComparison(t *testing.T) {
|
||||
// Some tests from RFC 7515, Section 10.13
|
||||
raw := []byte(`{"\u0073ig":"foo"}`)
|
||||
var ut UnicodeTest
|
||||
err := UnmarshalJSON(raw, &ut)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ut.Sig != "foo" {
|
||||
t.Error("strings 'sig' and '\\u0073ig' should be equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaseInsensitiveJSON(t *testing.T) {
|
||||
raw := []byte(`{"test":42}`)
|
||||
var ci CaseInsensitive
|
||||
err := UnmarshalJSON(raw, &ci)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ci.A != 42 {
|
||||
t.Errorf("parsing JSON should be case-insensitive (got %v)", ci)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaseInsensitiveJWE(t *testing.T) {
|
||||
invalidJWE := `{"protected":"eyJlbmMiOiJYWVoiLCJBTEciOiJYWVoifQo","encrypted_key":"QUJD","iv":"QUJD","ciphertext":"QUJD","tag":"QUJD"}`
|
||||
_, err := ParseEncrypted(invalidJWE)
|
||||
if err != nil {
|
||||
t.Error("Unable to parse message with case-invalid headers", invalidJWE)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCaseInsensitiveJWS(t *testing.T) {
|
||||
invalidJWS := `{"PAYLOAD":"CUJD","signatures":[{"protected":"e30","signature":"CUJD"}]}`
|
||||
_, err := ParseSigned(invalidJWS)
|
||||
if err != nil {
|
||||
t.Error("Unable to parse message with case-invalid headers", invalidJWS)
|
||||
}
|
||||
}
|
||||
|
||||
var JWKSetDuplicates = stripWhitespace(`{
|
||||
"keys": [{
|
||||
"kty": "RSA",
|
||||
"kid": "exclude-me",
|
||||
"use": "sig",
|
||||
"n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT
|
||||
-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqV
|
||||
wGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-
|
||||
oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde
|
||||
3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuC
|
||||
LqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5g
|
||||
HdrNP5zw",
|
||||
"e": "AQAB"
|
||||
}],
|
||||
"keys": [{
|
||||
"kty": "RSA",
|
||||
"kid": "include-me",
|
||||
"use": "sig",
|
||||
"n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT
|
||||
-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqV
|
||||
wGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-
|
||||
oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde
|
||||
3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuC
|
||||
LqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5g
|
||||
HdrNP5zw",
|
||||
"e": "AQAB"
|
||||
}],
|
||||
"custom": "exclude-me",
|
||||
"custom": "include-me"
|
||||
}`)
|
||||
|
||||
func TestDuplicateJWKSetMembersIgnored(t *testing.T) {
|
||||
type CustomSet struct {
|
||||
JSONWebKeySet
|
||||
CustomMember string `json:"custom"`
|
||||
}
|
||||
data := []byte(JWKSetDuplicates)
|
||||
var set CustomSet
|
||||
UnmarshalJSON(data, &set)
|
||||
if len(set.Keys) != 1 {
|
||||
t.Error("expected only one key in set")
|
||||
}
|
||||
if set.Keys[0].KeyID != "include-me" {
|
||||
t.Errorf("expected key with kid: \"include-me\", got: %s", set.Keys[0].KeyID)
|
||||
}
|
||||
if set.CustomMember != "include-me" {
|
||||
t.Errorf("expected custom member value: \"include-me\", got: %s", set.CustomMember)
|
||||
}
|
||||
}
|
5
vendor/gopkg.in/square/go-jose.v2/jwe.go
generated
vendored
5
vendor/gopkg.in/square/go-jose.v2/jwe.go
generated
vendored
@@ -18,6 +18,7 @@ package jose
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
@@ -112,7 +113,7 @@ func ParseEncrypted(input string) (*JSONWebEncryption, error) {
|
||||
// parseEncryptedFull parses a message in compact format.
|
||||
func parseEncryptedFull(input string) (*JSONWebEncryption, error) {
|
||||
var parsed rawJSONWebEncryption
|
||||
err := UnmarshalJSON([]byte(input), &parsed)
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -134,7 +135,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
}
|
||||
|
||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||
err := UnmarshalJSON(parsed.Protected.bytes(), &obj.protected)
|
||||
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())
|
||||
}
|
||||
|
73
vendor/gopkg.in/square/go-jose.v2/jwk.go
generated
vendored
73
vendor/gopkg.in/square/go-jose.v2/jwk.go
generated
vendored
@@ -21,10 +21,15 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
|
||||
@@ -49,14 +54,17 @@ type rawJSONWebKey struct {
|
||||
Dp *byteBuffer `json:"dp,omitempty"`
|
||||
Dq *byteBuffer `json:"dq,omitempty"`
|
||||
Qi *byteBuffer `json:"qi,omitempty"`
|
||||
// Certificates
|
||||
X5c []string `json:"x5c,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebKey represents a public or private key in JWK format.
|
||||
type JSONWebKey struct {
|
||||
Key interface{}
|
||||
KeyID string
|
||||
Algorithm string
|
||||
Use string
|
||||
Key interface{}
|
||||
Certificates []*x509.Certificate
|
||||
KeyID string
|
||||
Algorithm string
|
||||
Use string
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the given key to its JSON representation.
|
||||
@@ -87,13 +95,17 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
raw.Alg = k.Algorithm
|
||||
raw.Use = k.Use
|
||||
|
||||
return MarshalJSON(raw)
|
||||
for _, cert := range k.Certificates {
|
||||
raw.X5c = append(raw.X5c, base64.StdEncoding.EncodeToString(cert.Raw))
|
||||
}
|
||||
|
||||
return json.Marshal(raw)
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a key from its JSON representation.
|
||||
func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
var raw rawJSONWebKey
|
||||
err = UnmarshalJSON(data, &raw)
|
||||
err = json.Unmarshal(data, &raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -121,6 +133,19 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
if err == nil {
|
||||
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use}
|
||||
}
|
||||
|
||||
k.Certificates = make([]*x509.Certificate, len(raw.X5c))
|
||||
for i, cert := range raw.X5c {
|
||||
raw, err := base64.StdEncoding.DecodeString(cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k.Certificates[i], err = x509.ParseCertificate(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,7 +217,17 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
// Valid checks that the key contains the expected parameters
|
||||
// IsPublic returns true if the JWK represents a public key (not symmetric, not private).
|
||||
func (k *JSONWebKey) IsPublic() bool {
|
||||
switch k.Key.(type) {
|
||||
case *ecdsa.PublicKey, *rsa.PublicKey:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Valid checks that the key contains the expected parameters.
|
||||
func (k *JSONWebKey) Valid() bool {
|
||||
if k.Key == nil {
|
||||
return false
|
||||
@@ -253,13 +288,20 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
|
||||
}
|
||||
|
||||
if key.X == nil || key.Y == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC key, missing x/y values")
|
||||
return nil, errors.New("square/go-jose: invalid EC key, missing x/y values")
|
||||
}
|
||||
|
||||
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 &ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: key.X.bigInt(),
|
||||
Y: key.Y.bigInt(),
|
||||
X: x,
|
||||
Y: y,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -368,11 +410,18 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key, missing x/y/d values")
|
||||
}
|
||||
|
||||
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 &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: key.X.bigInt(),
|
||||
Y: key.Y.bigInt(),
|
||||
X: x,
|
||||
Y: y,
|
||||
},
|
||||
D: key.D.bigInt(),
|
||||
}, nil
|
||||
|
124
vendor/gopkg.in/square/go-jose.v2/jwk_test.go
generated
vendored
124
vendor/gopkg.in/square/go-jose.v2/jwk_test.go
generated
vendored
@@ -22,12 +22,57 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
// Test chain of two X.509 certificates
|
||||
var testCertificates, _ = x509.ParseCertificates(fromBase64Bytes(`
|
||||
MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJ
|
||||
BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4G
|
||||
A1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYx
|
||||
MDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNV
|
||||
BAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUw
|
||||
EwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKd
|
||||
sR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafE
|
||||
gJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieec
|
||||
w2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a9
|
||||
4rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+j
|
||||
HDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGj
|
||||
TzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAj
|
||||
hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcN
|
||||
AQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05
|
||||
kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7
|
||||
LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloS
|
||||
aa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx
|
||||
8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObi
|
||||
qdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIUwggNT
|
||||
MIICO6ADAgECAgkAqD4tCWKt9/AwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UE
|
||||
BhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQL
|
||||
EwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLXJvb3QwHhcNMTYwNjEwMjIx
|
||||
NDExWhcNMjMwNDE1MjIxNDExWjBVMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
|
||||
Q0ExEDAOBgNVBAoTB2NlcnRpZ28xEDAOBgNVBAsTB2V4YW1wbGUxFTATBgNV
|
||||
BAMTDGV4YW1wbGUtcm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||
ggEBAMo4ShKI2MxDz/NQVxBbz0tbD5R5NcobA0NKkaPKLyMEpnWVY9ucyauM
|
||||
joNn1F568cfOoF0pm3700U8UTPt2MMxEHIi4mFG/OF8UF+Voh1J42Tb42lRo
|
||||
W5RRR3ogh4+7QB1G94nxkYddHAJ4QMhUJlLigFg8c6Ff/MxYODy9I7ilLFOM
|
||||
Zzsjx8fFpRKRXNQFt471P/V4WTSba7GzdTOJRyTZf/xipF36n8RoEQPvyde8
|
||||
pEAsCC4oDOrEiCTdxw8rRJVAU0Wr55XX+qjxyi55C6oykIC/BWR+lUqGd7IL
|
||||
Y2Uyt/OVxllt8b+KuVKNCfn4TFlfgizLWkJRs6JV9KuwJ20CAwEAAaMmMCQw
|
||||
DgYDVR0PAQH/BAQDAgIEMBIGA1UdEwEB/wQIMAYBAf8CAQAwDQYJKoZIhvcN
|
||||
AQELBQADggEBAIsQlTrm9NT6gts0cs4JHp8AutuMrvGyLpIUOlJcEybvgxaz
|
||||
LebIMGZek5w3yEJiCyCK9RdNDP3Kdc/+nM6PhvzfPOVo58+0tMCYyEpZVXhD
|
||||
zmasNDP4fMbiUpczvx5OwPw/KuhwD+1ITuZUQnQlqXgTYoj9n39+qlgUsHos
|
||||
WXHmfzd6Fcz96ADSXg54IL2cEoJ41Q3ewhA7zmWWPLMAl21aex2haiAmzqqN
|
||||
xXyfZTnGNnE3lkV1yVguOrqDZyMRdcxDFvxvtmEeMtYV2Mc/zlS9ccrcOkrc
|
||||
mZSDxthLu3UMl98NA2NrCGWwzJwpk36vQ0PRSbibsCMarFspP8zbIoU=`))
|
||||
|
||||
func TestCurveSize(t *testing.T) {
|
||||
size256 := curveSize(elliptic.P256())
|
||||
size384 := curveSize(elliptic.P384())
|
||||
@@ -155,6 +200,38 @@ func TestRoundtripEcPrivate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundtripX5C(t *testing.T) {
|
||||
jwk := JSONWebKey{
|
||||
Key: rsaTestKey,
|
||||
KeyID: "bar",
|
||||
Algorithm: "foo",
|
||||
Certificates: testCertificates,
|
||||
}
|
||||
|
||||
jsonbar, err := jwk.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Error("problem marshaling", err)
|
||||
}
|
||||
|
||||
var jwk2 JSONWebKey
|
||||
err = jwk2.UnmarshalJSON(jsonbar)
|
||||
if err != nil {
|
||||
t.Error("problem unmarshalling", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(testCertificates, jwk2.Certificates) {
|
||||
t.Error("Certificates not equal", jwk.Certificates, jwk2.Certificates)
|
||||
}
|
||||
|
||||
jsonbar2, err := jwk2.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Error("problem marshaling", err)
|
||||
}
|
||||
if !bytes.Equal(jsonbar, jsonbar2) {
|
||||
t.Error("roundtrip should not lose information")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshal(t *testing.T) {
|
||||
kid := "DEADBEEF"
|
||||
|
||||
@@ -210,7 +287,7 @@ func TestMarshalNonPointer(t *testing.T) {
|
||||
"n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw"
|
||||
}`)
|
||||
var parsedKey JSONWebKey
|
||||
err := UnmarshalJSON(keyJSON, &parsedKey)
|
||||
err := json.Unmarshal(keyJSON, &parsedKey)
|
||||
if err != nil {
|
||||
t.Errorf("Error unmarshalling key: %v", err)
|
||||
return
|
||||
@@ -218,7 +295,7 @@ func TestMarshalNonPointer(t *testing.T) {
|
||||
ek := EmbedsKey{
|
||||
Key: parsedKey,
|
||||
}
|
||||
out, err := MarshalJSON(ek)
|
||||
out, err := json.Marshal(ek)
|
||||
if err != nil {
|
||||
t.Errorf("Error marshalling JSON: %v", err)
|
||||
return
|
||||
@@ -382,6 +459,38 @@ var cookbookJWKs = []string{
|
||||
"qi":"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq
|
||||
abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o
|
||||
Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"}`),
|
||||
|
||||
// X.509 Certificate Chain
|
||||
stripWhitespace(`{"kty":"RSA",
|
||||
"use":"sig",
|
||||
"kid":"1b94c",
|
||||
"n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08
|
||||
PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q
|
||||
u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a
|
||||
YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH
|
||||
MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv
|
||||
VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ",
|
||||
"e":"AQAB",
|
||||
"x5c":
|
||||
["MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB
|
||||
gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD
|
||||
VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1
|
||||
wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg
|
||||
NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV
|
||||
QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w
|
||||
YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH
|
||||
YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66
|
||||
s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6
|
||||
SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn
|
||||
fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq
|
||||
PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk
|
||||
aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA
|
||||
QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL
|
||||
+9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1
|
||||
zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL
|
||||
2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo
|
||||
4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq
|
||||
gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA=="]}`),
|
||||
}
|
||||
|
||||
// SHA-256 thumbprints of the above keys, hex-encoded
|
||||
@@ -390,6 +499,7 @@ var cookbookJWKThumbprints = []string{
|
||||
"747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793",
|
||||
"f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932",
|
||||
"0fc478f8579325fcee0d4cbc6d9d1ce21730a6e97e435d6008fb379b0ebe47d4",
|
||||
"0ddb05bfedbec2070fa037324ba397396561d3425d6d69245570c261dc49dee3",
|
||||
}
|
||||
|
||||
func TestWebKeyVectorsValid(t *testing.T) {
|
||||
@@ -429,16 +539,16 @@ func TestMarshalUnmarshalJWKSet(t *testing.T) {
|
||||
set.Keys = append(set.Keys, jwk1)
|
||||
set.Keys = append(set.Keys, jwk2)
|
||||
|
||||
jsonbar, err := MarshalJSON(&set)
|
||||
jsonbar, err := json.Marshal(&set)
|
||||
if err != nil {
|
||||
t.Error("problem marshalling set", err)
|
||||
}
|
||||
var set2 JSONWebKeySet
|
||||
err = UnmarshalJSON(jsonbar, &set2)
|
||||
err = json.Unmarshal(jsonbar, &set2)
|
||||
if err != nil {
|
||||
t.Error("problem unmarshalling set", err)
|
||||
}
|
||||
jsonbar2, err := MarshalJSON(&set2)
|
||||
jsonbar2, err := json.Marshal(&set2)
|
||||
if err != nil {
|
||||
t.Error("problem marshalling set", err)
|
||||
}
|
||||
@@ -467,7 +577,7 @@ func TestJWKSymmetricKey(t *testing.T) {
|
||||
sample2 := `{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow","kid":"HMAC key used in JWS spec Appendix A.1 example"}`
|
||||
|
||||
var jwk1 JSONWebKey
|
||||
UnmarshalJSON([]byte(sample1), &jwk1)
|
||||
json.Unmarshal([]byte(sample1), &jwk1)
|
||||
|
||||
if jwk1.Algorithm != "A128KW" {
|
||||
t.Errorf("expected Algorithm to be A128KW, but was '%s'", jwk1.Algorithm)
|
||||
@@ -478,7 +588,7 @@ func TestJWKSymmetricKey(t *testing.T) {
|
||||
}
|
||||
|
||||
var jwk2 JSONWebKey
|
||||
UnmarshalJSON([]byte(sample2), &jwk2)
|
||||
json.Unmarshal([]byte(sample2), &jwk2)
|
||||
|
||||
if jwk2.KeyID != "HMAC key used in JWS spec Appendix A.1 example" {
|
||||
t.Errorf("expected KeyID to be 'HMAC key used in JWS spec Appendix A.1 example', but was '%s'", jwk2.KeyID)
|
||||
|
32
vendor/gopkg.in/square/go-jose.v2/jws.go
generated
vendored
32
vendor/gopkg.in/square/go-jose.v2/jws.go
generated
vendored
@@ -18,8 +18,11 @@ package jose
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
|
||||
@@ -40,7 +43,10 @@ type rawSignatureInfo struct {
|
||||
|
||||
// JSONWebSignature represents a signed JWS object after parsing.
|
||||
type JSONWebSignature struct {
|
||||
payload []byte
|
||||
payload []byte
|
||||
// Signatures attached to this object (may be more than one for multi-sig).
|
||||
// Be careful about accessing these directly, prefer to use Verify() or
|
||||
// VerifyMulti() to ensure that the data you're getting is verified.
|
||||
Signatures []Signature
|
||||
}
|
||||
|
||||
@@ -57,7 +63,7 @@ type Signature struct {
|
||||
original *rawSignatureInfo
|
||||
}
|
||||
|
||||
// ParseSigned parses an encrypted message in compact or full serialization format.
|
||||
// ParseSigned parses a signed message in compact or full serialization format.
|
||||
func ParseSigned(input string) (*JSONWebSignature, error) {
|
||||
input = stripWhitespace(input)
|
||||
if strings.HasPrefix(input, "{") {
|
||||
@@ -95,7 +101,7 @@ func (obj JSONWebSignature) computeAuthData(signature *Signature) []byte {
|
||||
// parseSignedFull parses a message in full format.
|
||||
func parseSignedFull(input string) (*JSONWebSignature, error) {
|
||||
var parsed rawJSONWebSignature
|
||||
err := UnmarshalJSON([]byte(input), &parsed)
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -119,12 +125,13 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
signature := Signature{}
|
||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||
signature.protected = &rawHeader{}
|
||||
err := UnmarshalJSON(parsed.Protected.bytes(), signature.protected)
|
||||
err := json.Unmarshal(parsed.Protected.bytes(), signature.protected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check that there is not a nonce in the unprotected header
|
||||
if parsed.Header != nil && parsed.Header.Nonce != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
@@ -147,13 +154,20 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
}
|
||||
|
||||
signature.Header = signature.mergedHeaders().sanitized()
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
obj.Signatures = append(obj.Signatures, signature)
|
||||
}
|
||||
|
||||
for i, sig := range parsed.Signatures {
|
||||
if sig.Protected != nil && len(sig.Protected.bytes()) > 0 {
|
||||
obj.Signatures[i].protected = &rawHeader{}
|
||||
err := UnmarshalJSON(sig.Protected.bytes(), obj.Signatures[i].protected)
|
||||
err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -164,14 +178,20 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
|
||||
obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized()
|
||||
obj.Signatures[i].Signature = sig.Signature.bytes()
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
// Copy value of sig
|
||||
original := sig
|
||||
|
||||
obj.Signatures[i].header = sig.Header
|
||||
obj.Signatures[i].original = &original
|
||||
obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized()
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
|
10
vendor/gopkg.in/square/go-jose.v2/jws_test.go
generated
vendored
10
vendor/gopkg.in/square/go-jose.v2/jws_test.go
generated
vendored
@@ -22,6 +22,16 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmbeddedHMAC(t *testing.T) {
|
||||
// protected: {"alg":"HS256", "jwk":{"kty":"oct", "k":"MTEx"}}, aka HMAC key.
|
||||
msg := `{"payload":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ","protected":"eyJhbGciOiJIUzI1NiIsICJqd2siOnsia3R5Ijoib2N0IiwgImsiOiJNVEV4In19","signature":"lvo41ZZsuHwQvSh0uJtEXRR3vmuBJ7in6qMoD7p9jyo"}`
|
||||
|
||||
_, err := ParseSigned(msg)
|
||||
if err == nil {
|
||||
t.Error("should not allow parsing JWS with embedded JWK with HMAC key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompactParseJWS(t *testing.T) {
|
||||
// Should parse
|
||||
msg := "eyJhbGciOiJYWVoifQ.cGF5bG9hZA.c2lnbmF0dXJl"
|
||||
|
244
vendor/gopkg.in/square/go-jose.v2/jwt/builder.go
generated
vendored
244
vendor/gopkg.in/square/go-jose.v2/jwt/builder.go
generated
vendored
@@ -17,111 +17,211 @@
|
||||
|
||||
package jwt
|
||||
|
||||
import "gopkg.in/square/go-jose.v2"
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and
|
||||
// errors are accumulated until the final call to CompactSerialize/FullSerialize.
|
||||
type Builder struct {
|
||||
transform func([]byte) (serializer, payload, error)
|
||||
payload payload
|
||||
serializer serializer
|
||||
err error
|
||||
}
|
||||
|
||||
type payload func(interface{}) ([]byte, error)
|
||||
|
||||
type serializer interface {
|
||||
FullSerialize() string
|
||||
type Builder interface {
|
||||
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
|
||||
// into single JSON object.
|
||||
Claims(i interface{}) Builder
|
||||
// Token builds a JSONWebToken from provided data.
|
||||
Token() (*JSONWebToken, error)
|
||||
// FullSerialize serializes a token using the full serialization format.
|
||||
FullSerialize() (string, error)
|
||||
// CompactSerialize serializes a token using the compact serialization format.
|
||||
CompactSerialize() (string, error)
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
payload map[string]interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
type signedBuilder struct {
|
||||
builder
|
||||
sig jose.Signer
|
||||
}
|
||||
|
||||
type encryptedBuilder struct {
|
||||
builder
|
||||
enc jose.Encrypter
|
||||
}
|
||||
|
||||
// Signed creates builder for signed tokens.
|
||||
func Signed(sig jose.Signer) *Builder {
|
||||
return &Builder{
|
||||
transform: func(b []byte) (serializer, payload, error) {
|
||||
s, err := sig.Sign(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return s, s.Verify, nil
|
||||
},
|
||||
func Signed(sig jose.Signer) Builder {
|
||||
return &signedBuilder{
|
||||
sig: sig,
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypted creates builder for encrypted tokens.
|
||||
func Encrypted(enc jose.Encrypter) *Builder {
|
||||
return &Builder{
|
||||
transform: func(b []byte) (serializer, payload, error) {
|
||||
e, err := enc.Encrypt(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return e, e.Decrypt, nil
|
||||
},
|
||||
func Encrypted(enc jose.Encrypter) Builder {
|
||||
return &encryptedBuilder{
|
||||
enc: enc,
|
||||
}
|
||||
}
|
||||
|
||||
// Claims encodes claims into the builder.
|
||||
func (b *Builder) Claims(c interface{}) *Builder {
|
||||
if b.transform == nil {
|
||||
panic("Signer/Encrypter not set")
|
||||
func (b builder) claims(i interface{}) builder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
if b.payload != nil {
|
||||
panic("Claims already set")
|
||||
}
|
||||
|
||||
raw, err := marshalClaims(c)
|
||||
if err != nil {
|
||||
return &Builder{
|
||||
err: err,
|
||||
m, ok := i.(map[string]interface{})
|
||||
switch {
|
||||
case ok:
|
||||
return b.merge(m)
|
||||
case reflect.Indirect(reflect.ValueOf(i)).Kind() == reflect.Struct:
|
||||
m, err := normalize(i)
|
||||
if err != nil {
|
||||
return builder{
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
return b.merge(m)
|
||||
default:
|
||||
return builder{
|
||||
err: ErrInvalidClaims,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ser, pl, err := b.transform(raw)
|
||||
return &Builder{
|
||||
transform: b.transform,
|
||||
serializer: ser,
|
||||
payload: pl,
|
||||
err: err,
|
||||
func normalize(i interface{}) (map[string]interface{}, error) {
|
||||
m := make(map[string]interface{})
|
||||
|
||||
raw, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(raw, &m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (b *builder) merge(m map[string]interface{}) builder {
|
||||
p := make(map[string]interface{})
|
||||
for k, v := range b.payload {
|
||||
p[k] = v
|
||||
}
|
||||
for k, v := range m {
|
||||
p[k] = v
|
||||
}
|
||||
|
||||
return builder{
|
||||
payload: p,
|
||||
}
|
||||
}
|
||||
|
||||
// Token builds a JSONWebToken from provided data.
|
||||
func (b *Builder) Token() (*JSONWebToken, error) {
|
||||
func (b *builder) token(p func(interface{}) ([]byte, error), h []jose.Header) (*JSONWebToken, error) {
|
||||
return &JSONWebToken{
|
||||
payload: p,
|
||||
Headers: h,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *signedBuilder) Claims(i interface{}) Builder {
|
||||
return &signedBuilder{
|
||||
builder: b.builder.claims(i),
|
||||
sig: b.sig,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *signedBuilder) Token() (*JSONWebToken, error) {
|
||||
sig, err := b.sign()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h := make([]jose.Header, len(sig.Signatures))
|
||||
for i, v := range sig.Signatures {
|
||||
h[i] = v.Header
|
||||
}
|
||||
|
||||
return b.builder.token(sig.Verify, h)
|
||||
}
|
||||
|
||||
func (b *signedBuilder) CompactSerialize() (string, error) {
|
||||
sig, err := b.sign()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return sig.CompactSerialize()
|
||||
}
|
||||
|
||||
func (b *signedBuilder) FullSerialize() (string, error) {
|
||||
sig, err := b.sign()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return sig.FullSerialize(), nil
|
||||
}
|
||||
|
||||
func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) {
|
||||
if b.err != nil {
|
||||
return nil, b.err
|
||||
}
|
||||
|
||||
if b.payload == nil {
|
||||
return nil, ErrInvalidClaims
|
||||
p, err := json.Marshal(b.payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &JSONWebToken{b.payload}, nil
|
||||
return b.sig.Sign(p)
|
||||
}
|
||||
|
||||
// FullSerialize serializes a token using the full serialization format.
|
||||
func (b *Builder) FullSerialize() (string, error) {
|
||||
func (b *encryptedBuilder) Claims(i interface{}) Builder {
|
||||
return &encryptedBuilder{
|
||||
builder: b.builder.claims(i),
|
||||
enc: b.enc,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *encryptedBuilder) CompactSerialize() (string, error) {
|
||||
enc, err := b.encrypt()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return enc.CompactSerialize()
|
||||
}
|
||||
|
||||
func (b *encryptedBuilder) FullSerialize() (string, error) {
|
||||
enc, err := b.encrypt()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return enc.FullSerialize(), nil
|
||||
}
|
||||
|
||||
func (b *encryptedBuilder) Token() (*JSONWebToken, error) {
|
||||
enc, err := b.encrypt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.builder.token(enc.Decrypt, []jose.Header{enc.Header})
|
||||
}
|
||||
|
||||
func (b *encryptedBuilder) encrypt() (*jose.JSONWebEncryption, error) {
|
||||
if b.err != nil {
|
||||
return "", b.err
|
||||
return nil, b.err
|
||||
}
|
||||
|
||||
if b.serializer == nil {
|
||||
return "", ErrInvalidClaims
|
||||
p, err := json.Marshal(b.payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.serializer.FullSerialize(), nil
|
||||
}
|
||||
|
||||
// CompactSerialize serializes a token using the compact serialization format.
|
||||
func (b *Builder) CompactSerialize() (string, error) {
|
||||
if b.err != nil {
|
||||
return "", b.err
|
||||
}
|
||||
|
||||
if b.serializer == nil {
|
||||
return "", ErrInvalidClaims
|
||||
}
|
||||
|
||||
return b.serializer.CompactSerialize()
|
||||
return b.enc.Encrypt(p)
|
||||
}
|
||||
|
415
vendor/gopkg.in/square/go-jose.v2/jwt/builder_test.go
generated
vendored
Normal file
415
vendor/gopkg.in/square/go-jose.v2/jwt/builder_test.go
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
/*-
|
||||
* Copyright 2016 Zbigniew Mandziejewicz
|
||||
* Copyright 2016 Square, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
type testClaims struct {
|
||||
Subject string `json:"sub"`
|
||||
}
|
||||
|
||||
type invalidMarshalClaims struct {
|
||||
}
|
||||
|
||||
var errInvalidMarshalClaims = errors.New("Failed marshaling invalid claims.")
|
||||
|
||||
func (c invalidMarshalClaims) MarshalJSON() ([]byte, error) {
|
||||
return nil, errInvalidMarshalClaims
|
||||
}
|
||||
|
||||
var sampleClaims = Claims{
|
||||
Subject: "42",
|
||||
IssuedAt: NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)),
|
||||
Issuer: "issuer",
|
||||
Audience: Audience{"a1", "a2"},
|
||||
}
|
||||
|
||||
func TestBuilderCustomClaimsNonPointer(t *testing.T) {
|
||||
jwt, err := Signed(rsaSigner).Claims(testClaims{"foo"}).CompactSerialize()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
|
||||
parsed, err := ParseSigned(jwt)
|
||||
require.NoError(t, err, "Error parsing JWT.")
|
||||
|
||||
out := &testClaims{}
|
||||
if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, out), "Error unmarshaling claims.") {
|
||||
assert.Equal(t, "foo", out.Subject)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderCustomClaimsPointer(t *testing.T) {
|
||||
jwt, err := Signed(rsaSigner).Claims(&testClaims{"foo"}).CompactSerialize()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
|
||||
parsed, err := ParseSigned(jwt)
|
||||
require.NoError(t, err, "Error parsing JWT.")
|
||||
|
||||
out := &testClaims{}
|
||||
if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, out), "Error unmarshaling claims.") {
|
||||
assert.Equal(t, "foo", out.Subject)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderMergeClaims(t *testing.T) {
|
||||
jwt, err := Signed(rsaSigner).
|
||||
Claims(&Claims{
|
||||
Subject: "42",
|
||||
}).
|
||||
Claims(map[string]interface{}{
|
||||
"Scopes": []string{"read:users"},
|
||||
}).
|
||||
CompactSerialize()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
|
||||
parsed, err := ParseSigned(jwt)
|
||||
require.NoError(t, err, "Error parsing JWT.")
|
||||
|
||||
out := make(map[string]interface{})
|
||||
if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, &out), "Error unmarshaling claims.") {
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"sub": "42",
|
||||
"Scopes": []interface{}{"read:users"},
|
||||
}, out)
|
||||
}
|
||||
|
||||
_, err = Signed(rsaSigner).Claims("invalid-claims").Claims(&testClaims{"foo"}).CompactSerialize()
|
||||
assert.Equal(t, err, ErrInvalidClaims)
|
||||
|
||||
_, err = Signed(rsaSigner).Claims(&invalidMarshalClaims{}).CompactSerialize()
|
||||
assert.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.")
|
||||
}
|
||||
|
||||
func TestSignedFullSerializeAndToken(t *testing.T) {
|
||||
b := Signed(rsaSigner).Claims(&testClaims{"foo"})
|
||||
|
||||
jwt, err := b.FullSerialize()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
parsed, err := ParseSigned(jwt)
|
||||
require.NoError(t, err, "Error parsing JWT.")
|
||||
out := &testClaims{}
|
||||
if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, &out), "Error unmarshaling claims.") {
|
||||
assert.Equal(t, &testClaims{
|
||||
Subject: "foo",
|
||||
}, out)
|
||||
}
|
||||
|
||||
jwt2, err := b.Token()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
out2 := &testClaims{}
|
||||
if assert.NoError(t, jwt2.Claims(&testPrivRSAKey1.PublicKey, &out2), "Error unmarshaling claims.") {
|
||||
assert.Equal(t, &testClaims{
|
||||
Subject: "foo",
|
||||
}, out2)
|
||||
}
|
||||
|
||||
b2 := Signed(rsaSigner).Claims(&invalidMarshalClaims{})
|
||||
_, err = b2.FullSerialize()
|
||||
require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.")
|
||||
_, err = b2.Token()
|
||||
require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.")
|
||||
}
|
||||
|
||||
func TestEncryptedFullSerializeAndToken(t *testing.T) {
|
||||
recipient := jose.Recipient{
|
||||
Algorithm: jose.RSA1_5,
|
||||
Key: testPrivRSAKey1.Public(),
|
||||
}
|
||||
encrypter, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, nil)
|
||||
require.NoError(t, err, "Error creating encrypter.")
|
||||
|
||||
b := Encrypted(encrypter).Claims(&testClaims{"foo"})
|
||||
|
||||
jwt, err := b.FullSerialize()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
parsed, err := ParseEncrypted(jwt)
|
||||
require.NoError(t, err, "Error parsing JWT.")
|
||||
out := &testClaims{}
|
||||
if assert.NoError(t, parsed.Claims(testPrivRSAKey1, &out)) {
|
||||
assert.Equal(t, &testClaims{
|
||||
Subject: "foo",
|
||||
}, out)
|
||||
}
|
||||
|
||||
jwt2, err := b.Token()
|
||||
require.NoError(t, err, "Error creating JWT.")
|
||||
out2 := &testClaims{}
|
||||
if assert.NoError(t, jwt2.Claims(testPrivRSAKey1, &out2)) {
|
||||
assert.Equal(t, &testClaims{
|
||||
Subject: "foo",
|
||||
}, out2)
|
||||
}
|
||||
|
||||
b2 := Encrypted(encrypter).Claims(&invalidMarshalClaims{})
|
||||
|
||||
_, err = b2.FullSerialize()
|
||||
require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.")
|
||||
_, err = b2.Token()
|
||||
require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.")
|
||||
}
|
||||
|
||||
func TestBuilderHeadersSigner(t *testing.T) {
|
||||
tests := []struct {
|
||||
Keys []*rsa.PrivateKey
|
||||
Claims interface{}
|
||||
}{
|
||||
{
|
||||
Keys: []*rsa.PrivateKey{testPrivRSAKey1},
|
||||
Claims: &Claims{Issuer: "foo"},
|
||||
},
|
||||
{
|
||||
Keys: []*rsa.PrivateKey{testPrivRSAKey1, testPrivRSAKey2},
|
||||
Claims: &Claims{Issuer: "foo"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
wantKeyIDs := make([]string, len(tc.Keys))
|
||||
signingKeys := make([]jose.SigningKey, len(tc.Keys))
|
||||
|
||||
for j, key := range tc.Keys {
|
||||
keyIDBytes := make([]byte, 20)
|
||||
if _, err := io.ReadFull(rand.Reader, keyIDBytes); err != nil {
|
||||
t.Fatalf("failed to read random bytes: %v", err)
|
||||
}
|
||||
keyID := hex.EncodeToString(keyIDBytes)
|
||||
|
||||
wantKeyIDs[j] = keyID
|
||||
signingKeys[j] = jose.SigningKey{
|
||||
Algorithm: jose.RS256,
|
||||
Key: &jose.JSONWebKey{
|
||||
KeyID: keyID,
|
||||
Algorithm: "RSA",
|
||||
Key: key,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
signer, err := jose.NewMultiSigner(signingKeys, nil)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: NewMultiSigner(): %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var token string
|
||||
if len(tc.Keys) == 1 {
|
||||
token, err = Signed(signer).Claims(tc.Claims).CompactSerialize()
|
||||
} else {
|
||||
token, err = Signed(signer).Claims(tc.Claims).FullSerialize()
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed to create token: %v", i, err)
|
||||
continue
|
||||
}
|
||||
jws, err := jose.ParseSigned(token)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: parse signed: %v", i, err)
|
||||
continue
|
||||
}
|
||||
gotKeyIDs := make([]string, len(jws.Signatures))
|
||||
for i, sig := range jws.Signatures {
|
||||
gotKeyIDs[i] = sig.Header.KeyID
|
||||
}
|
||||
sort.Strings(wantKeyIDs)
|
||||
sort.Strings(gotKeyIDs)
|
||||
if !reflect.DeepEqual(wantKeyIDs, gotKeyIDs) {
|
||||
t.Errorf("case %d: wanted=%q got=%q", i, wantKeyIDs, gotKeyIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderHeadersEncrypter(t *testing.T) {
|
||||
key := testPrivRSAKey1
|
||||
claims := &Claims{Issuer: "foo"}
|
||||
|
||||
keyIDBytes := make([]byte, 20)
|
||||
if _, err := io.ReadFull(rand.Reader, keyIDBytes); err != nil {
|
||||
t.Fatalf("failed to read random bytes: %v", err)
|
||||
}
|
||||
keyID := hex.EncodeToString(keyIDBytes)
|
||||
|
||||
wantKeyID := keyID
|
||||
recipient := jose.Recipient{
|
||||
Algorithm: jose.RSA1_5,
|
||||
Key: key.Public(),
|
||||
KeyID: keyID,
|
||||
}
|
||||
|
||||
encrypter, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, nil)
|
||||
if err != nil {
|
||||
t.Errorf("NewEncrypter(): %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
token, err := Encrypted(encrypter).Claims(claims).CompactSerialize()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create token: %v", err)
|
||||
return
|
||||
}
|
||||
jwe, err := jose.ParseEncrypted(token)
|
||||
if err != nil {
|
||||
t.Errorf("parse signed: %v", err)
|
||||
return
|
||||
}
|
||||
if gotKeyID := jwe.Header.KeyID; gotKeyID != wantKeyID {
|
||||
t.Errorf("wanted=%q got=%q", wantKeyID, gotKeyID)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMapClaims(b *testing.B) {
|
||||
m := map[string]interface{}{
|
||||
"sub": "42",
|
||||
"iat": 1451606400,
|
||||
"iss": "issuer",
|
||||
"aud": []string{"a1", "a2"},
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Signed(rsaSigner).Claims(m)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStructClaims(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Signed(rsaSigner).Claims(sampleClaims)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSignedCompactSerializeRSA(b *testing.B) {
|
||||
tb := Signed(rsaSigner).Claims(sampleClaims)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tb.CompactSerialize()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSignedCompactSerializeSHA(b *testing.B) {
|
||||
tb := Signed(hmacSigner).Claims(sampleClaims)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tb.CompactSerialize()
|
||||
}
|
||||
}
|
||||
|
||||
func mustUnmarshalRSA(data string) *rsa.PrivateKey {
|
||||
block, _ := pem.Decode([]byte(data))
|
||||
if block == nil {
|
||||
panic("failed to decode PEM data")
|
||||
}
|
||||
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic("failed to parse RSA key: " + err.Error())
|
||||
}
|
||||
if key, ok := key.(*rsa.PrivateKey); ok {
|
||||
return key
|
||||
}
|
||||
panic("key is not of type *rsa.PrivateKey")
|
||||
}
|
||||
|
||||
func mustMakeSigner(alg jose.SignatureAlgorithm, k interface{}) jose.Signer {
|
||||
sig, err := jose.NewSigner(jose.SigningKey{Algorithm: alg, Key: k}, nil)
|
||||
if err != nil {
|
||||
panic("failed to create signer:" + err.Error())
|
||||
}
|
||||
|
||||
return sig
|
||||
}
|
||||
|
||||
var (
|
||||
sharedKey = []byte("secret")
|
||||
sharedEncryptionKey = []byte("itsa16bytesecret")
|
||||
|
||||
testPrivRSAKey1 = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIHBvDHAr7jh8h
|
||||
xaqBCl11fjI9YZtdC5b3HtXTXZW3c2dIOImNUjffT8POP6p5OpzivmC1om7iOyuZ
|
||||
3nJjC9LT3zqqs3f2i5d4mImxEuqG6uWdryFfkp0uIv5VkjVO+iQWd6pDAPGP7r1Z
|
||||
foXCleyCtmyNH4JSkJneNPOk/4BxO8vcvRnCMT/Gv81IT6H+OQ6OovWOuJr8RX9t
|
||||
1wuCjC9ezZxeI9ONffhiO5FMrVh5H9LJTl3dPOVa4aEcOvgd45hBmvxAyXqf8daE
|
||||
6Kl2O7vQ4uwgnSTVXYIIjCjbepuersApIMGx/XPSgiU1K3Xtah/TBvep+S3VlwPc
|
||||
q/QH25S9AgMBAAECggEAe+y8XKYfPw4SxY1uPB+5JSwT3ON3nbWxtjSIYy9Pqp5z
|
||||
Vcx9kuFZ7JevQSk4X38m7VzM8282kC/ono+d8yy9Uayq3k/qeOqV0X9Vti1qxEbw
|
||||
ECkG1/MqGApfy4qSLOjINInDDV+mOWa2KJgsKgdCwuhKbVMYGB2ozG2qfYIlfvlY
|
||||
vLcBEpGWmswJHNmkcjTtGFIyJgPbsI6ndkkOeQbqQKAaadXtG1xUzH+vIvqaUl/l
|
||||
AkNf+p4qhPkHsoAWXf1qu9cYa2T8T+mEo79AwlgVC6awXQWNRTiyClDJC7cu6NBy
|
||||
ZHXCLFMbalzWF9qeI2OPaFX2x3IBWrbyDxcJ4TSdQQKBgQD/Fp/uQonMBh1h4Vi4
|
||||
HlxZdqSOArTitXValdLFGVJ23MngTGV/St4WH6eRp4ICfPyldsfcv6MZpNwNm1Rn
|
||||
lB5Gtpqpby1dsrOSfvVbY7U3vpLnd8+hJ/lT5zCYt5Eor46N6iWRkYWzNe4PixiF
|
||||
z1puGUvFCbZdeeACVrPLmW3JKQKBgQDI0y9WTf8ezKPbtap4UEE6yBf49ftohVGz
|
||||
p4iD6Ng1uqePwKahwoVXKOc179CjGGtW/UUBORAoKRmxdHajHq6LJgsBxpaARz21
|
||||
COPy99BUyp9ER5P8vYn63lC7Cpd/K7uyMjaz1DAzYBZIeVZHIw8O9wuGNJKjRFy9
|
||||
SZyD3V0ddQKBgFMdohrWH2QVEfnUnT3Q1rJn0BJdm2bLTWOosbZ7G72TD0xAWEnz
|
||||
sQ1wXv88n0YER6X6YADziEdQykq8s/HT91F/KkHO8e83zP8M0xFmGaQCOoelKEgQ
|
||||
aFMIX3NDTM7+9OoUwwz9Z50PE3SJFAJ1n7eEEoYvNfabQXxBl+/dHEKRAoGAPEvU
|
||||
EaiXacrtg8EWrssB2sFLGU/ZrTciIbuybFCT4gXp22pvXXAHEvVP/kzDqsRhLhwb
|
||||
BNP6OuSkNziNikpjA5pngZ/7fgZly54gusmW/m5bxWdsUl0iOXVYbeAvPlqGH2me
|
||||
LP4Pfs1hw17S/cbT9Z1NE31jbavP4HFikeD73SUCgYEArQfuudml6ei7XZ1Emjq8
|
||||
jZiD+fX6e6BD/ISatVnuyZmGj9wPFsEhY2BpLiAMQHMDIvH9nlKzsFvjkTPB86qG
|
||||
jCh3D67Os8eSBk5uRC6iW3Fc4DXvB5EFS0W9/15Sl+V5vXAcrNMpYS82OTSMG2Gt
|
||||
b9Ym/nxaqyTu0PxajXkKm5Q=
|
||||
-----END PRIVATE KEY-----`)
|
||||
|
||||
testPrivRSAKey2 = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxJ09jkXZ5Okyq
|
||||
FrEKrs+GTzZRvoLziyzDTIZLJC6BVryau4gaFjuBG+pnm4z53oDP0XVnjFsx1mBw
|
||||
R6RHeXlXbxLXsMfJpMzU9I2SRen9DokpD187CAnjLOoN9QRl1h8CA+sqR5Jw9mdl
|
||||
mdaBKC99M9QYAPK3vGNfPC4soo8LDSBiemmt5raL4WSfoYh/6qg5rHUTymY28uxV
|
||||
ew3I9Yp+3ltIw+WlRDtW5l+MM5CSUofjj2zcgcG3LEuPtvyZ+CSObxxcZZugm9zc
|
||||
JdiazNyUxtX8yAj3Xg8Hde0jt0QDXv7A+U0KMVi9lX6PJEaNj4tOhOmQhJVMzAyr
|
||||
1W/bifZVAgMBAAECggEAduKnn21GMZLTUi4KP94SvNK55F/Sp7hVoPbhBNpSL1BT
|
||||
IBAMBV24LyvZwhAcqq8MiOrLPGNv6+EvNQqPD7xQl0GeRouHeCYVpDA+NdSfc8jm
|
||||
eVysjwQVBpTkudsdSW5JvuN8VRJVD2P8/a0gy+p4/C/k/Prd6DoQAiBz6FZrYoEd
|
||||
iYgIegHOMXWd4vzO3ENOWSIUI6ci7Aro+Y0Z75kfiVokAGhUcFgrZ58E82fBYh8I
|
||||
cxO20oMnucGrLicQzj536jx4wX3Cdd4jr9UVEJ9ZII1ldlp03nZlFLXqJH1547Aq
|
||||
ZM+3vVcBGoJ8T9ZQ4VDAL++0K2DLC9JkTARAYCEi/QKBgQDebIc1+2zblhQtVQ/e
|
||||
IbEErZcB7v+TkUoRoBfR0lj7bKBFJgRe37fgu1xf95/s63okdnOw/OuQqtGmgx/J
|
||||
TL3yULBdNcwTCRm41t+cqoGymjK0VRbqk6CWBId0E3r5TaCVWedk2JI2XwTvIJ1A
|
||||
eDiqfJeDHUD44yaonwbysj9ZDwKBgQDL5VQfTppVaJk2PXNwhAkRQklZ8RFmt/7p
|
||||
yA3dddQNdwMk4Fl8F7QuO1gBxDiHdnwIrlEOz6fTsM3LwIS+Q12P1vYFIhpo7HDB
|
||||
wvjfMwCPxBIS4jI28RgcAf0VbZ/+CHAm6bb9iDwsjXhh1J5oOm5VKnju6/rPH/QY
|
||||
+md40pnSWwKBgBnKPbdNquafNUG4XjmkcHEZa6wGuU20CAGZLYnfuP+WLdM2wET7
|
||||
7cc6ElDyVnHTL/twXKPF/85rcBm9lH7zzgZ9wqVcKoh+gqQDDjSNNLKv3Hc6cojK
|
||||
i1E5vzb/Vz/290q5/PGdhv6U7+6GOpWSGwfxoGPMjY8OT5o3rkeP0XaTAoGBALLR
|
||||
GQmr4eZtqZDMK+XNpjYgsDvVE7HGRCW7cY17vNFiQruglloiX778BJ7n+7uxye3D
|
||||
EwuuSj15ncLHwKMsaW2w1GqEEi1azzjfSWxWSnPLPR6aifdtUfueMtsMHXio5dL6
|
||||
vaV0SXG5UI5b7eDy/bhrW0wOYRQtreIKGZz49jZpAoGBAIvxYngkLwmq6g6MmnAc
|
||||
YK4oT6YAm2wfSy2mzpEQP5r1igp1rN7T46o7FMUPDLS9wK3ESAaIYe01qT6Yftcc
|
||||
5qF+yiOGDTr9XQiHwe4BcyrNEMfUjDhDU5ao2gH8+t1VGr1KspLsUNbedrJwZsY4
|
||||
UCZVKEEDHzKfLO/iBgKjJQF7
|
||||
-----END PRIVATE KEY-----`)
|
||||
|
||||
rsaSigner = mustMakeSigner(jose.RS256, testPrivRSAKey1)
|
||||
hmacSigner = mustMakeSigner(jose.HS256, sharedKey)
|
||||
)
|
112
vendor/gopkg.in/square/go-jose.v2/jwt/claims.go
generated
vendored
112
vendor/gopkg.in/square/go-jose.v2/jwt/claims.go
generated
vendored
@@ -18,66 +18,98 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
// Claims represents public claim values (as specified in RFC 7519).
|
||||
type Claims struct {
|
||||
Issuer string `json:"-"`
|
||||
Subject string `json:"-"`
|
||||
Audience []string `json:"-"`
|
||||
Expiry time.Time `json:"-"`
|
||||
NotBefore time.Time `json:"-"`
|
||||
IssuedAt time.Time `json:"-"`
|
||||
ID string `json:"-"`
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
Subject string `json:"sub,omitempty"`
|
||||
Audience Audience `json:"aud,omitempty"`
|
||||
Expiry NumericDate `json:"exp,omitempty"`
|
||||
NotBefore NumericDate `json:"nbf,omitempty"`
|
||||
IssuedAt NumericDate `json:"iat,omitempty"`
|
||||
ID string `json:"jti,omitempty"`
|
||||
}
|
||||
|
||||
type rawClaims struct {
|
||||
Iss string `json:"iss,omitempty"`
|
||||
Sub string `json:"sub,omitempty"`
|
||||
Aud audience `json:"aud,omitempty"`
|
||||
Exp NumericDate `json:"exp,omitempty"`
|
||||
Nbf NumericDate `json:"nbf,omitempty"`
|
||||
Iat NumericDate `json:"iat,omitempty"`
|
||||
Jti string `json:"jti,omitempty"`
|
||||
}
|
||||
// NumericDate represents date and time as the number of seconds since the
|
||||
// epoch, including leap seconds. Non-integer values can be represented
|
||||
// in the serialized format, but we round to the nearest second.
|
||||
type NumericDate int64
|
||||
|
||||
func (c *Claims) marshalJSON() ([]byte, error) {
|
||||
t := rawClaims{
|
||||
Iss: c.Issuer,
|
||||
Sub: c.Subject,
|
||||
Aud: audience(c.Audience),
|
||||
Exp: TimeToNumericDate(c.Expiry),
|
||||
Nbf: TimeToNumericDate(c.NotBefore),
|
||||
Iat: TimeToNumericDate(c.IssuedAt),
|
||||
Jti: c.ID,
|
||||
// NewNumericDate constructs NumericDate from time.Time value.
|
||||
func NewNumericDate(t time.Time) NumericDate {
|
||||
if t.IsZero() {
|
||||
return NumericDate(0)
|
||||
}
|
||||
|
||||
b, err := jose.MarshalJSON(t)
|
||||
// While RFC 7519 technically states that NumericDate values may be
|
||||
// non-integer values, we don't bother serializing timestamps in
|
||||
// claims with sub-second accurancy and just round to the nearest
|
||||
// second instead. Not convined sub-second accuracy is useful here.
|
||||
return NumericDate(t.Unix())
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the given NumericDate into its JSON representation.
|
||||
func (n NumericDate) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.FormatInt(int64(n), 10)), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a date from its JSON representation.
|
||||
func (n *NumericDate) UnmarshalJSON(b []byte) error {
|
||||
s := string(b)
|
||||
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ErrUnmarshalNumericDate
|
||||
}
|
||||
|
||||
return b, err
|
||||
*n = NumericDate(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Claims) unmarshalJSON(b []byte) error {
|
||||
t := rawClaims{}
|
||||
// Time returns time.Time representation of NumericDate.
|
||||
func (n NumericDate) Time() time.Time {
|
||||
return time.Unix(int64(n), 0)
|
||||
}
|
||||
|
||||
if err := jose.UnmarshalJSON(b, &t); err != nil {
|
||||
// Audience represents the recipents that the token is intended for.
|
||||
type Audience []string
|
||||
|
||||
// UnmarshalJSON reads an audience from its JSON representation.
|
||||
func (s *Audience) UnmarshalJSON(b []byte) error {
|
||||
var v interface{}
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Issuer = t.Iss
|
||||
c.Subject = t.Sub
|
||||
c.Audience = []string(t.Aud)
|
||||
c.Expiry = t.Exp.Time()
|
||||
c.NotBefore = t.Nbf.Time()
|
||||
c.IssuedAt = t.Iat.Time()
|
||||
c.ID = t.Jti
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
*s = []string{v}
|
||||
case []interface{}:
|
||||
a := make([]string, len(v))
|
||||
for i, e := range v {
|
||||
s, ok := e.(string)
|
||||
if !ok {
|
||||
return ErrUnmarshalAudience
|
||||
}
|
||||
a[i] = s
|
||||
}
|
||||
*s = a
|
||||
default:
|
||||
return ErrUnmarshalAudience
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Audience) Contains(v string) bool {
|
||||
for _, a := range s {
|
||||
if a == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
48
vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go
generated
vendored
48
vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go
generated
vendored
@@ -21,6 +21,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -28,14 +30,15 @@ func TestEncodeClaims(t *testing.T) {
|
||||
now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
c := Claims{
|
||||
Issuer: "issuer",
|
||||
Subject: "subject",
|
||||
Audience: []string{"a1", "a2"},
|
||||
IssuedAt: now,
|
||||
Expiry: now.Add(1 * time.Hour),
|
||||
Issuer: "issuer",
|
||||
Subject: "subject",
|
||||
Audience: Audience{"a1", "a2"},
|
||||
NotBefore: NewNumericDate(time.Time{}),
|
||||
IssuedAt: NewNumericDate(now),
|
||||
Expiry: NewNumericDate(now.Add(1 * time.Hour)),
|
||||
}
|
||||
|
||||
b, err := c.marshalJSON()
|
||||
b, err := json.Marshal(c)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := `{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}`
|
||||
@@ -47,12 +50,31 @@ func TestDecodeClaims(t *testing.T) {
|
||||
now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
c := Claims{}
|
||||
err := c.unmarshalJSON(s)
|
||||
assert.NoError(t, err)
|
||||
if err := json.Unmarshal(s, &c); assert.NoError(t, err) {
|
||||
assert.Equal(t, "issuer", c.Issuer)
|
||||
assert.Equal(t, "subject", c.Subject)
|
||||
assert.Equal(t, Audience{"a1", "a2"}, c.Audience)
|
||||
assert.True(t, now.Equal(c.IssuedAt.Time()))
|
||||
assert.True(t, now.Add(1*time.Hour).Equal(c.Expiry.Time()))
|
||||
}
|
||||
|
||||
assert.Equal(t, "issuer", c.Issuer)
|
||||
assert.Equal(t, "subject", c.Subject)
|
||||
assert.Equal(t, []string{"a1", "a2"}, c.Audience)
|
||||
assert.True(t, now.Equal(c.IssuedAt))
|
||||
assert.True(t, now.Add(1*time.Hour).Equal(c.Expiry))
|
||||
s2 := []byte(`{"aud": "a1"}`)
|
||||
c2 := Claims{}
|
||||
if err := json.Unmarshal(s2, &c2); assert.NoError(t, err) {
|
||||
assert.Equal(t, Audience{"a1"}, c2.Audience)
|
||||
}
|
||||
|
||||
invalid := []struct {
|
||||
Raw string
|
||||
Err error
|
||||
}{
|
||||
{`{"aud": 5}`, ErrUnmarshalAudience},
|
||||
{`{"aud": ["foo", 5, "bar"]}`, ErrUnmarshalAudience},
|
||||
{`{"exp": "invalid"}`, ErrUnmarshalNumericDate},
|
||||
}
|
||||
|
||||
for _, v := range invalid {
|
||||
c := Claims{}
|
||||
assert.Equal(t, v.Err, json.Unmarshal([]byte(v.Raw), &c))
|
||||
}
|
||||
}
|
||||
|
200
vendor/gopkg.in/square/go-jose.v2/jwt/example_test.go
generated
vendored
Normal file
200
vendor/gopkg.in/square/go-jose.v2/jwt/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
/*-
|
||||
* Copyright 2016 Zbigniew Mandziejewicz
|
||||
* Copyright 2016 Square, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jwt_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
var sharedKey = []byte("secret")
|
||||
var sharedEncryptionKey = []byte("itsa16bytesecret")
|
||||
var signer, _ = jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: sharedKey}, &jose.SignerOptions{})
|
||||
|
||||
func ExampleParseSigned() {
|
||||
raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0`
|
||||
tok, err := jwt.ParseSigned(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out := jwt.Claims{}
|
||||
if err := tok.Claims(sharedKey, &out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject)
|
||||
// Output: iss: issuer, sub: subject
|
||||
}
|
||||
|
||||
func ExampleParseEncrypted() {
|
||||
key := []byte("itsa16bytesecret")
|
||||
raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..jg45D9nmr6-8awml.z-zglLlEw9MVkYHi-Znd9bSwc-oRGbqKzf9WjXqZxno.kqji2DiZHZmh-1bLF6ARPw`
|
||||
tok, err := jwt.ParseEncrypted(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out := jwt.Claims{}
|
||||
if err := tok.Claims(key, &out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject)
|
||||
//Output: iss: issuer, sub: subject
|
||||
}
|
||||
|
||||
func ExampleClaims_Validate() {
|
||||
cl := jwt.Claims{
|
||||
Subject: "subject",
|
||||
Issuer: "issuer",
|
||||
NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)),
|
||||
Expiry: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 15, 0, 0, time.UTC)),
|
||||
Audience: jwt.Audience{"leela", "fry"},
|
||||
}
|
||||
|
||||
err := cl.Validate(jwt.Expected{
|
||||
Issuer: "issuer",
|
||||
Time: time.Date(2016, 1, 1, 0, 10, 0, 0, time.UTC),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("valid!")
|
||||
// Output: valid!
|
||||
}
|
||||
|
||||
func ExampleClaims_Validate_withParse() {
|
||||
raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0`
|
||||
tok, err := jwt.ParseSigned(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cl := jwt.Claims{}
|
||||
if err := tok.Claims(sharedKey, &cl); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = cl.Validate(jwt.Expected{
|
||||
Issuer: "issuer",
|
||||
Subject: "subject",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("valid!")
|
||||
// Output: valid!
|
||||
}
|
||||
|
||||
func ExampleSigned() {
|
||||
key := []byte("secret")
|
||||
sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, &jose.SignerOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cl := jwt.Claims{
|
||||
Subject: "subject",
|
||||
Issuer: "issuer",
|
||||
NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)),
|
||||
Audience: jwt.Audience{"leela", "fry"},
|
||||
}
|
||||
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(raw)
|
||||
// Output: eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiaXNzIjoiaXNzdWVyIiwibmJmIjoxLjQ1MTYwNjRlKzA5LCJzdWIiOiJzdWJqZWN0In0.uazfxZNgnlLdNDK7JkuYj3LlT4jSyEDG8EWISBPUuME
|
||||
}
|
||||
|
||||
func ExampleEncrypted() {
|
||||
enc, err := jose.NewEncrypter(jose.A128GCM, jose.Recipient{Algorithm: jose.DIRECT, Key: sharedEncryptionKey}, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cl := jwt.Claims{
|
||||
Subject: "subject",
|
||||
Issuer: "issuer",
|
||||
}
|
||||
raw, err := jwt.Encrypted(enc).Claims(cl).CompactSerialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(raw)
|
||||
}
|
||||
|
||||
func ExampleSigned_multipleClaims() {
|
||||
c := &jwt.Claims{
|
||||
Subject: "subject",
|
||||
Issuer: "issuer",
|
||||
}
|
||||
c2 := struct {
|
||||
Scopes []string
|
||||
}{
|
||||
[]string{"foo", "bar"},
|
||||
}
|
||||
raw, err := jwt.Signed(signer).Claims(c).Claims(c2).CompactSerialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(raw)
|
||||
// Output: eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y
|
||||
}
|
||||
|
||||
func ExampleJSONWebToken_Claims_map() {
|
||||
raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0`
|
||||
tok, err := jwt.ParseSigned(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out := make(map[string]interface{})
|
||||
if err := tok.Claims(sharedKey, &out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("iss: %s, sub: %s\n", out["iss"], out["sub"])
|
||||
// Output: iss: issuer, sub: subject
|
||||
}
|
||||
|
||||
func ExampleJSONWebToken_Claims_multiple() {
|
||||
raw := `eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y`
|
||||
tok, err := jwt.ParseSigned(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out := jwt.Claims{}
|
||||
out2 := struct {
|
||||
Scopes []string
|
||||
}{}
|
||||
if err := tok.Claims(sharedKey, &out, &out2); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("iss: %s, sub: %s, scopes: %s\n", out.Issuer, out.Subject, strings.Join(out2.Scopes, ","))
|
||||
// Output: iss: issuer, sub: subject, scopes: foo,bar
|
||||
}
|
179
vendor/gopkg.in/square/go-jose.v2/jwt/json.go
generated
vendored
179
vendor/gopkg.in/square/go-jose.v2/jwt/json.go
generated
vendored
@@ -1,179 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2016 Zbigniew Mandziejewicz
|
||||
* Copyright 2016 Square, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
// NumericDate represents date and time as the number of seconds since the
|
||||
// epoch, including leap seconds. Non-integer values can be represented
|
||||
// in the serialized format, but we round to the nearest second.
|
||||
type NumericDate int64
|
||||
|
||||
// TimeToNumericDate converts time.Time value into NumericDate.
|
||||
func TimeToNumericDate(t time.Time) NumericDate {
|
||||
if t.IsZero() {
|
||||
return NumericDate(0)
|
||||
}
|
||||
|
||||
// While RFC 7519 technically states that NumericDate values may be
|
||||
// non-integer values, we don't bother serializing timestamps in
|
||||
// claims with sub-second accurancy and just round to the nearest
|
||||
// second instead. Not convined sub-second accuracy is useful here.
|
||||
return NumericDate(t.Unix())
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the given NumericDate into its JSON representation.
|
||||
func (n NumericDate) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.FormatInt(int64(n), 10)), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a date from its JSON representation.
|
||||
func (n *NumericDate) UnmarshalJSON(b []byte) error {
|
||||
s := string(b)
|
||||
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return ErrUnmarshalNumericDate
|
||||
}
|
||||
|
||||
*n = NumericDate(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Time returns time.Time representation of NumericDate.
|
||||
func (n NumericDate) Time() time.Time {
|
||||
i, f := math.Modf(float64(n))
|
||||
return time.Unix(int64(i), int64(f*float64(time.Second)))
|
||||
}
|
||||
|
||||
type audience []string
|
||||
|
||||
func (s *audience) UnmarshalJSON(b []byte) error {
|
||||
var v interface{}
|
||||
if err := jose.UnmarshalJSON(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
*s = append(*s, v)
|
||||
case []interface{}:
|
||||
a := make([]string, len(v))
|
||||
for i, e := range v {
|
||||
s, ok := e.(string)
|
||||
if !ok {
|
||||
return ErrUnmarshalAudience
|
||||
}
|
||||
a[i] = s
|
||||
}
|
||||
*s = a
|
||||
default:
|
||||
return ErrUnmarshalAudience
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var claimsType = reflect.TypeOf((*Claims)(nil)).Elem()
|
||||
|
||||
func publicClaims(cl interface{}) (*Claims, error) {
|
||||
v := reflect.ValueOf(cl)
|
||||
if v.IsNil() || v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
|
||||
return nil, ErrInvalidClaims
|
||||
}
|
||||
|
||||
v = v.Elem()
|
||||
f := v.FieldByName("Claims")
|
||||
if !f.IsValid() || f.Type() != claimsType {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
c := f.Addr().Interface().(*Claims)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func marshalClaims(cl interface{}) ([]byte, error) {
|
||||
switch cl := cl.(type) {
|
||||
case *Claims:
|
||||
return cl.marshalJSON()
|
||||
case map[string]interface{}:
|
||||
return jose.MarshalJSON(cl)
|
||||
}
|
||||
|
||||
public, err := publicClaims(cl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// i doesn't contain nested jwt.Claims
|
||||
if public == nil {
|
||||
return jose.MarshalJSON(cl)
|
||||
}
|
||||
|
||||
// marshal jwt.Claims
|
||||
b1, err := public.marshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// marshal private claims
|
||||
b2, err := jose.MarshalJSON(cl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// merge claims
|
||||
r := make([]byte, len(b1)+len(b2)-1)
|
||||
copy(r, b1)
|
||||
r[len(b1)-1] = ','
|
||||
copy(r[len(b1):], b2[1:])
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func unmarshalClaims(b []byte, cl interface{}) error {
|
||||
switch cl := cl.(type) {
|
||||
case *Claims:
|
||||
return cl.unmarshalJSON(b)
|
||||
case map[string]interface{}:
|
||||
return jose.UnmarshalJSON(b, cl)
|
||||
}
|
||||
|
||||
if err := jose.UnmarshalJSON(b, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
public, err := publicClaims(cl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// unmarshal jwt.Claims
|
||||
if public != nil {
|
||||
if err := public.unmarshalJSON(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
25
vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go
generated
vendored
25
vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go
generated
vendored
@@ -17,20 +17,31 @@
|
||||
|
||||
package jwt
|
||||
|
||||
import "gopkg.in/square/go-jose.v2"
|
||||
import (
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
|
||||
type JSONWebToken struct {
|
||||
payload func(k interface{}) ([]byte, error)
|
||||
Headers []jose.Header
|
||||
}
|
||||
|
||||
// Claims deserializes a JSONWebToken into dest using the provided key.
|
||||
func (t *JSONWebToken) Claims(dest interface{}, key interface{}) error {
|
||||
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
|
||||
b, err := t.payload(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return unmarshalClaims(b, dest)
|
||||
|
||||
for _, d := range dest {
|
||||
if err := json.Unmarshal(b, d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseSigned parses token from JWS form.
|
||||
@@ -39,8 +50,12 @@ func ParseSigned(s string) (*JSONWebToken, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headers := make([]jose.Header, len(sig.Signatures))
|
||||
for i, signature := range sig.Signatures {
|
||||
headers[i] = signature.Header
|
||||
}
|
||||
|
||||
return &JSONWebToken{sig.Verify}, nil
|
||||
return &JSONWebToken{sig.Verify, headers}, nil
|
||||
}
|
||||
|
||||
// ParseEncrypted parses token from JWE form.
|
||||
@@ -50,5 +65,5 @@ func ParseEncrypted(s string) (*JSONWebToken, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &JSONWebToken{enc.Decrypt}, nil
|
||||
return &JSONWebToken{enc.Decrypt, []jose.Header{enc.Header}}, nil
|
||||
}
|
||||
|
117
vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go
generated
vendored
117
vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go
generated
vendored
@@ -21,57 +21,96 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
var encryptionKey = []byte("secret")
|
||||
var rawToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0.Y6_PfQHrzRJ_Vlxij5VI07-pgDIuJNN3Z_g5sSaGQ0c`
|
||||
var (
|
||||
hmacSignedToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0.Y6_PfQHrzRJ_Vlxij5VI07-pgDIuJNN3Z_g5sSaGQ0c`
|
||||
rsaSignedToken = `eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzY29wZXMiOlsiczEiLCJzMiJdLCJzdWIiOiJzdWJqZWN0In0.UDDtyK9gC9kyHltcP7E_XODsnqcJWZIiXeGmSAH7SE9YKy3N0KSfFIN85dCNjTfs6zvy4rkrCHzLB7uKAtzMearh3q7jL4nxbhUMhlUcs_9QDVoN4q_j58XmRqBqRnBk-RmDu9TgcV8RbErP4awpIhwWb5UU-hR__4_iNbHdKqwSUPDKYGlf5eicuiYrPxH8mxivk4LRD-vyRdBZZKBt0XIDnEU4TdcNCzAXojkftqcFWYsczwS8R4JHd1qYsMyiaWl4trdHZkO4QkeLe34z4ZAaPMt3wE-gcU-VoqYTGxz-K3Le2VaZ0r3j_z6bOInsv0yngC_cD1dCXMyQJWnWjQ`
|
||||
invalidPayloadSignedToken = `eyJhbGciOiJIUzI1NiJ9.aW52YWxpZC1wYXlsb2Fk.ScBKKm18jcaMLGYDNRUqB5gVMRZl4DM6dh3ShcxeNgY`
|
||||
invalidPartsSignedToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0`
|
||||
hmacEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..NZrU98U4QNO0y-u6.HSq5CvlmkUT1BPqLGZ4.1-zuiZ4RbHrTTUoA8Dvfhg`
|
||||
rsaEncryptedToken = `eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.IvkVHHiI8JwwavvTR80xGjYvkzubMrZ-TDDx8k8SNJMEylfFfNUc7F2rC3WAABF_xmJ3SW2A6on-S6EAG97k0RsjqHHNqZuaFpDvjeuLqZFfYKzI45aCtkGG4C2ij2GbeySqJ784CcvFJPUWJ-6VPN2Ho2nhefUSqig0jE2IvOKy1ywTj_VBVBxF_dyXFnXwxPKGUQr3apxrWeRJfDh2Cf8YPBlLiRznjfBfwgePB1jP7WCZNwItj10L7hsT_YWEx01XJcbxHaXFLwKyVzwWaDhreFyaWMRbGqEfqVuOT34zfmhLDhQlgLLwkXrvYqX90NsQ9Ftg0LLIfRMbsfdgug.BFy2Tj1RZN8yq2Lk-kMiZQ.9Z0eOyPiv5cEzmXh64RlAQ36Uvz0WpZgqRcc2_69zHTmUOv0Vnl1I6ks8sTraUEvukAilolNBjBj47s0b4b-Og.VM8-eJg5ZsqnTqs0LtGX_Q`
|
||||
invalidPayloadEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..T4jCS4Yyw1GCH0aW.y4gFaMITdBs_QZM8RKrL.6MPyk1cMVaOJFoNGlEuaRQ`
|
||||
invalidPartsEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..NZrU98U4QNO0y-u6.HSq5CvlmkUT1BPqLGZ4`
|
||||
)
|
||||
|
||||
type customClaims struct {
|
||||
Claims
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
}
|
||||
|
||||
func TestDecodeToken(t *testing.T) {
|
||||
tok, err := ParseSigned(rawToken)
|
||||
assert.NoError(t, err)
|
||||
c := &Claims{}
|
||||
if assert.NoError(t, tok.Claims(c, encryptionKey)) {
|
||||
assert.Equal(t, c.Subject, "subject")
|
||||
assert.Equal(t, c.Issuer, "issuer")
|
||||
tok, err := ParseSigned(hmacSignedToken)
|
||||
if assert.NoError(t, err, "Error parsing signed token.") {
|
||||
c := &Claims{}
|
||||
c2 := &customClaims{}
|
||||
if assert.NoError(t, tok.Claims(sharedKey, c, c2)) {
|
||||
assert.Equal(t, "subject", c.Subject)
|
||||
assert.Equal(t, "issuer", c.Issuer)
|
||||
assert.Equal(t, []string{"s1", "s2"}, c2.Scopes)
|
||||
}
|
||||
}
|
||||
assert.EqualError(t, tok.Claims([]byte("invalid-secret")), "square/go-jose: error in cryptographic primitive")
|
||||
|
||||
tok2, err := ParseSigned(rsaSignedToken)
|
||||
if assert.NoError(t, err, "Error parsing encrypted token.") {
|
||||
c := make(map[string]interface{})
|
||||
if assert.NoError(t, tok2.Claims(&testPrivRSAKey1.PublicKey, &c)) {
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"sub": "subject",
|
||||
"iss": "issuer",
|
||||
"scopes": []interface{}{"s1", "s2"},
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
assert.EqualError(t, tok.Claims(&testPrivRSAKey2.PublicKey), "square/go-jose: error in cryptographic primitive")
|
||||
|
||||
tok3, err := ParseSigned(invalidPayloadSignedToken)
|
||||
if assert.NoError(t, err, "Error parsing signed token.") {
|
||||
assert.Error(t, tok3.Claims(sharedKey, &Claims{}), "Expected unmarshaling claims to fail.")
|
||||
}
|
||||
|
||||
c2 := &customClaims{}
|
||||
if assert.NoError(t, tok.Claims(c2, encryptionKey)) {
|
||||
assert.Equal(t, c2.Subject, "subject")
|
||||
assert.Equal(t, c2.Issuer, "issuer")
|
||||
assert.Equal(t, c2.Scopes, []string{"s1", "s2"})
|
||||
_, err = ParseSigned(invalidPartsSignedToken)
|
||||
assert.EqualError(t, err, "square/go-jose: compact JWS format must have three parts")
|
||||
|
||||
tok4, err := ParseEncrypted(hmacEncryptedToken)
|
||||
if assert.NoError(t, err, "Error parsing encrypted token.") {
|
||||
c := Claims{}
|
||||
if assert.NoError(t, tok4.Claims(sharedEncryptionKey, &c)) {
|
||||
assert.Equal(t, "foo", c.Subject)
|
||||
}
|
||||
}
|
||||
assert.EqualError(t, tok4.Claims([]byte("invalid-secret-key")), "square/go-jose: error in cryptographic primitive")
|
||||
|
||||
tok5, err := ParseEncrypted(rsaEncryptedToken)
|
||||
if assert.NoError(t, err, "Error parsing encrypted token.") {
|
||||
c := make(map[string]interface{})
|
||||
if assert.NoError(t, tok5.Claims(testPrivRSAKey1, &c)) {
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"sub": "subject",
|
||||
"iss": "issuer",
|
||||
"scopes": []interface{}{"s1", "s2"},
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
assert.EqualError(t, tok5.Claims(testPrivRSAKey2), "square/go-jose: error in cryptographic primitive")
|
||||
|
||||
tok6, err := ParseEncrypted(invalidPayloadEncryptedToken)
|
||||
if assert.NoError(t, err, "Error parsing encrypted token.") {
|
||||
assert.Error(t, tok6.Claims(sharedEncryptionKey, &Claims{}))
|
||||
}
|
||||
|
||||
_, err = ParseEncrypted(invalidPartsEncryptedToken)
|
||||
assert.EqualError(t, err, "square/go-jose: compact JWE format must have five parts")
|
||||
}
|
||||
|
||||
func BenchmarkDecodeSignedToken(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ParseSigned(hmacSignedToken)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeToken(t *testing.T) {
|
||||
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: encryptionKey}, &jose.SignerOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
c := &customClaims{
|
||||
Claims: Claims{
|
||||
Subject: "subject",
|
||||
Issuer: "issuer",
|
||||
},
|
||||
Scopes: []string{"s1", "s2"},
|
||||
}
|
||||
|
||||
raw, err := Signed(signer).Claims(c).CompactSerialize()
|
||||
require.NoError(t, err)
|
||||
|
||||
tok, err := ParseSigned(raw)
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := &customClaims{}
|
||||
if assert.NoError(t, tok.Claims(c2, encryptionKey)) {
|
||||
assert.Equal(t, c2.Subject, "subject")
|
||||
assert.Equal(t, c2.Issuer, "issuer")
|
||||
assert.Equal(t, c2.Scopes, []string{"s1", "s2"})
|
||||
func BenchmarkDecodeEncryptedHMACToken(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ParseEncrypted(hmacEncryptedToken)
|
||||
}
|
||||
}
|
||||
|
26
vendor/gopkg.in/square/go-jose.v2/jwt/validation.go
generated
vendored
26
vendor/gopkg.in/square/go-jose.v2/jwt/validation.go
generated
vendored
@@ -24,13 +24,19 @@ const (
|
||||
DefaultLeeway = 1.0 * time.Minute
|
||||
)
|
||||
|
||||
// Expected defines values used for claims validation.
|
||||
// Expected defines values used for protected claims validation.
|
||||
// If field has zero value then validation is skipped.
|
||||
type Expected struct {
|
||||
Issuer string
|
||||
Subject string
|
||||
Audience []string
|
||||
ID string
|
||||
Time time.Time
|
||||
// Issuer matches the "iss" claim exactly.
|
||||
Issuer string
|
||||
// Subject matches the "sub" claim exactly.
|
||||
Subject string
|
||||
// Audience matches the values in "aud" claim, regardless of their order.
|
||||
Audience Audience
|
||||
// ID matches the "jti" claim exactly.
|
||||
ID string
|
||||
// Time matches the "exp" and "ebf" claims with leeway.
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
// WithTime copies expectations with new time.
|
||||
@@ -68,18 +74,18 @@ func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error {
|
||||
return ErrInvalidAudience
|
||||
}
|
||||
|
||||
for i, a := range e.Audience {
|
||||
if a != c.Audience[i] {
|
||||
for _, v := range e.Audience {
|
||||
if !c.Audience.Contains(v) {
|
||||
return ErrInvalidAudience
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !e.Time.IsZero() && e.Time.Add(leeway).Before(c.NotBefore) {
|
||||
if !e.Time.IsZero() && e.Time.Add(leeway).Before(c.NotBefore.Time()) {
|
||||
return ErrNotValidYet
|
||||
}
|
||||
|
||||
if !e.Time.IsZero() && e.Time.Add(-leeway).After(c.Expiry) {
|
||||
if !e.Time.IsZero() && e.Time.Add(-leeway).After(c.Expiry.Time()) {
|
||||
return ErrExpired
|
||||
}
|
||||
|
||||
|
42
vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go
generated
vendored
42
vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go
generated
vendored
@@ -32,28 +32,32 @@ func TestFieldsMatch(t *testing.T) {
|
||||
ID: "42",
|
||||
}
|
||||
|
||||
assert.NoError(t, c.Validate(Expected{Issuer: "issuer"}))
|
||||
err := c.Validate(Expected{Issuer: "invalid-issuer"})
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, err, ErrInvalidIssuer)
|
||||
valid := []Expected{
|
||||
{Issuer: "issuer"},
|
||||
{Subject: "subject"},
|
||||
{Audience: Audience{"a1", "a2"}},
|
||||
{Audience: Audience{"a2", "a1"}},
|
||||
{ID: "42"},
|
||||
}
|
||||
|
||||
assert.NoError(t, c.Validate(Expected{Subject: "subject"}))
|
||||
err = c.Validate(Expected{Subject: "invalid-subject"})
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, err, ErrInvalidSubject)
|
||||
for _, v := range valid {
|
||||
assert.NoError(t, c.Validate(v))
|
||||
}
|
||||
|
||||
assert.NoError(t, c.Validate(Expected{Audience: []string{"a1", "a2"}}))
|
||||
err = c.Validate(Expected{Audience: []string{"invalid-audience"}})
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, err, ErrInvalidAudience)
|
||||
invalid := []struct {
|
||||
Expected Expected
|
||||
Error error
|
||||
}{
|
||||
{Expected{Issuer: "invalid-issuer"}, ErrInvalidIssuer},
|
||||
{Expected{Subject: "invalid-subject"}, ErrInvalidSubject},
|
||||
{Expected{Audience: Audience{"a1"}}, ErrInvalidAudience},
|
||||
{Expected{Audience: Audience{"a1", "invalid-audience"}}, ErrInvalidAudience},
|
||||
{Expected{Audience: Audience{"invalid-audience"}}, ErrInvalidAudience},
|
||||
{Expected{ID: "invalid-id"}, ErrInvalidID},
|
||||
}
|
||||
|
||||
assert.NoError(t, c.Validate(Expected{ID: "42"}))
|
||||
err = c.Validate(Expected{ID: "invalid-id"})
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, err, ErrInvalidID)
|
||||
for _, v := range invalid {
|
||||
assert.Equal(t, v.Error, c.Validate(v.Expected))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,9 +66,9 @@ func TestExpiryAndNotBefore(t *testing.T) {
|
||||
twelveHoursAgo := now.Add(-12 * time.Hour)
|
||||
|
||||
c := Claims{
|
||||
IssuedAt: twelveHoursAgo,
|
||||
NotBefore: twelveHoursAgo,
|
||||
Expiry: now,
|
||||
IssuedAt: NewNumericDate(twelveHoursAgo),
|
||||
NotBefore: NewNumericDate(twelveHoursAgo),
|
||||
Expiry: NewNumericDate(now),
|
||||
}
|
||||
|
||||
// expired - default leeway (1 minute)
|
||||
|
44
vendor/gopkg.in/square/go-jose.v2/signing.go
generated
vendored
44
vendor/gopkg.in/square/go-jose.v2/signing.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@@ -185,13 +186,50 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
}
|
||||
|
||||
// Verify validates the signature on the object and returns the payload.
|
||||
// This function does not support multi-signature, if you desire multi-sig
|
||||
// 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.
|
||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||
verifier, err := newVerifier(verificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, signature := range obj.Signatures {
|
||||
if len(obj.Signatures) > 1 {
|
||||
return nil, errors.New("square/go-jose: too many signatures in payload; expecting only one")
|
||||
}
|
||||
|
||||
signature := obj.Signatures[0]
|
||||
headers := signature.mergedHeaders()
|
||||
if len(headers.Crit) > 0 {
|
||||
// Unsupported crit header
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
input := obj.computeAuthData(&signature)
|
||||
alg := SignatureAlgorithm(headers.Alg)
|
||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return obj.payload, nil
|
||||
}
|
||||
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// VerifyMulti validates (one of the multiple) signatures on the object and
|
||||
// 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.
|
||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||
verifier, err := newVerifier(verificationKey)
|
||||
if err != nil {
|
||||
return -1, Signature{}, nil, err
|
||||
}
|
||||
|
||||
for i, signature := range obj.Signatures {
|
||||
headers := signature.mergedHeaders()
|
||||
if len(headers.Crit) > 0 {
|
||||
// Unsupported crit header
|
||||
@@ -202,9 +240,9 @@ func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error)
|
||||
alg := SignatureAlgorithm(headers.Alg)
|
||||
err := verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return obj.payload, nil
|
||||
return i, signature, obj.payload, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ErrCryptoFailure
|
||||
return -1, Signature{}, nil, ErrCryptoFailure
|
||||
}
|
||||
|
38
vendor/gopkg.in/square/go-jose.v2/signing_test.go
generated
vendored
38
vendor/gopkg.in/square/go-jose.v2/signing_test.go
generated
vendored
@@ -24,6 +24,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
type staticNonceSource string
|
||||
@@ -223,43 +225,45 @@ func TestMultiRecipientJWS(t *testing.T) {
|
||||
input := []byte("Lorem ipsum dolor sit amet")
|
||||
obj, err := signer.Sign(input)
|
||||
if err != nil {
|
||||
t.Error("error on sign: ", err)
|
||||
return
|
||||
t.Fatal("error on sign: ", err)
|
||||
}
|
||||
|
||||
_, err = obj.CompactSerialize()
|
||||
if err == nil {
|
||||
t.Error("message with multiple recipient was compact serialized")
|
||||
t.Fatal("message with multiple recipient was compact serialized")
|
||||
}
|
||||
|
||||
msg := obj.FullSerialize()
|
||||
|
||||
obj, err = ParseSigned(msg)
|
||||
if err != nil {
|
||||
t.Error("error on parse: ", err)
|
||||
return
|
||||
t.Fatal("error on parse: ", err)
|
||||
}
|
||||
|
||||
output, err := obj.Verify(&rsaTestKey.PublicKey)
|
||||
i, _, output, err := obj.VerifyMulti(&rsaTestKey.PublicKey)
|
||||
if err != nil {
|
||||
t.Error("error on verify: ", err)
|
||||
return
|
||||
t.Fatal("error on verify: ", err)
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
t.Fatal("signature index should be 0 for RSA key")
|
||||
}
|
||||
|
||||
if bytes.Compare(output, input) != 0 {
|
||||
t.Error("input/output do not match", output, input)
|
||||
return
|
||||
t.Fatal("input/output do not match", output, input)
|
||||
}
|
||||
|
||||
output, err = obj.Verify(sharedKey)
|
||||
i, _, output, err = obj.VerifyMulti(sharedKey)
|
||||
if err != nil {
|
||||
t.Error("error on verify: ", err)
|
||||
return
|
||||
t.Fatal("error on verify: ", err)
|
||||
}
|
||||
|
||||
if i != 1 {
|
||||
t.Fatal("signature index should be 1 for EC key")
|
||||
}
|
||||
|
||||
if bytes.Compare(output, input) != 0 {
|
||||
t.Error("input/output do not match", output, input)
|
||||
return
|
||||
t.Fatal("input/output do not match", output, input)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,12 +348,12 @@ func TestSignerKid(t *testing.T) {
|
||||
}
|
||||
|
||||
var jsonmsi map[string]interface{}
|
||||
err = UnmarshalJSON(jsonbar, &jsonmsi)
|
||||
err = json.Unmarshal(jsonbar, &jsonmsi)
|
||||
if err != nil {
|
||||
t.Error("problem unmarshalling base JWK", err)
|
||||
}
|
||||
jsonmsi["kid"] = kid
|
||||
jsonbar2, err := MarshalJSON(jsonmsi)
|
||||
jsonbar2, err := json.Marshal(jsonmsi)
|
||||
if err != nil {
|
||||
t.Error("problem marshalling kided JWK", err)
|
||||
}
|
||||
|
2
vendor/gopkg.in/square/go-jose.v2/utils_test.go
generated
vendored
2
vendor/gopkg.in/square/go-jose.v2/utils_test.go
generated
vendored
@@ -44,7 +44,7 @@ func fromBase64Int(encoded string) *big.Int {
|
||||
re := regexp.MustCompile(`\s+`)
|
||||
val, err := base64.RawURLEncoding.DecodeString(re.ReplaceAllString(encoded, ""))
|
||||
if err != nil {
|
||||
panic("Invalid test data")
|
||||
panic("Invalid test data: " + err.Error())
|
||||
}
|
||||
return new(big.Int).SetBytes(val)
|
||||
}
|
||||
|
Reference in New Issue
Block a user