forked from mystiq/dex
Update go-jose to v2.1.8
This commit is contained in:
parent
06241eae9f
commit
a823c021c8
18 changed files with 4594 additions and 178 deletions
9
glide.lock
generated
9
glide.lock
generated
|
@ -1,5 +1,5 @@
|
||||||
hash: c41e5b1fbd68f04f14b6e9b2ebab8bf18b857b3dc3a5754e4adf7c1884981de7
|
hash: 12d0ad2fc0df4ab221e45c1ba7821708b908033c82741e250cc46dcd445b67eb
|
||||||
updated: 2018-09-05T08:40:39.486766558+02:00
|
updated: 2018-09-18T23:51:30.787348994+02:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/beevik/etree
|
- name: github.com/beevik/etree
|
||||||
version: 4cd0dd976db869f817248477718071a28e978df0
|
version: 4cd0dd976db869f817248477718071a28e978df0
|
||||||
|
@ -108,6 +108,9 @@ imports:
|
||||||
subpackages:
|
subpackages:
|
||||||
- bcrypt
|
- bcrypt
|
||||||
- blowfish
|
- blowfish
|
||||||
|
- ed25519
|
||||||
|
- ed25519/internal/edwards25519
|
||||||
|
- pbkdf2
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: 5602c733f70afc6dcec6766be0d5034d4c4f14de
|
version: 5602c733f70afc6dcec6766be0d5034d4c4f14de
|
||||||
subpackages:
|
subpackages:
|
||||||
|
@ -168,7 +171,7 @@ imports:
|
||||||
- name: gopkg.in/ldap.v2
|
- name: gopkg.in/ldap.v2
|
||||||
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
||||||
- name: gopkg.in/square/go-jose.v2
|
- name: gopkg.in/square/go-jose.v2
|
||||||
version: 8c5257b2f658f86d174ae68c6a592eaf6a9608d9
|
version: 8254d6c783765f38c8675fae4427a1fe73fbd09d
|
||||||
subpackages:
|
subpackages:
|
||||||
- cipher
|
- cipher
|
||||||
- json
|
- json
|
||||||
|
|
|
@ -25,7 +25,7 @@ import:
|
||||||
|
|
||||||
# Used for JOSE functionality (JWKs, JWTs, etc.).
|
# Used for JOSE functionality (JWKs, JWTs, etc.).
|
||||||
- package: gopkg.in/square/go-jose.v2
|
- package: gopkg.in/square/go-jose.v2
|
||||||
version: v2.0.0
|
version: v2.1.8
|
||||||
subpackages:
|
subpackages:
|
||||||
- cipher
|
- cipher
|
||||||
- json
|
- json
|
||||||
|
|
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
Normal file
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||||
|
// http://ed25519.cr.yp.to/.
|
||||||
|
//
|
||||||
|
// These functions are also compatible with the “Ed25519” function defined in
|
||||||
|
// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
|
||||||
|
package ed25519
|
||||||
|
|
||||||
|
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||||
|
// from SUPERCOP.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
cryptorand "crypto/rand"
|
||||||
|
"crypto/sha512"
|
||||||
|
"crypto/subtle"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
||||||
|
PublicKeySize = 32
|
||||||
|
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
||||||
|
PrivateKeySize = 64
|
||||||
|
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||||
|
SignatureSize = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicKey is the type of Ed25519 public keys.
|
||||||
|
type PublicKey []byte
|
||||||
|
|
||||||
|
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
||||||
|
type PrivateKey []byte
|
||||||
|
|
||||||
|
// Public returns the PublicKey corresponding to priv.
|
||||||
|
func (priv PrivateKey) Public() crypto.PublicKey {
|
||||||
|
publicKey := make([]byte, PublicKeySize)
|
||||||
|
copy(publicKey, priv[32:])
|
||||||
|
return PublicKey(publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the given message with priv.
|
||||||
|
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
||||||
|
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
||||||
|
// indicate the message hasn't been hashed. This can be achieved by passing
|
||||||
|
// crypto.Hash(0) as the value for opts.
|
||||||
|
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||||
|
if opts.HashFunc() != crypto.Hash(0) {
|
||||||
|
return nil, errors.New("ed25519: cannot sign hashed message")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sign(priv, message), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||||
|
// If rand is nil, crypto/rand.Reader will be used.
|
||||||
|
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
|
||||||
|
if rand == nil {
|
||||||
|
rand = cryptorand.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey = make([]byte, PrivateKeySize)
|
||||||
|
publicKey = make([]byte, PublicKeySize)
|
||||||
|
_, err = io.ReadFull(rand, privateKey[:32])
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
digest := sha512.Sum512(privateKey[:32])
|
||||||
|
digest[0] &= 248
|
||||||
|
digest[31] &= 127
|
||||||
|
digest[31] |= 64
|
||||||
|
|
||||||
|
var A edwards25519.ExtendedGroupElement
|
||||||
|
var hBytes [32]byte
|
||||||
|
copy(hBytes[:], digest[:])
|
||||||
|
edwards25519.GeScalarMultBase(&A, &hBytes)
|
||||||
|
var publicKeyBytes [32]byte
|
||||||
|
A.ToBytes(&publicKeyBytes)
|
||||||
|
|
||||||
|
copy(privateKey[32:], publicKeyBytes[:])
|
||||||
|
copy(publicKey, publicKeyBytes[:])
|
||||||
|
|
||||||
|
return publicKey, privateKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the message with privateKey and returns a signature. It will
|
||||||
|
// panic if len(privateKey) is not PrivateKeySize.
|
||||||
|
func Sign(privateKey PrivateKey, message []byte) []byte {
|
||||||
|
if l := len(privateKey); l != PrivateKeySize {
|
||||||
|
panic("ed25519: bad private key length: " + strconv.Itoa(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(privateKey[:32])
|
||||||
|
|
||||||
|
var digest1, messageDigest, hramDigest [64]byte
|
||||||
|
var expandedSecretKey [32]byte
|
||||||
|
h.Sum(digest1[:0])
|
||||||
|
copy(expandedSecretKey[:], digest1[:])
|
||||||
|
expandedSecretKey[0] &= 248
|
||||||
|
expandedSecretKey[31] &= 63
|
||||||
|
expandedSecretKey[31] |= 64
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write(digest1[32:])
|
||||||
|
h.Write(message)
|
||||||
|
h.Sum(messageDigest[:0])
|
||||||
|
|
||||||
|
var messageDigestReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
|
||||||
|
var R edwards25519.ExtendedGroupElement
|
||||||
|
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
|
||||||
|
|
||||||
|
var encodedR [32]byte
|
||||||
|
R.ToBytes(&encodedR)
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write(encodedR[:])
|
||||||
|
h.Write(privateKey[32:])
|
||||||
|
h.Write(message)
|
||||||
|
h.Sum(hramDigest[:0])
|
||||||
|
var hramDigestReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
|
||||||
|
|
||||||
|
var s [32]byte
|
||||||
|
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
|
||||||
|
|
||||||
|
signature := make([]byte, SignatureSize)
|
||||||
|
copy(signature[:], encodedR[:])
|
||||||
|
copy(signature[32:], s[:])
|
||||||
|
|
||||||
|
return signature
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify reports whether sig is a valid signature of message by publicKey. It
|
||||||
|
// will panic if len(publicKey) is not PublicKeySize.
|
||||||
|
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
||||||
|
if l := len(publicKey); l != PublicKeySize {
|
||||||
|
panic("ed25519: bad public key length: " + strconv.Itoa(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sig) != SignatureSize || sig[63]&224 != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var A edwards25519.ExtendedGroupElement
|
||||||
|
var publicKeyBytes [32]byte
|
||||||
|
copy(publicKeyBytes[:], publicKey)
|
||||||
|
if !A.FromBytes(&publicKeyBytes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
edwards25519.FeNeg(&A.X, &A.X)
|
||||||
|
edwards25519.FeNeg(&A.T, &A.T)
|
||||||
|
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(sig[:32])
|
||||||
|
h.Write(publicKey[:])
|
||||||
|
h.Write(message)
|
||||||
|
var digest [64]byte
|
||||||
|
h.Sum(digest[:0])
|
||||||
|
|
||||||
|
var hReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&hReduced, &digest)
|
||||||
|
|
||||||
|
var R edwards25519.ProjectiveGroupElement
|
||||||
|
var b [32]byte
|
||||||
|
copy(b[:], sig[32:])
|
||||||
|
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
||||||
|
|
||||||
|
var checkR [32]byte
|
||||||
|
R.ToBytes(&checkR)
|
||||||
|
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
|
||||||
|
}
|
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
Normal file
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
77
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
Normal file
77
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
|
||||||
|
2898 / PKCS #5 v2.0.
|
||||||
|
|
||||||
|
A key derivation function is useful when encrypting data based on a password
|
||||||
|
or any other not-fully-random data. It uses a pseudorandom function to derive
|
||||||
|
a secure encryption key based on the password.
|
||||||
|
|
||||||
|
While v2.0 of the standard defines only one pseudorandom function to use,
|
||||||
|
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
|
||||||
|
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
||||||
|
choose, you can pass the `New` functions from the different SHA packages to
|
||||||
|
pbkdf2.Key.
|
||||||
|
*/
|
||||||
|
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"hash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Key derives a key from the password, salt and iteration count, returning a
|
||||||
|
// []byte of length keylen that can be used as cryptographic key. The key is
|
||||||
|
// derived based on the method described as PBKDF2 with the HMAC variant using
|
||||||
|
// the supplied hash function.
|
||||||
|
//
|
||||||
|
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
|
||||||
|
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
|
||||||
|
// doing:
|
||||||
|
//
|
||||||
|
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
|
||||||
|
//
|
||||||
|
// Remember to get a good random salt. At least 8 bytes is recommended by the
|
||||||
|
// RFC.
|
||||||
|
//
|
||||||
|
// Using a higher iteration count will increase the cost of an exhaustive
|
||||||
|
// search but will also make derivation proportionally slower.
|
||||||
|
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
||||||
|
prf := hmac.New(h, password)
|
||||||
|
hashLen := prf.Size()
|
||||||
|
numBlocks := (keyLen + hashLen - 1) / hashLen
|
||||||
|
|
||||||
|
var buf [4]byte
|
||||||
|
dk := make([]byte, 0, numBlocks*hashLen)
|
||||||
|
U := make([]byte, hashLen)
|
||||||
|
for block := 1; block <= numBlocks; block++ {
|
||||||
|
// N.B.: || means concatenation, ^ means XOR
|
||||||
|
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||||
|
// U_1 = PRF(password, salt || uint(i))
|
||||||
|
prf.Reset()
|
||||||
|
prf.Write(salt)
|
||||||
|
buf[0] = byte(block >> 24)
|
||||||
|
buf[1] = byte(block >> 16)
|
||||||
|
buf[2] = byte(block >> 8)
|
||||||
|
buf[3] = byte(block)
|
||||||
|
prf.Write(buf[:4])
|
||||||
|
dk = prf.Sum(dk)
|
||||||
|
T := dk[len(dk)-hashLen:]
|
||||||
|
copy(U, T)
|
||||||
|
|
||||||
|
// U_n = PRF(password, U_(n-1))
|
||||||
|
for n := 2; n <= iter; n++ {
|
||||||
|
prf.Reset()
|
||||||
|
prf.Write(U)
|
||||||
|
U = U[:0]
|
||||||
|
U = prf.Sum(U)
|
||||||
|
for x := range U {
|
||||||
|
T[x] ^= U[x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dk[:keyLen]
|
||||||
|
}
|
110
vendor/gopkg.in/square/go-jose.v2/asymmetric.go
generated
vendored
110
vendor/gopkg.in/square/go-jose.v2/asymmetric.go
generated
vendored
|
@ -28,7 +28,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
"gopkg.in/square/go-jose.v2/cipher"
|
"gopkg.in/square/go-jose.v2/cipher"
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A generic RSA-based encrypter/verifier
|
// A generic RSA-based encrypter/verifier
|
||||||
|
@ -46,6 +48,10 @@ type ecEncrypterVerifier struct {
|
||||||
publicKey *ecdsa.PublicKey
|
publicKey *ecdsa.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type edEncrypterVerifier struct {
|
||||||
|
publicKey ed25519.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
// A key generator for ECDH-ES
|
// A key generator for ECDH-ES
|
||||||
type ecKeyGenerator struct {
|
type ecKeyGenerator struct {
|
||||||
size int
|
size int
|
||||||
|
@ -58,6 +64,10 @@ type ecDecrypterSigner struct {
|
||||||
privateKey *ecdsa.PrivateKey
|
privateKey *ecdsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type edDecrypterSigner struct {
|
||||||
|
privateKey ed25519.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
// newRSARecipient creates recipientKeyInfo based on the given key.
|
// newRSARecipient creates recipientKeyInfo based on the given key.
|
||||||
func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
|
func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
|
||||||
// Verify that key management algorithm is supported by this encrypter
|
// Verify that key management algorithm is supported by this encrypter
|
||||||
|
@ -94,15 +104,34 @@ func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipi
|
||||||
|
|
||||||
return recipientSigInfo{
|
return recipientSigInfo{
|
||||||
sigAlg: sigAlg,
|
sigAlg: sigAlg,
|
||||||
publicKey: &JSONWebKey{
|
publicKey: staticPublicKey(&JSONWebKey{
|
||||||
Key: &privateKey.PublicKey,
|
Key: privateKey.Public(),
|
||||||
},
|
}),
|
||||||
signer: &rsaDecrypterSigner{
|
signer: &rsaDecrypterSigner{
|
||||||
privateKey: privateKey,
|
privateKey: privateKey,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) {
|
||||||
|
if sigAlg != EdDSA {
|
||||||
|
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
if privateKey == nil {
|
||||||
|
return recipientSigInfo{}, errors.New("invalid private key")
|
||||||
|
}
|
||||||
|
return recipientSigInfo{
|
||||||
|
sigAlg: sigAlg,
|
||||||
|
publicKey: staticPublicKey(&JSONWebKey{
|
||||||
|
Key: privateKey.Public(),
|
||||||
|
}),
|
||||||
|
signer: &edDecrypterSigner{
|
||||||
|
privateKey: privateKey,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// newECDHRecipient creates recipientKeyInfo based on the given key.
|
// newECDHRecipient creates recipientKeyInfo based on the given key.
|
||||||
func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
|
func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
|
||||||
// Verify that key management algorithm is supported by this encrypter
|
// Verify that key management algorithm is supported by this encrypter
|
||||||
|
@ -139,9 +168,9 @@ func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (re
|
||||||
|
|
||||||
return recipientSigInfo{
|
return recipientSigInfo{
|
||||||
sigAlg: sigAlg,
|
sigAlg: sigAlg,
|
||||||
publicKey: &JSONWebKey{
|
publicKey: staticPublicKey(&JSONWebKey{
|
||||||
Key: &privateKey.PublicKey,
|
Key: privateKey.Public(),
|
||||||
},
|
}),
|
||||||
signer: &ecDecrypterSigner{
|
signer: &ecDecrypterSigner{
|
||||||
privateKey: privateKey,
|
privateKey: privateKey,
|
||||||
},
|
},
|
||||||
|
@ -178,7 +207,7 @@ func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, e
|
||||||
|
|
||||||
// Decrypt the given payload and return the content encryption key.
|
// Decrypt the given payload and return the content encryption key.
|
||||||
func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||||
return ctx.decrypt(recipient.encryptedKey, KeyAlgorithm(headers.Alg), generator)
|
return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt the given payload. Based on the key encryption algorithm,
|
// Decrypt the given payload. Based on the key encryption algorithm,
|
||||||
|
@ -366,10 +395,15 @@ func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||||
|
|
||||||
out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
|
out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
|
||||||
|
|
||||||
headers := rawHeader{
|
b, err := json.Marshal(&JSONWebKey{
|
||||||
Epk: &JSONWebKey{
|
|
||||||
Key: &priv.PublicKey,
|
Key: &priv.PublicKey,
|
||||||
},
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := rawHeader{
|
||||||
|
headerEPK: makeRawMessage(b),
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, headers, nil
|
return out, headers, nil
|
||||||
|
@ -377,11 +411,15 @@ func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||||
|
|
||||||
// Decrypt the given payload and return the content encryption key.
|
// Decrypt the given payload and return the content encryption key.
|
||||||
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||||
if headers.Epk == nil {
|
epk, err := headers.getEPK()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("square/go-jose: invalid epk header")
|
||||||
|
}
|
||||||
|
if epk == nil {
|
||||||
return nil, errors.New("square/go-jose: missing epk header")
|
return nil, errors.New("square/go-jose: missing epk header")
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey, ok := headers.Epk.Key.(*ecdsa.PublicKey)
|
publicKey, ok := epk.Key.(*ecdsa.PublicKey)
|
||||||
if publicKey == nil || !ok {
|
if publicKey == nil || !ok {
|
||||||
return nil, errors.New("square/go-jose: invalid epk header")
|
return nil, errors.New("square/go-jose: invalid epk header")
|
||||||
}
|
}
|
||||||
|
@ -390,19 +428,26 @@ func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientI
|
||||||
return nil, errors.New("square/go-jose: invalid public key in epk header")
|
return nil, errors.New("square/go-jose: invalid public key in epk header")
|
||||||
}
|
}
|
||||||
|
|
||||||
apuData := headers.Apu.bytes()
|
apuData, err := headers.getAPU()
|
||||||
apvData := headers.Apv.bytes()
|
if err != nil {
|
||||||
|
return nil, errors.New("square/go-jose: invalid apu header")
|
||||||
|
}
|
||||||
|
apvData, err := headers.getAPV()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("square/go-jose: invalid apv header")
|
||||||
|
}
|
||||||
|
|
||||||
deriveKey := func(algID string, size int) []byte {
|
deriveKey := func(algID string, size int) []byte {
|
||||||
return josecipher.DeriveECDHES(algID, apuData, apvData, ctx.privateKey, publicKey, size)
|
return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
var keySize int
|
var keySize int
|
||||||
|
|
||||||
switch KeyAlgorithm(headers.Alg) {
|
algorithm := headers.getAlgorithm()
|
||||||
|
switch algorithm {
|
||||||
case ECDH_ES:
|
case ECDH_ES:
|
||||||
// ECDH-ES uses direct key agreement, no key unwrapping necessary.
|
// ECDH-ES uses direct key agreement, no key unwrapping necessary.
|
||||||
return deriveKey(string(headers.Enc), generator.keySize()), nil
|
return deriveKey(string(headers.getEncryption()), generator.keySize()), nil
|
||||||
case ECDH_ES_A128KW:
|
case ECDH_ES_A128KW:
|
||||||
keySize = 16
|
keySize = 16
|
||||||
case ECDH_ES_A192KW:
|
case ECDH_ES_A192KW:
|
||||||
|
@ -413,7 +458,7 @@ func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientI
|
||||||
return nil, ErrUnsupportedAlgorithm
|
return nil, ErrUnsupportedAlgorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
key := deriveKey(headers.Alg, keySize)
|
key := deriveKey(string(algorithm), keySize)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -422,6 +467,33 @@ func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientI
|
||||||
return josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
return josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||||
|
if alg != EdDSA {
|
||||||
|
return Signature{}, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := ctx.privateKey.Sign(randReader, payload, crypto.Hash(0))
|
||||||
|
if err != nil {
|
||||||
|
return Signature{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Signature{
|
||||||
|
Signature: sig,
|
||||||
|
protected: &rawHeader{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||||
|
if alg != EdDSA {
|
||||||
|
return ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
ok := ed25519.Verify(ctx.publicKey, payload, signature)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("square/go-jose: ed25519 signature failed to verify")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Sign the given payload
|
// Sign the given payload
|
||||||
func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||||
var expectedBitSize int
|
var expectedBitSize int
|
||||||
|
@ -460,7 +532,7 @@ func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm)
|
||||||
keyBytes++
|
keyBytes++
|
||||||
}
|
}
|
||||||
|
|
||||||
// We serialize the outpus (r and s) into big-endian byte arrays and pad
|
// We serialize the outputs (r and s) into big-endian byte arrays and pad
|
||||||
// them with zeros on the left to make sure the sizes work out. Both arrays
|
// them with zeros on the left to make sure the sizes work out. Both arrays
|
||||||
// must be keyBytes long, and the output must be 2*keyBytes long.
|
// must be keyBytes long, and the output must be 2*keyBytes long.
|
||||||
rBytes := r.Bytes()
|
rBytes := r.Bytes()
|
||||||
|
|
2
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go
generated
vendored
2
vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go
generated
vendored
|
@ -28,7 +28,7 @@ import (
|
||||||
// size may be at most 1<<16 bytes (64 KiB).
|
// 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 {
|
func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte {
|
||||||
if size > 1<<16 {
|
if size > 1<<16 {
|
||||||
panic("ECDH-ES output size too large, must be less than 1<<16")
|
panic("ECDH-ES output size too large, must be less than or equal to 1<<16")
|
||||||
}
|
}
|
||||||
|
|
||||||
// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
|
// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
|
||||||
|
|
136
vendor/gopkg.in/square/go-jose.v2/crypter.go
generated
vendored
136
vendor/gopkg.in/square/go-jose.v2/crypter.go
generated
vendored
|
@ -22,12 +22,15 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
||||||
type Encrypter interface {
|
type Encrypter interface {
|
||||||
Encrypt(plaintext []byte) (*JSONWebEncryption, error)
|
Encrypt(plaintext []byte) (*JSONWebEncryption, error)
|
||||||
EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error)
|
EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error)
|
||||||
|
Options() EncrypterOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// A generic content cipher
|
// A generic content cipher
|
||||||
|
@ -60,6 +63,7 @@ type genericEncrypter struct {
|
||||||
cipher contentCipher
|
cipher contentCipher
|
||||||
recipients []recipientKeyInfo
|
recipients []recipientKeyInfo
|
||||||
keyGenerator keyGenerator
|
keyGenerator keyGenerator
|
||||||
|
extraHeaders map[HeaderKey]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type recipientKeyInfo struct {
|
type recipientKeyInfo struct {
|
||||||
|
@ -71,13 +75,47 @@ type recipientKeyInfo struct {
|
||||||
// EncrypterOptions represents options that can be set on new encrypters.
|
// EncrypterOptions represents options that can be set on new encrypters.
|
||||||
type EncrypterOptions struct {
|
type EncrypterOptions struct {
|
||||||
Compression CompressionAlgorithm
|
Compression CompressionAlgorithm
|
||||||
|
|
||||||
|
// Optional map of additional keys to be inserted into the protected header
|
||||||
|
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||||
|
// additional values here. All values must be JSON-serializable.
|
||||||
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||||
|
// if necessary. It returns itself and so can be used in a fluent style.
|
||||||
|
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
||||||
|
if eo.ExtraHeaders == nil {
|
||||||
|
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||||
|
}
|
||||||
|
eo.ExtraHeaders[k] = v
|
||||||
|
return eo
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContentType adds a content type ("cty") header and returns the updated
|
||||||
|
// EncrypterOptions.
|
||||||
|
func (eo *EncrypterOptions) WithContentType(contentType ContentType) *EncrypterOptions {
|
||||||
|
return eo.WithHeader(HeaderContentType, contentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithType adds a type ("typ") header and returns the updated EncrypterOptions.
|
||||||
|
func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
|
||||||
|
return eo.WithHeader(HeaderType, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recipient represents an algorithm/key to encrypt messages to.
|
// Recipient represents an algorithm/key to encrypt messages to.
|
||||||
|
//
|
||||||
|
// PBES2Count and PBES2Salt correspond with the "p2c" and "p2s" headers used
|
||||||
|
// on the password-based encryption algorithms PBES2-HS256+A128KW,
|
||||||
|
// PBES2-HS384+A192KW, and PBES2-HS512+A256KW. If they are not provided a safe
|
||||||
|
// default of 100000 will be used for the count and a 128-bit random salt will
|
||||||
|
// be generated.
|
||||||
type Recipient struct {
|
type Recipient struct {
|
||||||
Algorithm KeyAlgorithm
|
Algorithm KeyAlgorithm
|
||||||
Key interface{}
|
Key interface{}
|
||||||
KeyID string
|
KeyID string
|
||||||
|
PBES2Count int
|
||||||
|
PBES2Salt []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncrypter creates an appropriate encrypter based on the key type
|
// NewEncrypter creates an appropriate encrypter based on the key type
|
||||||
|
@ -89,6 +127,7 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||||
}
|
}
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
encrypter.compressionAlg = opts.Compression
|
encrypter.compressionAlg = opts.Compression
|
||||||
|
encrypter.extraHeaders = opts.ExtraHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
if encrypter.cipher == nil {
|
if encrypter.cipher == nil {
|
||||||
|
@ -98,9 +137,10 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||||
var keyID string
|
var keyID string
|
||||||
var rawKey interface{}
|
var rawKey interface{}
|
||||||
switch encryptionKey := rcpt.Key.(type) {
|
switch encryptionKey := rcpt.Key.(type) {
|
||||||
|
case JSONWebKey:
|
||||||
|
keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
keyID = encryptionKey.KeyID
|
keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
|
||||||
rawKey = encryptionKey.Key
|
|
||||||
default:
|
default:
|
||||||
rawKey = encryptionKey
|
rawKey = encryptionKey
|
||||||
}
|
}
|
||||||
|
@ -196,6 +236,14 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
|
||||||
recipientInfo.keyID = recipient.KeyID
|
recipientInfo.keyID = recipient.KeyID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch recipient.Algorithm {
|
||||||
|
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||||
|
if sr, ok := recipientInfo.keyEncrypter.(*symmetricKeyCipher); ok {
|
||||||
|
sr.p2c = recipient.PBES2Count
|
||||||
|
sr.p2s = recipient.PBES2Salt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ctx.recipients = append(ctx.recipients, recipientInfo)
|
ctx.recipients = append(ctx.recipients, recipientInfo)
|
||||||
}
|
}
|
||||||
|
@ -210,6 +258,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
|
||||||
return newECDHRecipient(alg, encryptionKey)
|
return newECDHRecipient(alg, encryptionKey)
|
||||||
case []byte:
|
case []byte:
|
||||||
return newSymmetricRecipient(alg, encryptionKey)
|
return newSymmetricRecipient(alg, encryptionKey)
|
||||||
|
case string:
|
||||||
|
return newSymmetricRecipient(alg, []byte(encryptionKey))
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
||||||
recipient.keyID = encryptionKey.KeyID
|
recipient.keyID = encryptionKey.KeyID
|
||||||
|
@ -234,6 +284,12 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
|
||||||
return &symmetricKeyCipher{
|
return &symmetricKeyCipher{
|
||||||
key: decryptionKey,
|
key: decryptionKey,
|
||||||
}, nil
|
}, nil
|
||||||
|
case string:
|
||||||
|
return &symmetricKeyCipher{
|
||||||
|
key: []byte(decryptionKey),
|
||||||
|
}, nil
|
||||||
|
case JSONWebKey:
|
||||||
|
return newDecrypter(decryptionKey.Key)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
return newDecrypter(decryptionKey.Key)
|
return newDecrypter(decryptionKey.Key)
|
||||||
default:
|
default:
|
||||||
|
@ -251,9 +307,12 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||||
obj := &JSONWebEncryption{}
|
obj := &JSONWebEncryption{}
|
||||||
obj.aad = aad
|
obj.aad = aad
|
||||||
|
|
||||||
obj.protected = &rawHeader{
|
obj.protected = &rawHeader{}
|
||||||
Enc: ctx.contentAlg,
|
err := obj.protected.set(headerEncryption, ctx.contentAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.recipients = make([]recipientInfo, len(ctx.recipients))
|
obj.recipients = make([]recipientInfo, len(ctx.recipients))
|
||||||
|
|
||||||
if len(ctx.recipients) == 0 {
|
if len(ctx.recipients) == 0 {
|
||||||
|
@ -273,9 +332,16 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
recipient.header.Alg = string(info.keyAlg)
|
err = recipient.header.set(headerAlgorithm, info.keyAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if info.keyID != "" {
|
if info.keyID != "" {
|
||||||
recipient.header.Kid = info.keyID
|
err = recipient.header.set(headerKeyID, info.keyID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
obj.recipients[i] = recipient
|
obj.recipients[i] = recipient
|
||||||
}
|
}
|
||||||
|
@ -293,7 +359,18 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.protected.Zip = ctx.compressionAlg
|
err = obj.protected.set(headerCompression, ctx.compressionAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range ctx.extraHeaders {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
(*obj.protected)[k] = makeRawMessage(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
authData := obj.computeAuthData()
|
authData := obj.computeAuthData()
|
||||||
|
@ -309,6 +386,13 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *genericEncrypter) Options() EncrypterOptions {
|
||||||
|
return EncrypterOptions{
|
||||||
|
Compression: ctx.compressionAlg,
|
||||||
|
ExtraHeaders: ctx.extraHeaders,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Decrypt and validate the object and return the plaintext. Note that this
|
// Decrypt and validate the object and return the plaintext. Note that this
|
||||||
// function does not support multi-recipient, if you desire multi-recipient
|
// function does not support multi-recipient, if you desire multi-recipient
|
||||||
// decryption use DecryptMulti instead.
|
// decryption use DecryptMulti instead.
|
||||||
|
@ -319,7 +403,12 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||||
return nil, errors.New("square/go-jose: too many recipients in payload; expecting only one")
|
return nil, errors.New("square/go-jose: too many recipients in payload; expecting only one")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(headers.Crit) > 0 {
|
critical, err := headers.getCritical()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid crit header")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(critical) > 0 {
|
||||||
return nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
return nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,9 +417,9 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher := getContentCipher(headers.Enc)
|
cipher := getContentCipher(headers.getEncryption())
|
||||||
if cipher == nil {
|
if cipher == nil {
|
||||||
return nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(headers.Enc))
|
return nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
|
||||||
}
|
}
|
||||||
|
|
||||||
generator := randomKeyGenerator{
|
generator := randomKeyGenerator{
|
||||||
|
@ -360,8 +449,8 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "zip" header parameter may only be present in the protected header.
|
// The "zip" header parameter may only be present in the protected header.
|
||||||
if obj.protected.Zip != "" {
|
if comp := obj.protected.getCompression(); comp != "" {
|
||||||
plaintext, err = decompress(obj.protected.Zip, plaintext)
|
plaintext, err = decompress(comp, plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
return plaintext, err
|
return plaintext, err
|
||||||
|
@ -374,7 +463,12 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||||
globalHeaders := obj.mergedHeaders(nil)
|
globalHeaders := obj.mergedHeaders(nil)
|
||||||
|
|
||||||
if len(globalHeaders.Crit) > 0 {
|
critical, err := globalHeaders.getCritical()
|
||||||
|
if err != nil {
|
||||||
|
return -1, Header{}, nil, fmt.Errorf("square/go-jose: invalid crit header")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(critical) > 0 {
|
||||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,9 +477,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||||
return -1, Header{}, nil, err
|
return -1, Header{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher := getContentCipher(globalHeaders.Enc)
|
encryption := globalHeaders.getEncryption()
|
||||||
|
cipher := getContentCipher(encryption)
|
||||||
if cipher == nil {
|
if cipher == nil {
|
||||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(globalHeaders.Enc))
|
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(encryption))
|
||||||
}
|
}
|
||||||
|
|
||||||
generator := randomKeyGenerator{
|
generator := randomKeyGenerator{
|
||||||
|
@ -424,9 +519,14 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "zip" header parameter may only be present in the protected header.
|
// The "zip" header parameter may only be present in the protected header.
|
||||||
if obj.protected.Zip != "" {
|
if comp := obj.protected.getCompression(); comp != "" {
|
||||||
plaintext, err = decompress(obj.protected.Zip, plaintext)
|
plaintext, err = decompress(comp, plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
return index, headers.sanitized(), plaintext, err
|
sanitized, err := headers.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return -1, Header{}, nil, fmt.Errorf("square/go-jose: failed to sanitize header: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return index, sanitized, plaintext, err
|
||||||
}
|
}
|
||||||
|
|
9
vendor/gopkg.in/square/go-jose.v2/doc.go
generated
vendored
9
vendor/gopkg.in/square/go-jose.v2/doc.go
generated
vendored
|
@ -17,10 +17,11 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||||
and Encryption set of standards. For the moment, it mainly focuses on
|
and Encryption set of standards. It implements encryption and signing based on
|
||||||
encryption and signing based on the JSON Web Encryption and JSON Web Signature
|
the JSON Web Encryption and JSON Web Signature standards, with optional JSON
|
||||||
standards. The library supports both the compact and full serialization
|
Web Token support available in a sub-package. The library supports both the
|
||||||
formats, and has optional support for multiple recipients.
|
compact and full serialization formats, and has optional support for multiple
|
||||||
|
recipients.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package jose
|
package jose
|
||||||
|
|
3
vendor/gopkg.in/square/go-jose.v2/encoding.go
generated
vendored
3
vendor/gopkg.in/square/go-jose.v2/encoding.go
generated
vendored
|
@ -21,10 +21,11 @@ import (
|
||||||
"compress/flate"
|
"compress/flate"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stripWhitespaceRegex = regexp.MustCompile("\\s")
|
var stripWhitespaceRegex = regexp.MustCompile("\\s")
|
||||||
|
|
30
vendor/gopkg.in/square/go-jose.v2/jwe.go
generated
vendored
30
vendor/gopkg.in/square/go-jose.v2/jwe.go
generated
vendored
|
@ -18,9 +18,10 @@ package jose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
||||||
|
@ -85,10 +86,12 @@ func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader {
|
||||||
func (obj JSONWebEncryption) computeAuthData() []byte {
|
func (obj JSONWebEncryption) computeAuthData() []byte {
|
||||||
var protected string
|
var protected string
|
||||||
|
|
||||||
if obj.original != nil {
|
if obj.original != nil && obj.original.Protected != nil {
|
||||||
protected = obj.original.Protected.base64()
|
protected = obj.original.Protected.base64()
|
||||||
} else {
|
} else if obj.protected != nil {
|
||||||
protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected)))
|
protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected)))
|
||||||
|
} else {
|
||||||
|
protected = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
output := []byte(protected)
|
output := []byte(protected)
|
||||||
|
@ -129,10 +132,16 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is not a nonce in the unprotected headers
|
// Check that there is not a nonce in the unprotected headers
|
||||||
if (parsed.Unprotected != nil && parsed.Unprotected.Nonce != "") ||
|
if parsed.Unprotected != nil {
|
||||||
(parsed.Header != nil && parsed.Header.Nonce != "") {
|
if nonce := parsed.Unprotected.getNonce(); nonce != "" {
|
||||||
return nil, ErrUnprotectedNonce
|
return nil, ErrUnprotectedNonce
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if parsed.Header != nil {
|
||||||
|
if nonce := parsed.Header.getNonce(); nonce != "" {
|
||||||
|
return nil, ErrUnprotectedNonce
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||||
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
|
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
|
||||||
|
@ -143,7 +152,12 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
|
|
||||||
// Note: this must be called _after_ we parse the protected header,
|
// Note: this must be called _after_ we parse the protected header,
|
||||||
// otherwise fields from the protected header will not get picked up.
|
// otherwise fields from the protected header will not get picked up.
|
||||||
obj.Header = obj.mergedHeaders(nil).sanitized()
|
var err error
|
||||||
|
mergedHeaders := obj.mergedHeaders(nil)
|
||||||
|
obj.Header, err = mergedHeaders.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
if len(parsed.Recipients) == 0 {
|
if len(parsed.Recipients) == 0 {
|
||||||
obj.recipients = []recipientInfo{
|
obj.recipients = []recipientInfo{
|
||||||
|
@ -161,7 +175,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is not a nonce in the unprotected header
|
// Check that there is not a nonce in the unprotected header
|
||||||
if parsed.Recipients[r].Header != nil && parsed.Recipients[r].Header.Nonce != "" {
|
if parsed.Recipients[r].Header != nil && parsed.Recipients[r].Header.getNonce() != "" {
|
||||||
return nil, ErrUnprotectedNonce
|
return nil, ErrUnprotectedNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +186,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
|
|
||||||
for _, recipient := range obj.recipients {
|
for _, recipient := range obj.recipients {
|
||||||
headers := obj.mergedHeaders(&recipient)
|
headers := obj.mergedHeaders(&recipient)
|
||||||
if headers.Alg == "" || headers.Enc == "" {
|
if headers.getAlgorithm() == "" || headers.getEncryption() == "" {
|
||||||
return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers")
|
return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
119
vendor/gopkg.in/square/go-jose.v2/jwk.go
generated
vendored
119
vendor/gopkg.in/square/go-jose.v2/jwk.go
generated
vendored
|
@ -29,6 +29,8 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
|
||||||
"gopkg.in/square/go-jose.v2/json"
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -73,10 +75,14 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch key := k.Key.(type) {
|
switch key := k.Key.(type) {
|
||||||
|
case ed25519.PublicKey:
|
||||||
|
raw = fromEdPublicKey(key)
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
raw, err = fromEcPublicKey(key)
|
raw, err = fromEcPublicKey(key)
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
raw = fromRsaPublicKey(key)
|
raw = fromRsaPublicKey(key)
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
raw, err = fromEdPrivateKey(key)
|
||||||
case *ecdsa.PrivateKey:
|
case *ecdsa.PrivateKey:
|
||||||
raw, err = fromEcPrivateKey(key)
|
raw, err = fromEcPrivateKey(key)
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
|
@ -126,23 +132,26 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||||
}
|
}
|
||||||
case "oct":
|
case "oct":
|
||||||
key, err = raw.symmetricKey()
|
key, err = raw.symmetricKey()
|
||||||
|
case "OKP":
|
||||||
|
if raw.Crv == "Ed25519" && raw.X != nil {
|
||||||
|
if raw.D != nil {
|
||||||
|
key, err = raw.edPrivateKey()
|
||||||
|
} else {
|
||||||
|
key, err = raw.edPublicKey()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty)
|
err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use}
|
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use}
|
||||||
}
|
|
||||||
|
|
||||||
k.Certificates = make([]*x509.Certificate, len(raw.X5c))
|
k.Certificates, err = parseCertificateChain(raw.X5c)
|
||||||
for i, cert := range raw.X5c {
|
|
||||||
raw, err := base64.StdEncoding.DecodeString(cert)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to unmarshal x5c field: %s", err)
|
||||||
}
|
|
||||||
k.Certificates[i], err = x509.ParseCertificate(raw)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +180,7 @@ func (s *JSONWebKeySet) Key(kid string) []JSONWebKey {
|
||||||
|
|
||||||
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
|
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
|
||||||
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
|
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
|
||||||
|
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP",x":"%s"}`
|
||||||
|
|
||||||
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
||||||
coordLength := curveSize(curve)
|
coordLength := curveSize(curve)
|
||||||
|
@ -179,6 +189,10 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
|
||||||
|
return "", errors.New("square/go-jose: invalid elliptic key (too large)")
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(ecThumbprintTemplate, crv,
|
return fmt.Sprintf(ecThumbprintTemplate, crv,
|
||||||
newFixedSizeBuffer(x.Bytes(), coordLength).base64(),
|
newFixedSizeBuffer(x.Bytes(), coordLength).base64(),
|
||||||
newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil
|
newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil
|
||||||
|
@ -190,12 +204,23 @@ func rsaThumbprintInput(n *big.Int, e int) (string, error) {
|
||||||
newBuffer(n.Bytes()).base64()), nil
|
newBuffer(n.Bytes()).base64()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
|
||||||
|
crv := "Ed25519"
|
||||||
|
if len(ed) > 32 {
|
||||||
|
return "", errors.New("square/go-jose: invalid elliptic key (too large)")
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(edThumbprintTemplate, crv,
|
||||||
|
newFixedSizeBuffer(ed, 32).base64()), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Thumbprint computes the JWK Thumbprint of a key using the
|
// Thumbprint computes the JWK Thumbprint of a key using the
|
||||||
// indicated hash algorithm.
|
// indicated hash algorithm.
|
||||||
func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||||
var input string
|
var input string
|
||||||
var err error
|
var err error
|
||||||
switch key := k.Key.(type) {
|
switch key := k.Key.(type) {
|
||||||
|
case ed25519.PublicKey:
|
||||||
|
input, err = edThumbprintInput(key)
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
|
input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
|
||||||
case *ecdsa.PrivateKey:
|
case *ecdsa.PrivateKey:
|
||||||
|
@ -204,6 +229,8 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||||
input, err = rsaThumbprintInput(key.N, key.E)
|
input, err = rsaThumbprintInput(key.N, key.E)
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
input, err = rsaThumbprintInput(key.N, key.E)
|
input, err = rsaThumbprintInput(key.N, key.E)
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
input, err = edThumbprintInput(ed25519.PublicKey(key[0:32]))
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||||
}
|
}
|
||||||
|
@ -220,13 +247,32 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||||
// IsPublic returns true if the JWK represents a public key (not symmetric, not private).
|
// IsPublic returns true if the JWK represents a public key (not symmetric, not private).
|
||||||
func (k *JSONWebKey) IsPublic() bool {
|
func (k *JSONWebKey) IsPublic() bool {
|
||||||
switch k.Key.(type) {
|
switch k.Key.(type) {
|
||||||
case *ecdsa.PublicKey, *rsa.PublicKey:
|
case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public creates JSONWebKey with corresponding publik key if JWK represents asymmetric private key.
|
||||||
|
func (k *JSONWebKey) Public() JSONWebKey {
|
||||||
|
if k.IsPublic() {
|
||||||
|
return *k
|
||||||
|
}
|
||||||
|
ret := *k
|
||||||
|
switch key := k.Key.(type) {
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
ret.Key = key.Public()
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
ret.Key = key.Public()
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
ret.Key = key.Public()
|
||||||
|
default:
|
||||||
|
return JSONWebKey{} // returning invalid key
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// Valid checks that the key contains the expected parameters.
|
// Valid checks that the key contains the expected parameters.
|
||||||
func (k *JSONWebKey) Valid() bool {
|
func (k *JSONWebKey) Valid() bool {
|
||||||
if k.Key == nil {
|
if k.Key == nil {
|
||||||
|
@ -249,6 +295,14 @@ func (k *JSONWebKey) Valid() bool {
|
||||||
if key.N == nil || key.E == 0 || key.D == nil || len(key.Primes) < 2 {
|
if key.N == nil || key.E == 0 || key.D == nil || len(key.Primes) < 2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case ed25519.PublicKey:
|
||||||
|
if len(key) != 32 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
if len(key) != 64 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -266,6 +320,14 @@ func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fromEdPublicKey(pub ed25519.PublicKey) *rawJSONWebKey {
|
||||||
|
return &rawJSONWebKey{
|
||||||
|
Kty: "OKP",
|
||||||
|
Crv: "Ed25519",
|
||||||
|
X: newBuffer(pub),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey {
|
func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey {
|
||||||
return &rawJSONWebKey{
|
return &rawJSONWebKey{
|
||||||
Kty: "RSA",
|
Kty: "RSA",
|
||||||
|
@ -334,6 +396,36 @@ func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
|
||||||
|
var missing []string
|
||||||
|
switch {
|
||||||
|
case key.D == nil:
|
||||||
|
missing = append(missing, "D")
|
||||||
|
case key.X == nil:
|
||||||
|
missing = append(missing, "X")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missing) > 0 {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey := make([]byte, ed25519.PrivateKeySize)
|
||||||
|
copy(privateKey[0:32], key.X.bytes())
|
||||||
|
copy(privateKey[32:], key.D.bytes())
|
||||||
|
rv := ed25519.PrivateKey(privateKey)
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
|
||||||
|
if key.X == nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid Ed key, missing x value")
|
||||||
|
}
|
||||||
|
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||||
|
copy(publicKey[0:32], key.X.bytes())
|
||||||
|
rv := ed25519.PublicKey(publicKey)
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||||
var missing []string
|
var missing []string
|
||||||
switch {
|
switch {
|
||||||
|
@ -379,6 +471,13 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||||
return rv, err
|
return rv, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fromEdPrivateKey(ed ed25519.PrivateKey) (*rawJSONWebKey, error) {
|
||||||
|
raw := fromEdPublicKey(ed25519.PublicKey(ed[0:32]))
|
||||||
|
|
||||||
|
raw.D = newBuffer(ed[32:])
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
|
||||||
func fromRsaPrivateKey(rsa *rsa.PrivateKey) (*rawJSONWebKey, error) {
|
func fromRsaPrivateKey(rsa *rsa.PrivateKey) (*rawJSONWebKey, error) {
|
||||||
if len(rsa.Primes) != 2 {
|
if len(rsa.Primes) != 2 {
|
||||||
return nil, ErrUnsupportedKeyType
|
return nil, ErrUnsupportedKeyType
|
||||||
|
|
62
vendor/gopkg.in/square/go-jose.v2/jws.go
generated
vendored
62
vendor/gopkg.in/square/go-jose.v2/jws.go
generated
vendored
|
@ -52,9 +52,20 @@ type JSONWebSignature struct {
|
||||||
|
|
||||||
// Signature represents a single signature over the JWS payload and protected header.
|
// Signature represents a single signature over the JWS payload and protected header.
|
||||||
type Signature struct {
|
type Signature struct {
|
||||||
// Header fields, such as the signature algorithm
|
// Merged header fields. Contains both protected and unprotected header
|
||||||
|
// values. Prefer using Protected and Unprotected fields instead of this.
|
||||||
|
// Values in this header may or may not have been signed and in general
|
||||||
|
// should not be trusted.
|
||||||
Header Header
|
Header Header
|
||||||
|
|
||||||
|
// Protected header. Values in this header were signed and
|
||||||
|
// will be verified as part of the signature verification process.
|
||||||
|
Protected Header
|
||||||
|
|
||||||
|
// Unprotected header. Values in this header were not signed
|
||||||
|
// and in general should not be trusted.
|
||||||
|
Unprotected Header
|
||||||
|
|
||||||
// The actual signature value
|
// The actual signature value
|
||||||
Signature []byte
|
Signature []byte
|
||||||
|
|
||||||
|
@ -82,7 +93,7 @@ func (sig Signature) mergedHeaders() rawHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute data to be signed
|
// Compute data to be signed
|
||||||
func (obj JSONWebSignature) computeAuthData(signature *Signature) []byte {
|
func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) []byte {
|
||||||
var serializedProtected string
|
var serializedProtected string
|
||||||
|
|
||||||
if signature.original != nil && signature.original.Protected != nil {
|
if signature.original != nil && signature.original.Protected != nil {
|
||||||
|
@ -95,7 +106,7 @@ func (obj JSONWebSignature) computeAuthData(signature *Signature) []byte {
|
||||||
|
|
||||||
return []byte(fmt.Sprintf("%s.%s",
|
return []byte(fmt.Sprintf("%s.%s",
|
||||||
serializedProtected,
|
serializedProtected,
|
||||||
base64.RawURLEncoding.EncodeToString(obj.payload)))
|
base64.RawURLEncoding.EncodeToString(payload)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSignedFull parses a message in full format.
|
// parseSignedFull parses a message in full format.
|
||||||
|
@ -132,7 +143,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is not a nonce in the unprotected header
|
// Check that there is not a nonce in the unprotected header
|
||||||
if parsed.Header != nil && parsed.Header.Nonce != "" {
|
if parsed.Header != nil && parsed.Header.getNonce() != "" {
|
||||||
return nil, ErrUnprotectedNonce
|
return nil, ErrUnprotectedNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +164,25 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
Signature: parsed.Signature,
|
Signature: parsed.Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
signature.Header = signature.mergedHeaders().sanitized()
|
var err error
|
||||||
|
signature.Header, err = signature.mergedHeaders().sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if signature.header != nil {
|
||||||
|
signature.Unprotected, err = signature.header.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if signature.protected != nil {
|
||||||
|
signature.Protected, err = signature.protected.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||||
jwk := signature.Header.JSONWebKey
|
jwk := signature.Header.JSONWebKey
|
||||||
|
@ -174,11 +203,30 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is not a nonce in the unprotected header
|
// Check that there is not a nonce in the unprotected header
|
||||||
if sig.Header != nil && sig.Header.Nonce != "" {
|
if sig.Header != nil && sig.Header.getNonce() != "" {
|
||||||
return nil, ErrUnprotectedNonce
|
return nil, ErrUnprotectedNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized()
|
var err error
|
||||||
|
obj.Signatures[i].Header, err = obj.Signatures[i].mergedHeaders().sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Signatures[i].header != nil {
|
||||||
|
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Signatures[i].protected != nil {
|
||||||
|
obj.Signatures[i].Protected, err = obj.Signatures[i].protected.sanitized()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj.Signatures[i].Signature = sig.Signature.bytes()
|
obj.Signatures[i].Signature = sig.Signature.bytes()
|
||||||
|
|
||||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||||
|
|
83
vendor/gopkg.in/square/go-jose.v2/opaque.go
generated
vendored
Normal file
83
vendor/gopkg.in/square/go-jose.v2/opaque.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*-
|
||||||
|
* Copyright 2018 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
|
||||||
|
|
||||||
|
// OpaqueSigner is an interface that supports signing payloads with opaque
|
||||||
|
// private key(s). Private key operations preformed by implementors may, for
|
||||||
|
// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
|
||||||
|
// transparently to the user of this interface.
|
||||||
|
type OpaqueSigner interface {
|
||||||
|
// Public returns the public key of the current signing key.
|
||||||
|
Public() *JSONWebKey
|
||||||
|
// Algs returns a list of supported signing algorithms.
|
||||||
|
Algs() []SignatureAlgorithm
|
||||||
|
// SignPayload signs a payload with the current signing key using the given
|
||||||
|
// algorithm.
|
||||||
|
SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type opaqueSigner struct {
|
||||||
|
signer OpaqueSigner
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) {
|
||||||
|
var algSupported bool
|
||||||
|
for _, salg := range signer.Algs() {
|
||||||
|
if alg == salg {
|
||||||
|
algSupported = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !algSupported {
|
||||||
|
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipientSigInfo{
|
||||||
|
sigAlg: alg,
|
||||||
|
publicKey: signer.Public,
|
||||||
|
signer: &opaqueSigner{
|
||||||
|
signer: signer,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||||
|
out, err := o.signer.SignPayload(payload, alg)
|
||||||
|
if err != nil {
|
||||||
|
return Signature{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Signature{
|
||||||
|
Signature: out,
|
||||||
|
protected: &rawHeader{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpaqueVerifier is an interface that supports verifying payloads with opaque
|
||||||
|
// public key(s). An OpaqueSigner may rotate signing keys transparently to the
|
||||||
|
// user of this interface.
|
||||||
|
type OpaqueVerifier interface {
|
||||||
|
VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type opaqueVerifier struct {
|
||||||
|
verifier OpaqueVerifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||||
|
return o.verifier.VerifyPayload(payload, signature, alg)
|
||||||
|
}
|
386
vendor/gopkg.in/square/go-jose.v2/shared.go
generated
vendored
386
vendor/gopkg.in/square/go-jose.v2/shared.go
generated
vendored
|
@ -18,8 +18,12 @@ package jose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyAlgorithm represents a key management algorithm.
|
// KeyAlgorithm represents a key management algorithm.
|
||||||
|
@ -34,6 +38,9 @@ type ContentEncryption string
|
||||||
// CompressionAlgorithm represents an algorithm used for plaintext compression.
|
// CompressionAlgorithm represents an algorithm used for plaintext compression.
|
||||||
type CompressionAlgorithm string
|
type CompressionAlgorithm string
|
||||||
|
|
||||||
|
// ContentType represents type of the contained data.
|
||||||
|
type ContentType string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrCryptoFailure represents an error in cryptographic primitive. This
|
// ErrCryptoFailure represents an error in cryptographic primitive. This
|
||||||
// occurs when, for example, a message had an invalid authentication tag or
|
// occurs when, for example, a message had an invalid authentication tag or
|
||||||
|
@ -63,6 +70,7 @@ var (
|
||||||
|
|
||||||
// Key management algorithms
|
// Key management algorithms
|
||||||
const (
|
const (
|
||||||
|
ED25519 = KeyAlgorithm("ED25519")
|
||||||
RSA1_5 = KeyAlgorithm("RSA1_5") // RSA-PKCS1v1.5
|
RSA1_5 = KeyAlgorithm("RSA1_5") // RSA-PKCS1v1.5
|
||||||
RSA_OAEP = KeyAlgorithm("RSA-OAEP") // RSA-OAEP-SHA1
|
RSA_OAEP = KeyAlgorithm("RSA-OAEP") // RSA-OAEP-SHA1
|
||||||
RSA_OAEP_256 = KeyAlgorithm("RSA-OAEP-256") // RSA-OAEP-SHA256
|
RSA_OAEP_256 = KeyAlgorithm("RSA-OAEP-256") // RSA-OAEP-SHA256
|
||||||
|
@ -84,6 +92,7 @@ const (
|
||||||
|
|
||||||
// Signature algorithms
|
// Signature algorithms
|
||||||
const (
|
const (
|
||||||
|
EdDSA = SignatureAlgorithm("EdDSA")
|
||||||
HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256
|
HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256
|
||||||
HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384
|
HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384
|
||||||
HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512
|
HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512
|
||||||
|
@ -114,21 +123,44 @@ const (
|
||||||
DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
|
DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A key in the protected header of a JWS object. Use of the Header...
|
||||||
|
// constants is preferred to enhance type safety.
|
||||||
|
type HeaderKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
HeaderType HeaderKey = "typ" // string
|
||||||
|
HeaderContentType = "cty" // string
|
||||||
|
|
||||||
|
// These are set by go-jose and shouldn't need to be set by consumers of the
|
||||||
|
// library.
|
||||||
|
headerAlgorithm = "alg" // string
|
||||||
|
headerEncryption = "enc" // ContentEncryption
|
||||||
|
headerCompression = "zip" // CompressionAlgorithm
|
||||||
|
headerCritical = "crit" // []string
|
||||||
|
|
||||||
|
headerAPU = "apu" // *byteBuffer
|
||||||
|
headerAPV = "apv" // *byteBuffer
|
||||||
|
headerEPK = "epk" // *JSONWebKey
|
||||||
|
headerIV = "iv" // *byteBuffer
|
||||||
|
headerTag = "tag" // *byteBuffer
|
||||||
|
headerX5c = "x5c" // []*x509.Certificate
|
||||||
|
|
||||||
|
headerJWK = "jwk" // *JSONWebKey
|
||||||
|
headerKeyID = "kid" // string
|
||||||
|
headerNonce = "nonce" // string
|
||||||
|
|
||||||
|
headerP2C = "p2c" // *byteBuffer (int)
|
||||||
|
headerP2S = "p2s" // *byteBuffer ([]byte)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
|
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
|
||||||
type rawHeader struct {
|
//
|
||||||
Alg string `json:"alg,omitempty"`
|
// The decoding of the constituent items is deferred because we want to marshal
|
||||||
Enc ContentEncryption `json:"enc,omitempty"`
|
// some members into particular structs rather than generic maps, but at the
|
||||||
Zip CompressionAlgorithm `json:"zip,omitempty"`
|
// same time we need to receive any extra fields unhandled by this library to
|
||||||
Crit []string `json:"crit,omitempty"`
|
// pass through to consuming code in case it wants to examine them.
|
||||||
Apu *byteBuffer `json:"apu,omitempty"`
|
type rawHeader map[HeaderKey]*json.RawMessage
|
||||||
Apv *byteBuffer `json:"apv,omitempty"`
|
|
||||||
Epk *JSONWebKey `json:"epk,omitempty"`
|
|
||||||
Iv *byteBuffer `json:"iv,omitempty"`
|
|
||||||
Tag *byteBuffer `json:"tag,omitempty"`
|
|
||||||
Jwk *JSONWebKey `json:"jwk,omitempty"`
|
|
||||||
Kid string `json:"kid,omitempty"`
|
|
||||||
Nonce string `json:"nonce,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header represents the read-only JOSE header for JWE/JWS objects.
|
// Header represents the read-only JOSE header for JWE/JWS objects.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
|
@ -136,62 +168,295 @@ type Header struct {
|
||||||
JSONWebKey *JSONWebKey
|
JSONWebKey *JSONWebKey
|
||||||
Algorithm string
|
Algorithm string
|
||||||
Nonce string
|
Nonce string
|
||||||
|
|
||||||
|
// Unverified certificate chain parsed from x5c header.
|
||||||
|
certificates []*x509.Certificate
|
||||||
|
|
||||||
|
// Any headers not recognised above get unmarshaled
|
||||||
|
// from JSON in a generic manner and placed in this map.
|
||||||
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Certificates verifies & returns the certificate chain present
|
||||||
|
// in the x5c header field of a message, if one was present. Returns
|
||||||
|
// an error if there was no x5c header present or the chain could
|
||||||
|
// not be validated with the given verify options.
|
||||||
|
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
|
||||||
|
if len(h.certificates) == 0 {
|
||||||
|
return nil, errors.New("square/go-jose: no x5c header present in message")
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf := h.certificates[0]
|
||||||
|
if opts.Intermediates == nil {
|
||||||
|
opts.Intermediates = x509.NewCertPool()
|
||||||
|
for _, intermediate := range h.certificates[1:] {
|
||||||
|
opts.Intermediates.AddCert(intermediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaf.Verify(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (parsed rawHeader) set(k HeaderKey, v interface{}) error {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed[k] = makeRawMessage(b)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getString gets a string from the raw JSON, defaulting to "".
|
||||||
|
func (parsed rawHeader) getString(k HeaderKey) string {
|
||||||
|
v, ok := parsed[k]
|
||||||
|
if !ok || v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var s string
|
||||||
|
err := json.Unmarshal(*v, &s)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// getByteBuffer gets a byte buffer from the raw JSON. Returns (nil, nil) if
|
||||||
|
// not specified.
|
||||||
|
func (parsed rawHeader) getByteBuffer(k HeaderKey) (*byteBuffer, error) {
|
||||||
|
v := parsed[k]
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var bb *byteBuffer
|
||||||
|
err := json.Unmarshal(*v, &bb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getAlgorithm extracts parsed "alg" from the raw JSON as a KeyAlgorithm.
|
||||||
|
func (parsed rawHeader) getAlgorithm() KeyAlgorithm {
|
||||||
|
return KeyAlgorithm(parsed.getString(headerAlgorithm))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSignatureAlgorithm extracts parsed "alg" from the raw JSON as a SignatureAlgorithm.
|
||||||
|
func (parsed rawHeader) getSignatureAlgorithm() SignatureAlgorithm {
|
||||||
|
return SignatureAlgorithm(parsed.getString(headerAlgorithm))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getEncryption extracts parsed "enc" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getEncryption() ContentEncryption {
|
||||||
|
return ContentEncryption(parsed.getString(headerEncryption))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCompression extracts parsed "zip" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getCompression() CompressionAlgorithm {
|
||||||
|
return CompressionAlgorithm(parsed.getString(headerCompression))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (parsed rawHeader) getNonce() string {
|
||||||
|
return parsed.getString(headerNonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getEPK extracts parsed "epk" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
|
||||||
|
v := parsed[headerEPK]
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var epk *JSONWebKey
|
||||||
|
err := json.Unmarshal(*v, &epk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return epk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getAPU extracts parsed "apu" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getAPU() (*byteBuffer, error) {
|
||||||
|
return parsed.getByteBuffer(headerAPU)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getAPV extracts parsed "apv" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getAPV() (*byteBuffer, error) {
|
||||||
|
return parsed.getByteBuffer(headerAPV)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIV extracts parsed "iv" frpom the raw JSON.
|
||||||
|
func (parsed rawHeader) getIV() (*byteBuffer, error) {
|
||||||
|
return parsed.getByteBuffer(headerIV)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTag extracts parsed "tag" frpom the raw JSON.
|
||||||
|
func (parsed rawHeader) getTag() (*byteBuffer, error) {
|
||||||
|
return parsed.getByteBuffer(headerTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getJWK extracts parsed "jwk" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getJWK() (*JSONWebKey, error) {
|
||||||
|
v := parsed[headerJWK]
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var jwk *JSONWebKey
|
||||||
|
err := json.Unmarshal(*v, &jwk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return jwk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCritical extracts parsed "crit" from the raw JSON. If omitted, it
|
||||||
|
// returns an empty slice.
|
||||||
|
func (parsed rawHeader) getCritical() ([]string, error) {
|
||||||
|
v := parsed[headerCritical]
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var q []string
|
||||||
|
err := json.Unmarshal(*v, &q)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return q, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getS2C extracts parsed "p2c" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getP2C() (int, error) {
|
||||||
|
v := parsed[headerP2C]
|
||||||
|
if v == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var p2c int
|
||||||
|
err := json.Unmarshal(*v, &p2c)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return p2c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getS2S extracts parsed "p2s" from the raw JSON.
|
||||||
|
func (parsed rawHeader) getP2S() (*byteBuffer, error) {
|
||||||
|
return parsed.getByteBuffer(headerP2S)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitized produces a cleaned-up header object from the raw JSON.
|
// sanitized produces a cleaned-up header object from the raw JSON.
|
||||||
func (parsed rawHeader) sanitized() Header {
|
func (parsed rawHeader) sanitized() (h Header, err error) {
|
||||||
return Header{
|
for k, v := range parsed {
|
||||||
KeyID: parsed.Kid,
|
if v == nil {
|
||||||
JSONWebKey: parsed.Jwk,
|
continue
|
||||||
Algorithm: parsed.Alg,
|
|
||||||
Nonce: parsed.Nonce,
|
|
||||||
}
|
}
|
||||||
|
switch k {
|
||||||
|
case headerJWK:
|
||||||
|
var jwk *JSONWebKey
|
||||||
|
err = json.Unmarshal(*v, &jwk)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.JSONWebKey = jwk
|
||||||
|
case headerKeyID:
|
||||||
|
var s string
|
||||||
|
err = json.Unmarshal(*v, &s)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal key ID: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.KeyID = s
|
||||||
|
case headerAlgorithm:
|
||||||
|
var s string
|
||||||
|
err = json.Unmarshal(*v, &s)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal algorithm: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Algorithm = s
|
||||||
|
case headerNonce:
|
||||||
|
var s string
|
||||||
|
err = json.Unmarshal(*v, &s)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal nonce: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Nonce = s
|
||||||
|
case headerX5c:
|
||||||
|
c := []string{}
|
||||||
|
err = json.Unmarshal(*v, &c)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.certificates, err = parseCertificateChain(c)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if h.ExtraHeaders == nil {
|
||||||
|
h.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||||
|
}
|
||||||
|
var v2 interface{}
|
||||||
|
err = json.Unmarshal(*v, &v2)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to unmarshal value: %v: %#v", err, string(*v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.ExtraHeaders[k] = v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
|
||||||
|
out := make([]*x509.Certificate, len(chain))
|
||||||
|
for i, cert := range chain {
|
||||||
|
raw, err := base64.StdEncoding.DecodeString(cert)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i], err = x509.ParseCertificate(raw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst rawHeader) isSet(k HeaderKey) bool {
|
||||||
|
dvr := dst[k]
|
||||||
|
if dvr == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var dv interface{}
|
||||||
|
err := json.Unmarshal(*dvr, &dv)
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if dvStr, ok := dv.(string); ok {
|
||||||
|
return dvStr != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge headers from src into dst, giving precedence to headers from l.
|
// Merge headers from src into dst, giving precedence to headers from l.
|
||||||
func (dst *rawHeader) merge(src *rawHeader) {
|
func (dst rawHeader) merge(src *rawHeader) {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if dst.Alg == "" {
|
for k, v := range *src {
|
||||||
dst.Alg = src.Alg
|
if dst.isSet(k) {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if dst.Enc == "" {
|
|
||||||
dst.Enc = src.Enc
|
dst[k] = v
|
||||||
}
|
|
||||||
if dst.Zip == "" {
|
|
||||||
dst.Zip = src.Zip
|
|
||||||
}
|
|
||||||
if dst.Crit == nil {
|
|
||||||
dst.Crit = src.Crit
|
|
||||||
}
|
|
||||||
if dst.Crit == nil {
|
|
||||||
dst.Crit = src.Crit
|
|
||||||
}
|
|
||||||
if dst.Apu == nil {
|
|
||||||
dst.Apu = src.Apu
|
|
||||||
}
|
|
||||||
if dst.Apv == nil {
|
|
||||||
dst.Apv = src.Apv
|
|
||||||
}
|
|
||||||
if dst.Epk == nil {
|
|
||||||
dst.Epk = src.Epk
|
|
||||||
}
|
|
||||||
if dst.Iv == nil {
|
|
||||||
dst.Iv = src.Iv
|
|
||||||
}
|
|
||||||
if dst.Tag == nil {
|
|
||||||
dst.Tag = src.Tag
|
|
||||||
}
|
|
||||||
if dst.Kid == "" {
|
|
||||||
dst.Kid = src.Kid
|
|
||||||
}
|
|
||||||
if dst.Jwk == nil {
|
|
||||||
dst.Jwk = src.Jwk
|
|
||||||
}
|
|
||||||
if dst.Nonce == "" {
|
|
||||||
dst.Nonce = src.Nonce
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,3 +487,8 @@ func curveSize(crv elliptic.Curve) int {
|
||||||
|
|
||||||
return div + 1
|
return div + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeRawMessage(b []byte) *json.RawMessage {
|
||||||
|
rm := json.RawMessage(b)
|
||||||
|
return &rm
|
||||||
|
}
|
||||||
|
|
199
vendor/gopkg.in/square/go-jose.v2/signing.go
generated
vendored
199
vendor/gopkg.in/square/go-jose.v2/signing.go
generated
vendored
|
@ -22,6 +22,10 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NonceSource represents a source of random nonces to go into JWS objects
|
// NonceSource represents a source of random nonces to go into JWS objects
|
||||||
|
@ -32,6 +36,7 @@ type NonceSource interface {
|
||||||
// Signer represents a signer which takes a payload and produces a signed JWS object.
|
// Signer represents a signer which takes a payload and produces a signed JWS object.
|
||||||
type Signer interface {
|
type Signer interface {
|
||||||
Sign(payload []byte) (*JSONWebSignature, error)
|
Sign(payload []byte) (*JSONWebSignature, error)
|
||||||
|
Options() SignerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// SigningKey represents an algorithm/key used to sign a message.
|
// SigningKey represents an algorithm/key used to sign a message.
|
||||||
|
@ -44,6 +49,32 @@ type SigningKey struct {
|
||||||
type SignerOptions struct {
|
type SignerOptions struct {
|
||||||
NonceSource NonceSource
|
NonceSource NonceSource
|
||||||
EmbedJWK bool
|
EmbedJWK bool
|
||||||
|
|
||||||
|
// Optional map of additional keys to be inserted into the protected header
|
||||||
|
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||||
|
// additional values here. All values must be JSON-serializable.
|
||||||
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||||
|
// if necessary. It returns itself and so can be used in a fluent style.
|
||||||
|
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
||||||
|
if so.ExtraHeaders == nil {
|
||||||
|
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||||
|
}
|
||||||
|
so.ExtraHeaders[k] = v
|
||||||
|
return so
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContentType adds a content type ("cty") header and returns the updated
|
||||||
|
// SignerOptions.
|
||||||
|
func (so *SignerOptions) WithContentType(contentType ContentType) *SignerOptions {
|
||||||
|
return so.WithHeader(HeaderContentType, contentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithType adds a type ("typ") header and returns the updated SignerOptions.
|
||||||
|
func (so *SignerOptions) WithType(typ ContentType) *SignerOptions {
|
||||||
|
return so.WithHeader(HeaderType, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
type payloadSigner interface {
|
type payloadSigner interface {
|
||||||
|
@ -58,14 +89,21 @@ type genericSigner struct {
|
||||||
recipients []recipientSigInfo
|
recipients []recipientSigInfo
|
||||||
nonceSource NonceSource
|
nonceSource NonceSource
|
||||||
embedJWK bool
|
embedJWK bool
|
||||||
|
extraHeaders map[HeaderKey]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type recipientSigInfo struct {
|
type recipientSigInfo struct {
|
||||||
sigAlg SignatureAlgorithm
|
sigAlg SignatureAlgorithm
|
||||||
publicKey *JSONWebKey
|
publicKey func() *JSONWebKey
|
||||||
signer payloadSigner
|
signer payloadSigner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func staticPublicKey(jwk *JSONWebKey) func() *JSONWebKey {
|
||||||
|
return func() *JSONWebKey {
|
||||||
|
return jwk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewSigner creates an appropriate signer based on the key type
|
// NewSigner creates an appropriate signer based on the key type
|
||||||
func NewSigner(sig SigningKey, opts *SignerOptions) (Signer, error) {
|
func NewSigner(sig SigningKey, opts *SignerOptions) (Signer, error) {
|
||||||
return NewMultiSigner([]SigningKey{sig}, opts)
|
return NewMultiSigner([]SigningKey{sig}, opts)
|
||||||
|
@ -78,6 +116,7 @@ func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
signer.nonceSource = opts.NonceSource
|
signer.nonceSource = opts.NonceSource
|
||||||
signer.embedJWK = opts.EmbedJWK
|
signer.embedJWK = opts.EmbedJWK
|
||||||
|
signer.extraHeaders = opts.ExtraHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sig := range sigs {
|
for _, sig := range sigs {
|
||||||
|
@ -93,6 +132,10 @@ func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
|
||||||
// newVerifier creates a verifier based on the key type
|
// newVerifier creates a verifier based on the key type
|
||||||
func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||||
switch verificationKey := verificationKey.(type) {
|
switch verificationKey := verificationKey.(type) {
|
||||||
|
case ed25519.PublicKey:
|
||||||
|
return &edEncrypterVerifier{
|
||||||
|
publicKey: verificationKey,
|
||||||
|
}, nil
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
return &rsaEncrypterVerifier{
|
return &rsaEncrypterVerifier{
|
||||||
publicKey: verificationKey,
|
publicKey: verificationKey,
|
||||||
|
@ -105,11 +148,15 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||||
return &symmetricMac{
|
return &symmetricMac{
|
||||||
key: verificationKey,
|
key: verificationKey,
|
||||||
}, nil
|
}, nil
|
||||||
|
case JSONWebKey:
|
||||||
|
return newVerifier(verificationKey.Key)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
return newVerifier(verificationKey.Key)
|
return newVerifier(verificationKey.Key)
|
||||||
default:
|
|
||||||
return nil, ErrUnsupportedKeyType
|
|
||||||
}
|
}
|
||||||
|
if ov, ok := verificationKey.(OpaqueVerifier); ok {
|
||||||
|
return &opaqueVerifier{verifier: ov}, nil
|
||||||
|
}
|
||||||
|
return nil, ErrUnsupportedKeyType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
||||||
|
@ -124,22 +171,44 @@ func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interf
|
||||||
|
|
||||||
func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) {
|
func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) {
|
||||||
switch signingKey := signingKey.(type) {
|
switch signingKey := signingKey.(type) {
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
return newEd25519Signer(alg, signingKey)
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
return newRSASigner(alg, signingKey)
|
return newRSASigner(alg, signingKey)
|
||||||
case *ecdsa.PrivateKey:
|
case *ecdsa.PrivateKey:
|
||||||
return newECDSASigner(alg, signingKey)
|
return newECDSASigner(alg, signingKey)
|
||||||
case []byte:
|
case []byte:
|
||||||
return newSymmetricSigner(alg, signingKey)
|
return newSymmetricSigner(alg, signingKey)
|
||||||
|
case JSONWebKey:
|
||||||
|
return newJWKSigner(alg, signingKey)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
|
return newJWKSigner(alg, *signingKey)
|
||||||
|
}
|
||||||
|
if signer, ok := signingKey.(OpaqueSigner); ok {
|
||||||
|
return newOpaqueSigner(alg, signer)
|
||||||
|
}
|
||||||
|
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||||
|
}
|
||||||
|
|
||||||
|
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
||||||
recipient, err := makeJWSRecipient(alg, signingKey.Key)
|
recipient, err := makeJWSRecipient(alg, signingKey.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return recipientSigInfo{}, err
|
return recipientSigInfo{}, err
|
||||||
}
|
}
|
||||||
recipient.publicKey.KeyID = signingKey.KeyID
|
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||||
return recipient, nil
|
// recipient.publicKey is a JWK synthesized for embedding when recipientSigInfo
|
||||||
default:
|
// was created for the inner key (such as a RSA or ECDSA public key). It contains
|
||||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
// the pub key for embedding, but doesn't have extra params like key id.
|
||||||
|
publicKey := signingKey
|
||||||
|
publicKey.Key = recipient.publicKey().Key
|
||||||
|
recipient.publicKey = staticPublicKey(&publicKey)
|
||||||
|
|
||||||
|
// This should be impossible, but let's check anyway.
|
||||||
|
if !recipient.publicKey().IsPublic() {
|
||||||
|
return recipientSigInfo{}, errors.New("square/go-jose: public key was unexpectedly not public")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return recipient, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||||
|
@ -148,15 +217,24 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||||
obj.Signatures = make([]Signature, len(ctx.recipients))
|
obj.Signatures = make([]Signature, len(ctx.recipients))
|
||||||
|
|
||||||
for i, recipient := range ctx.recipients {
|
for i, recipient := range ctx.recipients {
|
||||||
protected := &rawHeader{
|
protected := map[HeaderKey]interface{}{
|
||||||
Alg: string(recipient.sigAlg),
|
headerAlgorithm: string(recipient.sigAlg),
|
||||||
}
|
}
|
||||||
|
|
||||||
if recipient.publicKey != nil {
|
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||||
|
// We want to embed the JWK or set the kid header, but not both. Having a protected
|
||||||
|
// header that contains an embedded JWK while also simultaneously containing the kid
|
||||||
|
// header is confusing, and at least in ACME the two are considered to be mutually
|
||||||
|
// exclusive. The fact that both can exist at the same time is a somewhat unfortunate
|
||||||
|
// result of the JOSE spec. We've decided that this library will only include one or
|
||||||
|
// the other to avoid this confusion.
|
||||||
|
//
|
||||||
|
// See https://github.com/square/go-jose/issues/157 for more context.
|
||||||
if ctx.embedJWK {
|
if ctx.embedJWK {
|
||||||
protected.Jwk = recipient.publicKey
|
protected[headerJWK] = recipient.publicKey()
|
||||||
|
} else {
|
||||||
|
protected[headerKeyID] = recipient.publicKey().KeyID
|
||||||
}
|
}
|
||||||
protected.Kid = recipient.publicKey.KeyID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.nonceSource != nil {
|
if ctx.nonceSource != nil {
|
||||||
|
@ -164,7 +242,11 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err)
|
return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err)
|
||||||
}
|
}
|
||||||
protected.Nonce = nonce
|
protected[headerNonce] = nonce
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range ctx.extraHeaders {
|
||||||
|
protected[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
serializedProtected := mustSerializeJSON(protected)
|
serializedProtected := mustSerializeJSON(protected)
|
||||||
|
@ -178,13 +260,28 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
signatureInfo.protected = protected
|
signatureInfo.protected = &rawHeader{}
|
||||||
|
for k, v := range protected {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: Error marshalling item %#v: %v", k, err)
|
||||||
|
}
|
||||||
|
(*signatureInfo.protected)[k] = makeRawMessage(b)
|
||||||
|
}
|
||||||
obj.Signatures[i] = signatureInfo
|
obj.Signatures[i] = signatureInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *genericSigner) Options() SignerOptions {
|
||||||
|
return SignerOptions{
|
||||||
|
NonceSource: ctx.nonceSource,
|
||||||
|
EmbedJWK: ctx.embedJWK,
|
||||||
|
ExtraHeaders: ctx.extraHeaders,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify validates the signature on the object and returns the payload.
|
// Verify validates the signature on the object and returns the payload.
|
||||||
// This function does not support multi-signature, if you desire multi-sig
|
// This function does not support multi-signature, if you desire multi-sig
|
||||||
// verification use VerifyMulti instead.
|
// verification use VerifyMulti instead.
|
||||||
|
@ -193,30 +290,53 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||||
// payload header. You cannot assume that the key received in a payload is
|
// payload header. You cannot assume that the key received in a payload is
|
||||||
// trusted.
|
// trusted.
|
||||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||||
verifier, err := newVerifier(verificationKey)
|
err := obj.DetachedVerify(obj.payload, verificationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return obj.payload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsafePayloadWithoutVerification returns the payload without
|
||||||
|
// verifying it. The content returned from this function cannot be
|
||||||
|
// trusted.
|
||||||
|
func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
||||||
|
return obj.payload
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetachedVerify validates a detached signature on the given payload. In
|
||||||
|
// most cases, you will probably want to use Verify instead. DetachedVerify
|
||||||
|
// is only useful if you have a payload and signature that are separated from
|
||||||
|
// each other.
|
||||||
|
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||||
|
verifier, err := newVerifier(verificationKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(obj.Signatures) > 1 {
|
if len(obj.Signatures) > 1 {
|
||||||
return nil, errors.New("square/go-jose: too many signatures in payload; expecting only one")
|
return errors.New("square/go-jose: too many signatures in payload; expecting only one")
|
||||||
}
|
}
|
||||||
|
|
||||||
signature := obj.Signatures[0]
|
signature := obj.Signatures[0]
|
||||||
headers := signature.mergedHeaders()
|
headers := signature.mergedHeaders()
|
||||||
if len(headers.Crit) > 0 {
|
critical, err := headers.getCritical()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(critical) > 0 {
|
||||||
// Unsupported crit header
|
// Unsupported crit header
|
||||||
return nil, ErrCryptoFailure
|
return ErrCryptoFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
input := obj.computeAuthData(&signature)
|
input := obj.computeAuthData(payload, &signature)
|
||||||
alg := SignatureAlgorithm(headers.Alg)
|
alg := headers.getSignatureAlgorithm()
|
||||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return obj.payload, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrCryptoFailure
|
return ErrCryptoFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyMulti validates (one of the multiple) signatures on the object and
|
// VerifyMulti validates (one of the multiple) signatures on the object and
|
||||||
|
@ -224,25 +344,46 @@ func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error)
|
||||||
// object and the payload. We return the signature and index to guarantee that
|
// object and the payload. We return the signature and index to guarantee that
|
||||||
// callers are getting the verified value.
|
// callers are getting the verified value.
|
||||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||||
verifier, err := newVerifier(verificationKey)
|
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, Signature{}, nil, err
|
return -1, Signature{}, nil, err
|
||||||
}
|
}
|
||||||
|
return idx, sig, obj.payload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetachedVerifyMulti validates a detached signature on the given payload with
|
||||||
|
// a signature/object that has potentially multiple signers. This returns the index
|
||||||
|
// of the signature that was verified, along with the signature object. We return
|
||||||
|
// the signature and index to guarantee that callers are getting the verified value.
|
||||||
|
//
|
||||||
|
// In most cases, you will probably want to use Verify or VerifyMulti instead.
|
||||||
|
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
||||||
|
// separated from each other, and the signature can have multiple signers at the
|
||||||
|
// same time.
|
||||||
|
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||||
|
verifier, err := newVerifier(verificationKey)
|
||||||
|
if err != nil {
|
||||||
|
return -1, Signature{}, err
|
||||||
|
}
|
||||||
|
|
||||||
for i, signature := range obj.Signatures {
|
for i, signature := range obj.Signatures {
|
||||||
headers := signature.mergedHeaders()
|
headers := signature.mergedHeaders()
|
||||||
if len(headers.Crit) > 0 {
|
critical, err := headers.getCritical()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(critical) > 0 {
|
||||||
// Unsupported crit header
|
// Unsupported crit header
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
input := obj.computeAuthData(&signature)
|
input := obj.computeAuthData(payload, &signature)
|
||||||
alg := SignatureAlgorithm(headers.Alg)
|
alg := headers.getSignatureAlgorithm()
|
||||||
err := verifier.verifyPayload(input, signature.Signature, alg)
|
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return i, signature, obj.payload, nil
|
return i, signature, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1, Signature{}, nil, ErrCryptoFailure
|
return -1, Signature{}, ErrCryptoFailure
|
||||||
}
|
}
|
||||||
|
|
147
vendor/gopkg.in/square/go-jose.v2/symmetric.go
generated
vendored
147
vendor/gopkg.in/square/go-jose.v2/symmetric.go
generated
vendored
|
@ -17,6 +17,7 @@
|
||||||
package jose
|
package jose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
|
@ -25,18 +26,34 @@ import (
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
"gopkg.in/square/go-jose.v2/cipher"
|
"gopkg.in/square/go-jose.v2/cipher"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Random reader (stubbed out in tests)
|
// Random reader (stubbed out in tests)
|
||||||
var randReader = rand.Reader
|
var randReader = rand.Reader
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||||
|
// https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||||
|
// NIST recommends a minimum of 10,000:
|
||||||
|
// https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||||
|
// 1Password uses 100,000:
|
||||||
|
// https://support.1password.com/pbkdf2/
|
||||||
|
defaultP2C = 100000
|
||||||
|
// Default salt size: 128 bits
|
||||||
|
defaultP2SSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
// Dummy key cipher for shared symmetric key mode
|
// Dummy key cipher for shared symmetric key mode
|
||||||
type symmetricKeyCipher struct {
|
type symmetricKeyCipher struct {
|
||||||
key []byte // Pre-shared content-encryption key
|
key []byte // Pre-shared content-encryption key
|
||||||
|
p2c int // PBES2 Count
|
||||||
|
p2s []byte // PBES2 Salt Input
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signer/verifier for MAC modes
|
// Signer/verifier for MAC modes
|
||||||
|
@ -113,10 +130,37 @@ func getContentCipher(alg ContentEncryption) contentCipher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPbkdf2Params returns the key length and hash function used in
|
||||||
|
// pbkdf2.Key.
|
||||||
|
func getPbkdf2Params(alg KeyAlgorithm) (int, func() hash.Hash) {
|
||||||
|
switch alg {
|
||||||
|
case PBES2_HS256_A128KW:
|
||||||
|
return 16, sha256.New
|
||||||
|
case PBES2_HS384_A192KW:
|
||||||
|
return 24, sha512.New384
|
||||||
|
case PBES2_HS512_A256KW:
|
||||||
|
return 32, sha512.New
|
||||||
|
default:
|
||||||
|
panic("invalid algorithm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRandomSalt generates a new salt of the given size.
|
||||||
|
func getRandomSalt(size int) ([]byte, error) {
|
||||||
|
salt := make([]byte, size)
|
||||||
|
_, err := io.ReadFull(randReader, salt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return salt, nil
|
||||||
|
}
|
||||||
|
|
||||||
// newSymmetricRecipient creates a JWE encrypter based on AES-GCM key wrap.
|
// newSymmetricRecipient creates a JWE encrypter based on AES-GCM key wrap.
|
||||||
func newSymmetricRecipient(keyAlg KeyAlgorithm, key []byte) (recipientKeyInfo, error) {
|
func newSymmetricRecipient(keyAlg KeyAlgorithm, key []byte) (recipientKeyInfo, error) {
|
||||||
switch keyAlg {
|
switch keyAlg {
|
||||||
case DIRECT, A128GCMKW, A192GCMKW, A256GCMKW, A128KW, A192KW, A256KW:
|
case DIRECT, A128GCMKW, A192GCMKW, A256GCMKW, A128KW, A192KW, A256KW:
|
||||||
|
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||||
default:
|
default:
|
||||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||||
}
|
}
|
||||||
|
@ -211,6 +255,10 @@ func (ctx aeadContentCipher) decrypt(key, aad []byte, parts *aeadParts) ([]byte,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(parts.iv) != aead.NonceSize() || len(parts.tag) < ctx.authtagBytes {
|
||||||
|
return nil, ErrCryptoFailure
|
||||||
|
}
|
||||||
|
|
||||||
return aead.Open(nil, parts.iv, append(parts.ciphertext, parts.tag...), aad)
|
return aead.Open(nil, parts.iv, append(parts.ciphertext, parts.tag...), aad)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,11 +277,12 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||||
return recipientInfo{}, err
|
return recipientInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header := &rawHeader{}
|
||||||
|
header.set(headerIV, newBuffer(parts.iv))
|
||||||
|
header.set(headerTag, newBuffer(parts.tag))
|
||||||
|
|
||||||
return recipientInfo{
|
return recipientInfo{
|
||||||
header: &rawHeader{
|
header: header,
|
||||||
Iv: newBuffer(parts.iv),
|
|
||||||
Tag: newBuffer(parts.tag),
|
|
||||||
},
|
|
||||||
encryptedKey: parts.ciphertext,
|
encryptedKey: parts.ciphertext,
|
||||||
}, nil
|
}, nil
|
||||||
case A128KW, A192KW, A256KW:
|
case A128KW, A192KW, A256KW:
|
||||||
|
@ -251,6 +300,45 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||||
encryptedKey: jek,
|
encryptedKey: jek,
|
||||||
header: &rawHeader{},
|
header: &rawHeader{},
|
||||||
}, nil
|
}, nil
|
||||||
|
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||||
|
if len(ctx.p2s) == 0 {
|
||||||
|
salt, err := getRandomSalt(defaultP2SSize)
|
||||||
|
if err != nil {
|
||||||
|
return recipientInfo{}, err
|
||||||
|
}
|
||||||
|
ctx.p2s = salt
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.p2c <= 0 {
|
||||||
|
ctx.p2c = defaultP2C
|
||||||
|
}
|
||||||
|
|
||||||
|
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||||
|
salt := bytes.Join([][]byte{[]byte(alg), ctx.p2s}, []byte{0x00})
|
||||||
|
|
||||||
|
// derive key
|
||||||
|
keyLen, h := getPbkdf2Params(alg)
|
||||||
|
key := pbkdf2.Key(ctx.key, salt, ctx.p2c, keyLen, h)
|
||||||
|
|
||||||
|
// use AES cipher with derived key
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return recipientInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jek, err := josecipher.KeyWrap(block, cek)
|
||||||
|
if err != nil {
|
||||||
|
return recipientInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
header := &rawHeader{}
|
||||||
|
header.set(headerP2C, ctx.p2c)
|
||||||
|
header.set(headerP2S, newBuffer(ctx.p2s))
|
||||||
|
|
||||||
|
return recipientInfo{
|
||||||
|
encryptedKey: jek,
|
||||||
|
header: header,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return recipientInfo{}, ErrUnsupportedAlgorithm
|
return recipientInfo{}, ErrUnsupportedAlgorithm
|
||||||
|
@ -258,7 +346,7 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||||
|
|
||||||
// Decrypt the content encryption key.
|
// Decrypt the content encryption key.
|
||||||
func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||||
switch KeyAlgorithm(headers.Alg) {
|
switch headers.getAlgorithm() {
|
||||||
case DIRECT:
|
case DIRECT:
|
||||||
cek := make([]byte, len(ctx.key))
|
cek := make([]byte, len(ctx.key))
|
||||||
copy(cek, ctx.key)
|
copy(cek, ctx.key)
|
||||||
|
@ -266,10 +354,19 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||||
case A128GCMKW, A192GCMKW, A256GCMKW:
|
case A128GCMKW, A192GCMKW, A256GCMKW:
|
||||||
aead := newAESGCM(len(ctx.key))
|
aead := newAESGCM(len(ctx.key))
|
||||||
|
|
||||||
|
iv, err := headers.getIV()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid IV: %v", err)
|
||||||
|
}
|
||||||
|
tag, err := headers.getTag()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid tag: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
parts := &aeadParts{
|
parts := &aeadParts{
|
||||||
iv: headers.Iv.bytes(),
|
iv: iv.bytes(),
|
||||||
ciphertext: recipient.encryptedKey,
|
ciphertext: recipient.encryptedKey,
|
||||||
tag: headers.Tag.bytes(),
|
tag: tag.bytes(),
|
||||||
}
|
}
|
||||||
|
|
||||||
cek, err := aead.decrypt(ctx.key, []byte{}, parts)
|
cek, err := aead.decrypt(ctx.key, []byte{}, parts)
|
||||||
|
@ -284,6 +381,42 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cek, nil
|
||||||
|
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||||
|
p2s, err := headers.getP2S()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid P2S: %v", err)
|
||||||
|
}
|
||||||
|
if p2s == nil || len(p2s.data) == 0 {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid P2S: must be present")
|
||||||
|
}
|
||||||
|
|
||||||
|
p2c, err := headers.getP2C()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid P2C: %v", err)
|
||||||
|
}
|
||||||
|
if p2c <= 0 {
|
||||||
|
return nil, fmt.Errorf("square/go-jose: invalid P2C: must be a positive integer")
|
||||||
|
}
|
||||||
|
|
||||||
|
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||||
|
alg := headers.getAlgorithm()
|
||||||
|
salt := bytes.Join([][]byte{[]byte(alg), p2s.bytes()}, []byte{0x00})
|
||||||
|
|
||||||
|
// derive key
|
||||||
|
keyLen, h := getPbkdf2Params(alg)
|
||||||
|
key := pbkdf2.Key(ctx.key, salt, p2c, keyLen, h)
|
||||||
|
|
||||||
|
// use AES cipher with derived key
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in a new issue