mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 16:13:45 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			265 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package signed
 | |
| 
 | |
| import (
 | |
| 	"crypto"
 | |
| 	"crypto/ecdsa"
 | |
| 	"crypto/rsa"
 | |
| 	"crypto/sha256"
 | |
| 	"crypto/x509"
 | |
| 	"encoding/pem"
 | |
| 	"fmt"
 | |
| 	"math/big"
 | |
| 
 | |
| 	"github.com/agl/ed25519"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| 	"github.com/theupdateframework/notary/tuf/data"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	minRSAKeySizeBit  = 2048 // 2048 bits = 256 bytes
 | |
| 	minRSAKeySizeByte = minRSAKeySizeBit / 8
 | |
| )
 | |
| 
 | |
| // Verifiers serves as a map of all verifiers available on the system and
 | |
| // can be injected into a verificationService. For testing and configuration
 | |
| // purposes, it will not be used by default.
 | |
| var Verifiers = map[data.SigAlgorithm]Verifier{
 | |
| 	data.RSAPSSSignature:      RSAPSSVerifier{},
 | |
| 	data.RSAPKCS1v15Signature: RSAPKCS1v15Verifier{},
 | |
| 	data.PyCryptoSignature:    RSAPyCryptoVerifier{},
 | |
| 	data.ECDSASignature:       ECDSAVerifier{},
 | |
| 	data.EDDSASignature:       Ed25519Verifier{},
 | |
| }
 | |
| 
 | |
| // Ed25519Verifier used to verify Ed25519 signatures
 | |
| type Ed25519Verifier struct{}
 | |
| 
 | |
| // Verify checks that an ed25519 signature is valid
 | |
| func (v Ed25519Verifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 | |
| 	if key.Algorithm() != data.ED25519Key {
 | |
| 		return ErrInvalidKeyType{}
 | |
| 	}
 | |
| 	var sigBytes [ed25519.SignatureSize]byte
 | |
| 	if len(sig) != ed25519.SignatureSize {
 | |
| 		logrus.Debugf("signature length is incorrect, must be %d, was %d.", ed25519.SignatureSize, len(sig))
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 	copy(sigBytes[:], sig)
 | |
| 
 | |
| 	var keyBytes [ed25519.PublicKeySize]byte
 | |
| 	pub := key.Public()
 | |
| 	if len(pub) != ed25519.PublicKeySize {
 | |
| 		logrus.Errorf("public key is incorrect size, must be %d, was %d.", ed25519.PublicKeySize, len(pub))
 | |
| 		return ErrInvalidKeyLength{msg: fmt.Sprintf("ed25519 public key must be %d bytes.", ed25519.PublicKeySize)}
 | |
| 	}
 | |
| 	n := copy(keyBytes[:], key.Public())
 | |
| 	if n < ed25519.PublicKeySize {
 | |
| 		logrus.Errorf("failed to copy the key, must have %d bytes, copied %d bytes.", ed25519.PublicKeySize, n)
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	if !ed25519.Verify(&keyBytes, msg, &sigBytes) {
 | |
| 		logrus.Debugf("failed ed25519 verification")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func verifyPSS(key interface{}, digest, sig []byte) error {
 | |
| 	rsaPub, ok := key.(*rsa.PublicKey)
 | |
| 	if !ok {
 | |
| 		logrus.Debugf("value was not an RSA public key")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	if rsaPub.N.BitLen() < minRSAKeySizeBit {
 | |
| 		logrus.Debugf("RSA keys less than 2048 bits are not acceptable, provided key has length %d.", rsaPub.N.BitLen())
 | |
| 		return ErrInvalidKeyLength{msg: fmt.Sprintf("RSA key must be at least %d bits.", minRSAKeySizeBit)}
 | |
| 	}
 | |
| 
 | |
| 	if len(sig) < minRSAKeySizeByte {
 | |
| 		logrus.Debugf("RSA keys less than 2048 bits are not acceptable, provided signature has length %d.", len(sig))
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	opts := rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256}
 | |
| 	if err := rsa.VerifyPSS(rsaPub, crypto.SHA256, digest[:], sig, &opts); err != nil {
 | |
| 		logrus.Debugf("failed RSAPSS verification: %s", err)
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func getRSAPubKey(key data.PublicKey) (crypto.PublicKey, error) {
 | |
| 	algorithm := key.Algorithm()
 | |
| 	var pubKey crypto.PublicKey
 | |
| 
 | |
| 	switch algorithm {
 | |
| 	case data.RSAx509Key:
 | |
| 		pemCert, _ := pem.Decode([]byte(key.Public()))
 | |
| 		if pemCert == nil {
 | |
| 			logrus.Debugf("failed to decode PEM-encoded x509 certificate")
 | |
| 			return nil, ErrInvalid
 | |
| 		}
 | |
| 		cert, err := x509.ParseCertificate(pemCert.Bytes)
 | |
| 		if err != nil {
 | |
| 			logrus.Debugf("failed to parse x509 certificate: %s\n", err)
 | |
| 			return nil, ErrInvalid
 | |
| 		}
 | |
| 		pubKey = cert.PublicKey
 | |
| 	case data.RSAKey:
 | |
| 		var err error
 | |
| 		pubKey, err = x509.ParsePKIXPublicKey(key.Public())
 | |
| 		if err != nil {
 | |
| 			logrus.Debugf("failed to parse public key: %s\n", err)
 | |
| 			return nil, ErrInvalid
 | |
| 		}
 | |
| 	default:
 | |
| 		// only accept RSA keys
 | |
| 		logrus.Debugf("invalid key type for RSAPSS verifier: %s", algorithm)
 | |
| 		return nil, ErrInvalidKeyType{}
 | |
| 	}
 | |
| 
 | |
| 	return pubKey, nil
 | |
| }
 | |
| 
 | |
| // RSAPSSVerifier checks RSASSA-PSS signatures
 | |
| type RSAPSSVerifier struct{}
 | |
| 
 | |
| // Verify does the actual check.
 | |
| func (v RSAPSSVerifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 | |
| 	// will return err if keytype is not a recognized RSA type
 | |
| 	pubKey, err := getRSAPubKey(key)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	digest := sha256.Sum256(msg)
 | |
| 
 | |
| 	return verifyPSS(pubKey, digest[:], sig)
 | |
| }
 | |
| 
 | |
| // RSAPKCS1v15Verifier checks RSA PKCS1v15 signatures
 | |
| type RSAPKCS1v15Verifier struct{}
 | |
| 
 | |
| // Verify does the actual verification
 | |
| func (v RSAPKCS1v15Verifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 | |
| 	// will return err if keytype is not a recognized RSA type
 | |
| 	pubKey, err := getRSAPubKey(key)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	digest := sha256.Sum256(msg)
 | |
| 
 | |
| 	rsaPub, ok := pubKey.(*rsa.PublicKey)
 | |
| 	if !ok {
 | |
| 		logrus.Debugf("value was not an RSA public key")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	if rsaPub.N.BitLen() < minRSAKeySizeBit {
 | |
| 		logrus.Debugf("RSA keys less than 2048 bits are not acceptable, provided key has length %d.", rsaPub.N.BitLen())
 | |
| 		return ErrInvalidKeyLength{msg: fmt.Sprintf("RSA key must be at least %d bits.", minRSAKeySizeBit)}
 | |
| 	}
 | |
| 
 | |
| 	if len(sig) < minRSAKeySizeByte {
 | |
| 		logrus.Debugf("RSA keys less than 2048 bits are not acceptable, provided signature has length %d.", len(sig))
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	if err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig); err != nil {
 | |
| 		logrus.Errorf("Failed verification: %s", err.Error())
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // RSAPyCryptoVerifier checks RSASSA-PSS signatures
 | |
| type RSAPyCryptoVerifier struct{}
 | |
| 
 | |
| // Verify does the actual check.
 | |
| // N.B. We have not been able to make this work in a way that is compatible
 | |
| // with PyCrypto.
 | |
| func (v RSAPyCryptoVerifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 | |
| 	digest := sha256.Sum256(msg)
 | |
| 	if key.Algorithm() != data.RSAKey {
 | |
| 		return ErrInvalidKeyType{}
 | |
| 	}
 | |
| 
 | |
| 	k, _ := pem.Decode([]byte(key.Public()))
 | |
| 	if k == nil {
 | |
| 		logrus.Debugf("failed to decode PEM-encoded x509 certificate")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	pub, err := x509.ParsePKIXPublicKey(k.Bytes)
 | |
| 	if err != nil {
 | |
| 		logrus.Debugf("failed to parse public key: %s\n", err)
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	return verifyPSS(pub, digest[:], sig)
 | |
| }
 | |
| 
 | |
| // ECDSAVerifier checks ECDSA signatures, decoding the keyType appropriately
 | |
| type ECDSAVerifier struct{}
 | |
| 
 | |
| // Verify does the actual check.
 | |
| func (v ECDSAVerifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 | |
| 	algorithm := key.Algorithm()
 | |
| 	var pubKey crypto.PublicKey
 | |
| 
 | |
| 	switch algorithm {
 | |
| 	case data.ECDSAx509Key:
 | |
| 		pemCert, _ := pem.Decode([]byte(key.Public()))
 | |
| 		if pemCert == nil {
 | |
| 			logrus.Debugf("failed to decode PEM-encoded x509 certificate for keyID: %s", key.ID())
 | |
| 			logrus.Debugf("certificate bytes: %s", string(key.Public()))
 | |
| 			return ErrInvalid
 | |
| 		}
 | |
| 		cert, err := x509.ParseCertificate(pemCert.Bytes)
 | |
| 		if err != nil {
 | |
| 			logrus.Debugf("failed to parse x509 certificate: %s\n", err)
 | |
| 			return ErrInvalid
 | |
| 		}
 | |
| 		pubKey = cert.PublicKey
 | |
| 	case data.ECDSAKey:
 | |
| 		var err error
 | |
| 		pubKey, err = x509.ParsePKIXPublicKey(key.Public())
 | |
| 		if err != nil {
 | |
| 			logrus.Debugf("Failed to parse private key for keyID: %s, %s\n", key.ID(), err)
 | |
| 			return ErrInvalid
 | |
| 		}
 | |
| 	default:
 | |
| 		// only accept ECDSA keys.
 | |
| 		logrus.Debugf("invalid key type for ECDSA verifier: %s", algorithm)
 | |
| 		return ErrInvalidKeyType{}
 | |
| 	}
 | |
| 
 | |
| 	ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey)
 | |
| 	if !ok {
 | |
| 		logrus.Debugf("value isn't an ECDSA public key")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	sigLength := len(sig)
 | |
| 	expectedOctetLength := 2 * ((ecdsaPubKey.Params().BitSize + 7) >> 3)
 | |
| 	if sigLength != expectedOctetLength {
 | |
| 		logrus.Debugf("signature had an unexpected length")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	rBytes, sBytes := sig[:sigLength/2], sig[sigLength/2:]
 | |
| 	r := new(big.Int).SetBytes(rBytes)
 | |
| 	s := new(big.Int).SetBytes(sBytes)
 | |
| 
 | |
| 	digest := sha256.Sum256(msg)
 | |
| 
 | |
| 	if !ecdsa.Verify(ecdsaPubKey, digest[:], r, s) {
 | |
| 		logrus.Debugf("failed ECDSA signature validation")
 | |
| 		return ErrInvalid
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | 
