mirror of
				https://github.com/StackExchange/dnscontrol.git
				synced 2024-05-11 05:55:12 +00:00 
			
		
		
		
	* switch to new go-acme imports from xenolf. Fix api changes * update many vault related dependencies
		
			
				
	
	
		
			593 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			593 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*-
 | 
						|
 * Copyright 2014 Square Inc.
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
package jose
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto"
 | 
						|
	"crypto/aes"
 | 
						|
	"crypto/ecdsa"
 | 
						|
	"crypto/rand"
 | 
						|
	"crypto/rsa"
 | 
						|
	"crypto/sha1"
 | 
						|
	"crypto/sha256"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"math/big"
 | 
						|
 | 
						|
	"golang.org/x/crypto/ed25519"
 | 
						|
	"gopkg.in/square/go-jose.v2/cipher"
 | 
						|
	"gopkg.in/square/go-jose.v2/json"
 | 
						|
)
 | 
						|
 | 
						|
// A generic RSA-based encrypter/verifier
 | 
						|
type rsaEncrypterVerifier struct {
 | 
						|
	publicKey *rsa.PublicKey
 | 
						|
}
 | 
						|
 | 
						|
// A generic RSA-based decrypter/signer
 | 
						|
type rsaDecrypterSigner struct {
 | 
						|
	privateKey *rsa.PrivateKey
 | 
						|
}
 | 
						|
 | 
						|
// A generic EC-based encrypter/verifier
 | 
						|
type ecEncrypterVerifier struct {
 | 
						|
	publicKey *ecdsa.PublicKey
 | 
						|
}
 | 
						|
 | 
						|
type edEncrypterVerifier struct {
 | 
						|
	publicKey ed25519.PublicKey
 | 
						|
}
 | 
						|
 | 
						|
// A key generator for ECDH-ES
 | 
						|
type ecKeyGenerator struct {
 | 
						|
	size      int
 | 
						|
	algID     string
 | 
						|
	publicKey *ecdsa.PublicKey
 | 
						|
}
 | 
						|
 | 
						|
// A generic EC-based decrypter/signer
 | 
						|
type ecDecrypterSigner struct {
 | 
						|
	privateKey *ecdsa.PrivateKey
 | 
						|
}
 | 
						|
 | 
						|
type edDecrypterSigner struct {
 | 
						|
	privateKey ed25519.PrivateKey
 | 
						|
}
 | 
						|
 | 
						|
// newRSARecipient creates recipientKeyInfo based on the given key.
 | 
						|
func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
 | 
						|
	// Verify that key management algorithm is supported by this encrypter
 | 
						|
	switch keyAlg {
 | 
						|
	case RSA1_5, RSA_OAEP, RSA_OAEP_256:
 | 
						|
	default:
 | 
						|
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	if publicKey == nil {
 | 
						|
		return recipientKeyInfo{}, errors.New("invalid public key")
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientKeyInfo{
 | 
						|
		keyAlg: keyAlg,
 | 
						|
		keyEncrypter: &rsaEncrypterVerifier{
 | 
						|
			publicKey: publicKey,
 | 
						|
		},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// newRSASigner creates a recipientSigInfo based on the given key.
 | 
						|
func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) {
 | 
						|
	// Verify that key management algorithm is supported by this encrypter
 | 
						|
	switch sigAlg {
 | 
						|
	case RS256, RS384, RS512, PS256, PS384, PS512:
 | 
						|
	default:
 | 
						|
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	if privateKey == nil {
 | 
						|
		return recipientSigInfo{}, errors.New("invalid private key")
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientSigInfo{
 | 
						|
		sigAlg: sigAlg,
 | 
						|
		publicKey: staticPublicKey(&JSONWebKey{
 | 
						|
			Key: privateKey.Public(),
 | 
						|
		}),
 | 
						|
		signer: &rsaDecrypterSigner{
 | 
						|
			privateKey: privateKey,
 | 
						|
		},
 | 
						|
	}, 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.
 | 
						|
func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
 | 
						|
	// Verify that key management algorithm is supported by this encrypter
 | 
						|
	switch keyAlg {
 | 
						|
	case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
 | 
						|
	default:
 | 
						|
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
 | 
						|
		return recipientKeyInfo{}, errors.New("invalid public key")
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientKeyInfo{
 | 
						|
		keyAlg: keyAlg,
 | 
						|
		keyEncrypter: &ecEncrypterVerifier{
 | 
						|
			publicKey: publicKey,
 | 
						|
		},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// newECDSASigner creates a recipientSigInfo based on the given key.
 | 
						|
func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) {
 | 
						|
	// Verify that key management algorithm is supported by this encrypter
 | 
						|
	switch sigAlg {
 | 
						|
	case ES256, ES384, ES512:
 | 
						|
	default:
 | 
						|
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	if privateKey == nil {
 | 
						|
		return recipientSigInfo{}, errors.New("invalid private key")
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientSigInfo{
 | 
						|
		sigAlg: sigAlg,
 | 
						|
		publicKey: staticPublicKey(&JSONWebKey{
 | 
						|
			Key: privateKey.Public(),
 | 
						|
		}),
 | 
						|
		signer: &ecDecrypterSigner{
 | 
						|
			privateKey: privateKey,
 | 
						|
		},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// Encrypt the given payload and update the object.
 | 
						|
func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
						|
	encryptedKey, err := ctx.encrypt(cek, alg)
 | 
						|
	if err != nil {
 | 
						|
		return recipientInfo{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientInfo{
 | 
						|
		encryptedKey: encryptedKey,
 | 
						|
		header:       &rawHeader{},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// Encrypt the given payload. Based on the key encryption algorithm,
 | 
						|
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
 | 
						|
func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) {
 | 
						|
	switch alg {
 | 
						|
	case RSA1_5:
 | 
						|
		return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek)
 | 
						|
	case RSA_OAEP:
 | 
						|
		return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{})
 | 
						|
	case RSA_OAEP_256:
 | 
						|
		return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{})
 | 
						|
	}
 | 
						|
 | 
						|
	return nil, ErrUnsupportedAlgorithm
 | 
						|
}
 | 
						|
 | 
						|
// Decrypt the given payload and return the content encryption key.
 | 
						|
func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
						|
	return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator)
 | 
						|
}
 | 
						|
 | 
						|
// Decrypt the given payload. Based on the key encryption algorithm,
 | 
						|
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
 | 
						|
func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) {
 | 
						|
	// Note: The random reader on decrypt operations is only used for blinding,
 | 
						|
	// so stubbing is meanlingless (hence the direct use of rand.Reader).
 | 
						|
	switch alg {
 | 
						|
	case RSA1_5:
 | 
						|
		defer func() {
 | 
						|
			// DecryptPKCS1v15SessionKey sometimes panics on an invalid payload
 | 
						|
			// because of an index out of bounds error, which we want to ignore.
 | 
						|
			// This has been fixed in Go 1.3.1 (released 2014/08/13), the recover()
 | 
						|
			// only exists for preventing crashes with unpatched versions.
 | 
						|
			// See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k
 | 
						|
			// See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33
 | 
						|
			_ = recover()
 | 
						|
		}()
 | 
						|
 | 
						|
		// Perform some input validation.
 | 
						|
		keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8
 | 
						|
		if keyBytes != len(jek) {
 | 
						|
			// Input size is incorrect, the encrypted payload should always match
 | 
						|
			// the size of the public modulus (e.g. using a 2048 bit key will
 | 
						|
			// produce 256 bytes of output). Reject this since it's invalid input.
 | 
						|
			return nil, ErrCryptoFailure
 | 
						|
		}
 | 
						|
 | 
						|
		cek, _, err := generator.genKey()
 | 
						|
		if err != nil {
 | 
						|
			return nil, ErrCryptoFailure
 | 
						|
		}
 | 
						|
 | 
						|
		// When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to
 | 
						|
		// prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing
 | 
						|
		// the Million Message Attack on Cryptographic Message Syntax". We are
 | 
						|
		// therefore deliberately ignoring errors here.
 | 
						|
		_ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek)
 | 
						|
 | 
						|
		return cek, nil
 | 
						|
	case RSA_OAEP:
 | 
						|
		// Use rand.Reader for RSA blinding
 | 
						|
		return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{})
 | 
						|
	case RSA_OAEP_256:
 | 
						|
		// Use rand.Reader for RSA blinding
 | 
						|
		return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{})
 | 
						|
	}
 | 
						|
 | 
						|
	return nil, ErrUnsupportedAlgorithm
 | 
						|
}
 | 
						|
 | 
						|
// Sign the given payload
 | 
						|
func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
						|
	var hash crypto.Hash
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case RS256, PS256:
 | 
						|
		hash = crypto.SHA256
 | 
						|
	case RS384, PS384:
 | 
						|
		hash = crypto.SHA384
 | 
						|
	case RS512, PS512:
 | 
						|
		hash = crypto.SHA512
 | 
						|
	default:
 | 
						|
		return Signature{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	hasher := hash.New()
 | 
						|
 | 
						|
	// According to documentation, Write() on hash never fails
 | 
						|
	_, _ = hasher.Write(payload)
 | 
						|
	hashed := hasher.Sum(nil)
 | 
						|
 | 
						|
	var out []byte
 | 
						|
	var err error
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case RS256, RS384, RS512:
 | 
						|
		out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
 | 
						|
	case PS256, PS384, PS512:
 | 
						|
		out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
 | 
						|
			SaltLength: rsa.PSSSaltLengthAuto,
 | 
						|
		})
 | 
						|
	}
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return Signature{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	return Signature{
 | 
						|
		Signature: out,
 | 
						|
		protected: &rawHeader{},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// Verify the given payload
 | 
						|
func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
						|
	var hash crypto.Hash
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case RS256, PS256:
 | 
						|
		hash = crypto.SHA256
 | 
						|
	case RS384, PS384:
 | 
						|
		hash = crypto.SHA384
 | 
						|
	case RS512, PS512:
 | 
						|
		hash = crypto.SHA512
 | 
						|
	default:
 | 
						|
		return ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	hasher := hash.New()
 | 
						|
 | 
						|
	// According to documentation, Write() on hash never fails
 | 
						|
	_, _ = hasher.Write(payload)
 | 
						|
	hashed := hasher.Sum(nil)
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case RS256, RS384, RS512:
 | 
						|
		return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature)
 | 
						|
	case PS256, PS384, PS512:
 | 
						|
		return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil)
 | 
						|
	}
 | 
						|
 | 
						|
	return ErrUnsupportedAlgorithm
 | 
						|
}
 | 
						|
 | 
						|
// Encrypt the given payload and update the object.
 | 
						|
func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
						|
	switch alg {
 | 
						|
	case ECDH_ES:
 | 
						|
		// ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key.
 | 
						|
		return recipientInfo{
 | 
						|
			header: &rawHeader{},
 | 
						|
		}, nil
 | 
						|
	case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
 | 
						|
	default:
 | 
						|
		return recipientInfo{}, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	generator := ecKeyGenerator{
 | 
						|
		algID:     string(alg),
 | 
						|
		publicKey: ctx.publicKey,
 | 
						|
	}
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case ECDH_ES_A128KW:
 | 
						|
		generator.size = 16
 | 
						|
	case ECDH_ES_A192KW:
 | 
						|
		generator.size = 24
 | 
						|
	case ECDH_ES_A256KW:
 | 
						|
		generator.size = 32
 | 
						|
	}
 | 
						|
 | 
						|
	kek, header, err := generator.genKey()
 | 
						|
	if err != nil {
 | 
						|
		return recipientInfo{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	block, err := aes.NewCipher(kek)
 | 
						|
	if err != nil {
 | 
						|
		return recipientInfo{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	jek, err := josecipher.KeyWrap(block, cek)
 | 
						|
	if err != nil {
 | 
						|
		return recipientInfo{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	return recipientInfo{
 | 
						|
		encryptedKey: jek,
 | 
						|
		header:       &header,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// Get key size for EC key generator
 | 
						|
func (ctx ecKeyGenerator) keySize() int {
 | 
						|
	return ctx.size
 | 
						|
}
 | 
						|
 | 
						|
// Get a content encryption key for ECDH-ES
 | 
						|
func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
 | 
						|
	priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader)
 | 
						|
	if err != nil {
 | 
						|
		return nil, rawHeader{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
 | 
						|
 | 
						|
	b, err := json.Marshal(&JSONWebKey{
 | 
						|
		Key: &priv.PublicKey,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	headers := rawHeader{
 | 
						|
		headerEPK: makeRawMessage(b),
 | 
						|
	}
 | 
						|
 | 
						|
	return out, headers, nil
 | 
						|
}
 | 
						|
 | 
						|
// Decrypt the given payload and return the content encryption key.
 | 
						|
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
						|
	epk, err := headers.getEPK()
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.New("square/go-jose: invalid epk header")
 | 
						|
	}
 | 
						|
	if epk == nil {
 | 
						|
		return nil, errors.New("square/go-jose: missing epk header")
 | 
						|
	}
 | 
						|
 | 
						|
	publicKey, ok := epk.Key.(*ecdsa.PublicKey)
 | 
						|
	if publicKey == nil || !ok {
 | 
						|
		return nil, errors.New("square/go-jose: invalid epk header")
 | 
						|
	}
 | 
						|
 | 
						|
	if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
 | 
						|
		return nil, errors.New("square/go-jose: invalid public key in epk header")
 | 
						|
	}
 | 
						|
 | 
						|
	apuData, err := headers.getAPU()
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.New("square/go-jose: invalid apu header")
 | 
						|
	}
 | 
						|
	apvData, err := headers.getAPV()
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.New("square/go-jose: invalid apv header")
 | 
						|
	}
 | 
						|
 | 
						|
	deriveKey := func(algID string, size int) []byte {
 | 
						|
		return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size)
 | 
						|
	}
 | 
						|
 | 
						|
	var keySize int
 | 
						|
 | 
						|
	algorithm := headers.getAlgorithm()
 | 
						|
	switch algorithm {
 | 
						|
	case ECDH_ES:
 | 
						|
		// ECDH-ES uses direct key agreement, no key unwrapping necessary.
 | 
						|
		return deriveKey(string(headers.getEncryption()), generator.keySize()), nil
 | 
						|
	case ECDH_ES_A128KW:
 | 
						|
		keySize = 16
 | 
						|
	case ECDH_ES_A192KW:
 | 
						|
		keySize = 24
 | 
						|
	case ECDH_ES_A256KW:
 | 
						|
		keySize = 32
 | 
						|
	default:
 | 
						|
		return nil, ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	key := deriveKey(string(algorithm), keySize)
 | 
						|
	block, err := aes.NewCipher(key)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	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
 | 
						|
func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
						|
	var expectedBitSize int
 | 
						|
	var hash crypto.Hash
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case ES256:
 | 
						|
		expectedBitSize = 256
 | 
						|
		hash = crypto.SHA256
 | 
						|
	case ES384:
 | 
						|
		expectedBitSize = 384
 | 
						|
		hash = crypto.SHA384
 | 
						|
	case ES512:
 | 
						|
		expectedBitSize = 521
 | 
						|
		hash = crypto.SHA512
 | 
						|
	}
 | 
						|
 | 
						|
	curveBits := ctx.privateKey.Curve.Params().BitSize
 | 
						|
	if expectedBitSize != curveBits {
 | 
						|
		return Signature{}, fmt.Errorf("square/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
 | 
						|
	}
 | 
						|
 | 
						|
	hasher := hash.New()
 | 
						|
 | 
						|
	// According to documentation, Write() on hash never fails
 | 
						|
	_, _ = hasher.Write(payload)
 | 
						|
	hashed := hasher.Sum(nil)
 | 
						|
 | 
						|
	r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed)
 | 
						|
	if err != nil {
 | 
						|
		return Signature{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	keyBytes := curveBits / 8
 | 
						|
	if curveBits%8 > 0 {
 | 
						|
		keyBytes++
 | 
						|
	}
 | 
						|
 | 
						|
	// 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
 | 
						|
	// must be keyBytes long, and the output must be 2*keyBytes long.
 | 
						|
	rBytes := r.Bytes()
 | 
						|
	rBytesPadded := make([]byte, keyBytes)
 | 
						|
	copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
 | 
						|
 | 
						|
	sBytes := s.Bytes()
 | 
						|
	sBytesPadded := make([]byte, keyBytes)
 | 
						|
	copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
 | 
						|
 | 
						|
	out := append(rBytesPadded, sBytesPadded...)
 | 
						|
 | 
						|
	return Signature{
 | 
						|
		Signature: out,
 | 
						|
		protected: &rawHeader{},
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// Verify the given payload
 | 
						|
func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
						|
	var keySize int
 | 
						|
	var hash crypto.Hash
 | 
						|
 | 
						|
	switch alg {
 | 
						|
	case ES256:
 | 
						|
		keySize = 32
 | 
						|
		hash = crypto.SHA256
 | 
						|
	case ES384:
 | 
						|
		keySize = 48
 | 
						|
		hash = crypto.SHA384
 | 
						|
	case ES512:
 | 
						|
		keySize = 66
 | 
						|
		hash = crypto.SHA512
 | 
						|
	default:
 | 
						|
		return ErrUnsupportedAlgorithm
 | 
						|
	}
 | 
						|
 | 
						|
	if len(signature) != 2*keySize {
 | 
						|
		return fmt.Errorf("square/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
 | 
						|
	}
 | 
						|
 | 
						|
	hasher := hash.New()
 | 
						|
 | 
						|
	// According to documentation, Write() on hash never fails
 | 
						|
	_, _ = hasher.Write(payload)
 | 
						|
	hashed := hasher.Sum(nil)
 | 
						|
 | 
						|
	r := big.NewInt(0).SetBytes(signature[:keySize])
 | 
						|
	s := big.NewInt(0).SetBytes(signature[keySize:])
 | 
						|
 | 
						|
	match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
 | 
						|
	if !match {
 | 
						|
		return errors.New("square/go-jose: ecdsa signature failed to verify")
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |