mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 16:13:45 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			529 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			529 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package data
 | |
| 
 | |
| import (
 | |
| 	"crypto"
 | |
| 	"crypto/ecdsa"
 | |
| 	"crypto/rsa"
 | |
| 	"crypto/sha256"
 | |
| 	"crypto/x509"
 | |
| 	"encoding/asn1"
 | |
| 	"encoding/hex"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	"math/big"
 | |
| 
 | |
| 	"github.com/agl/ed25519"
 | |
| 	"github.com/docker/go/canonical/json"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // PublicKey is the necessary interface for public keys
 | |
| type PublicKey interface {
 | |
| 	ID() string
 | |
| 	Algorithm() string
 | |
| 	Public() []byte
 | |
| }
 | |
| 
 | |
| // PrivateKey adds the ability to access the private key
 | |
| type PrivateKey interface {
 | |
| 	PublicKey
 | |
| 	Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error)
 | |
| 	Private() []byte
 | |
| 	CryptoSigner() crypto.Signer
 | |
| 	SignatureAlgorithm() SigAlgorithm
 | |
| }
 | |
| 
 | |
| // KeyPair holds the public and private key bytes
 | |
| type KeyPair struct {
 | |
| 	Public  []byte `json:"public"`
 | |
| 	Private []byte `json:"private"`
 | |
| }
 | |
| 
 | |
| // Keys represents a map of key ID to PublicKey object. It's necessary
 | |
| // to allow us to unmarshal into an interface via the json.Unmarshaller
 | |
| // interface
 | |
| type Keys map[string]PublicKey
 | |
| 
 | |
| // UnmarshalJSON implements the json.Unmarshaller interface
 | |
| func (ks *Keys) UnmarshalJSON(data []byte) error {
 | |
| 	parsed := make(map[string]TUFKey)
 | |
| 	err := json.Unmarshal(data, &parsed)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	final := make(map[string]PublicKey)
 | |
| 	for k, tk := range parsed {
 | |
| 		final[k] = typedPublicKey(tk)
 | |
| 	}
 | |
| 	*ks = final
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // KeyList represents a list of keys
 | |
| type KeyList []PublicKey
 | |
| 
 | |
| // UnmarshalJSON implements the json.Unmarshaller interface
 | |
| func (ks *KeyList) UnmarshalJSON(data []byte) error {
 | |
| 	parsed := make([]TUFKey, 0, 1)
 | |
| 	err := json.Unmarshal(data, &parsed)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	final := make([]PublicKey, 0, len(parsed))
 | |
| 	for _, tk := range parsed {
 | |
| 		final = append(final, typedPublicKey(tk))
 | |
| 	}
 | |
| 	*ks = final
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // IDs generates a list of the hex encoded key IDs in the KeyList
 | |
| func (ks KeyList) IDs() []string {
 | |
| 	keyIDs := make([]string, 0, len(ks))
 | |
| 	for _, k := range ks {
 | |
| 		keyIDs = append(keyIDs, k.ID())
 | |
| 	}
 | |
| 	return keyIDs
 | |
| }
 | |
| 
 | |
| func typedPublicKey(tk TUFKey) PublicKey {
 | |
| 	switch tk.Algorithm() {
 | |
| 	case ECDSAKey:
 | |
| 		return &ECDSAPublicKey{TUFKey: tk}
 | |
| 	case ECDSAx509Key:
 | |
| 		return &ECDSAx509PublicKey{TUFKey: tk}
 | |
| 	case RSAKey:
 | |
| 		return &RSAPublicKey{TUFKey: tk}
 | |
| 	case RSAx509Key:
 | |
| 		return &RSAx509PublicKey{TUFKey: tk}
 | |
| 	case ED25519Key:
 | |
| 		return &ED25519PublicKey{TUFKey: tk}
 | |
| 	}
 | |
| 	return &UnknownPublicKey{TUFKey: tk}
 | |
| }
 | |
| 
 | |
| func typedPrivateKey(tk TUFKey) (PrivateKey, error) {
 | |
| 	private := tk.Value.Private
 | |
| 	tk.Value.Private = nil
 | |
| 	switch tk.Algorithm() {
 | |
| 	case ECDSAKey:
 | |
| 		return NewECDSAPrivateKey(
 | |
| 			&ECDSAPublicKey{
 | |
| 				TUFKey: tk,
 | |
| 			},
 | |
| 			private,
 | |
| 		)
 | |
| 	case ECDSAx509Key:
 | |
| 		return NewECDSAPrivateKey(
 | |
| 			&ECDSAx509PublicKey{
 | |
| 				TUFKey: tk,
 | |
| 			},
 | |
| 			private,
 | |
| 		)
 | |
| 	case RSAKey:
 | |
| 		return NewRSAPrivateKey(
 | |
| 			&RSAPublicKey{
 | |
| 				TUFKey: tk,
 | |
| 			},
 | |
| 			private,
 | |
| 		)
 | |
| 	case RSAx509Key:
 | |
| 		return NewRSAPrivateKey(
 | |
| 			&RSAx509PublicKey{
 | |
| 				TUFKey: tk,
 | |
| 			},
 | |
| 			private,
 | |
| 		)
 | |
| 	case ED25519Key:
 | |
| 		return NewED25519PrivateKey(
 | |
| 			ED25519PublicKey{
 | |
| 				TUFKey: tk,
 | |
| 			},
 | |
| 			private,
 | |
| 		)
 | |
| 	}
 | |
| 	return &UnknownPrivateKey{
 | |
| 		TUFKey:     tk,
 | |
| 		privateKey: privateKey{private: private},
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // NewPublicKey creates a new, correctly typed PublicKey, using the
 | |
| // UnknownPublicKey catchall for unsupported ciphers
 | |
| func NewPublicKey(alg string, public []byte) PublicKey {
 | |
| 	tk := TUFKey{
 | |
| 		Type: alg,
 | |
| 		Value: KeyPair{
 | |
| 			Public: public,
 | |
| 		},
 | |
| 	}
 | |
| 	return typedPublicKey(tk)
 | |
| }
 | |
| 
 | |
| // NewPrivateKey creates a new, correctly typed PrivateKey, using the
 | |
| // UnknownPrivateKey catchall for unsupported ciphers
 | |
| func NewPrivateKey(pubKey PublicKey, private []byte) (PrivateKey, error) {
 | |
| 	tk := TUFKey{
 | |
| 		Type: pubKey.Algorithm(),
 | |
| 		Value: KeyPair{
 | |
| 			Public:  pubKey.Public(),
 | |
| 			Private: private, // typedPrivateKey moves this value
 | |
| 		},
 | |
| 	}
 | |
| 	return typedPrivateKey(tk)
 | |
| }
 | |
| 
 | |
| // UnmarshalPublicKey is used to parse individual public keys in JSON
 | |
| func UnmarshalPublicKey(data []byte) (PublicKey, error) {
 | |
| 	var parsed TUFKey
 | |
| 	err := json.Unmarshal(data, &parsed)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return typedPublicKey(parsed), nil
 | |
| }
 | |
| 
 | |
| // UnmarshalPrivateKey is used to parse individual private keys in JSON
 | |
| func UnmarshalPrivateKey(data []byte) (PrivateKey, error) {
 | |
| 	var parsed TUFKey
 | |
| 	err := json.Unmarshal(data, &parsed)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return typedPrivateKey(parsed)
 | |
| }
 | |
| 
 | |
| // TUFKey is the structure used for both public and private keys in TUF.
 | |
| // Normally it would make sense to use a different structures for public and
 | |
| // private keys, but that would change the key ID algorithm (since the canonical
 | |
| // JSON would be different). This structure should normally be accessed through
 | |
| // the PublicKey or PrivateKey interfaces.
 | |
| type TUFKey struct {
 | |
| 	id    string
 | |
| 	Type  string  `json:"keytype"`
 | |
| 	Value KeyPair `json:"keyval"`
 | |
| }
 | |
| 
 | |
| // Algorithm returns the algorithm of the key
 | |
| func (k TUFKey) Algorithm() string {
 | |
| 	return k.Type
 | |
| }
 | |
| 
 | |
| // ID efficiently generates if necessary, and caches the ID of the key
 | |
| func (k *TUFKey) ID() string {
 | |
| 	if k.id == "" {
 | |
| 		pubK := TUFKey{
 | |
| 			Type: k.Algorithm(),
 | |
| 			Value: KeyPair{
 | |
| 				Public:  k.Public(),
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		}
 | |
| 		data, err := json.MarshalCanonical(&pubK)
 | |
| 		if err != nil {
 | |
| 			logrus.Error("Error generating key ID:", err)
 | |
| 		}
 | |
| 		digest := sha256.Sum256(data)
 | |
| 		k.id = hex.EncodeToString(digest[:])
 | |
| 	}
 | |
| 	return k.id
 | |
| }
 | |
| 
 | |
| // Public returns the public bytes
 | |
| func (k TUFKey) Public() []byte {
 | |
| 	return k.Value.Public
 | |
| }
 | |
| 
 | |
| // Public key types
 | |
| 
 | |
| // ECDSAPublicKey represents an ECDSA key using a raw serialization
 | |
| // of the public key
 | |
| type ECDSAPublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // ECDSAx509PublicKey represents an ECDSA key using an x509 cert
 | |
| // as the serialized format of the public key
 | |
| type ECDSAx509PublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // RSAPublicKey represents an RSA key using a raw serialization
 | |
| // of the public key
 | |
| type RSAPublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // RSAx509PublicKey represents an RSA key using an x509 cert
 | |
| // as the serialized format of the public key
 | |
| type RSAx509PublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // ED25519PublicKey represents an ED25519 key using a raw serialization
 | |
| // of the public key
 | |
| type ED25519PublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // UnknownPublicKey is a catchall for key types that are not supported
 | |
| type UnknownPublicKey struct {
 | |
| 	TUFKey
 | |
| }
 | |
| 
 | |
| // NewECDSAPublicKey initializes a new public key with the ECDSAKey type
 | |
| func NewECDSAPublicKey(public []byte) *ECDSAPublicKey {
 | |
| 	return &ECDSAPublicKey{
 | |
| 		TUFKey: TUFKey{
 | |
| 			Type: ECDSAKey,
 | |
| 			Value: KeyPair{
 | |
| 				Public:  public,
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewECDSAx509PublicKey initializes a new public key with the ECDSAx509Key type
 | |
| func NewECDSAx509PublicKey(public []byte) *ECDSAx509PublicKey {
 | |
| 	return &ECDSAx509PublicKey{
 | |
| 		TUFKey: TUFKey{
 | |
| 			Type: ECDSAx509Key,
 | |
| 			Value: KeyPair{
 | |
| 				Public:  public,
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewRSAPublicKey initializes a new public key with the RSA type
 | |
| func NewRSAPublicKey(public []byte) *RSAPublicKey {
 | |
| 	return &RSAPublicKey{
 | |
| 		TUFKey: TUFKey{
 | |
| 			Type: RSAKey,
 | |
| 			Value: KeyPair{
 | |
| 				Public:  public,
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewRSAx509PublicKey initializes a new public key with the RSAx509Key type
 | |
| func NewRSAx509PublicKey(public []byte) *RSAx509PublicKey {
 | |
| 	return &RSAx509PublicKey{
 | |
| 		TUFKey: TUFKey{
 | |
| 			Type: RSAx509Key,
 | |
| 			Value: KeyPair{
 | |
| 				Public:  public,
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewED25519PublicKey initializes a new public key with the ED25519Key type
 | |
| func NewED25519PublicKey(public []byte) *ED25519PublicKey {
 | |
| 	return &ED25519PublicKey{
 | |
| 		TUFKey: TUFKey{
 | |
| 			Type: ED25519Key,
 | |
| 			Value: KeyPair{
 | |
| 				Public:  public,
 | |
| 				Private: nil,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Private key types
 | |
| type privateKey struct {
 | |
| 	private []byte
 | |
| }
 | |
| 
 | |
| type signer struct {
 | |
| 	signer crypto.Signer
 | |
| }
 | |
| 
 | |
| // ECDSAPrivateKey represents a private ECDSA key
 | |
| type ECDSAPrivateKey struct {
 | |
| 	PublicKey
 | |
| 	privateKey
 | |
| 	signer
 | |
| }
 | |
| 
 | |
| // RSAPrivateKey represents a private RSA key
 | |
| type RSAPrivateKey struct {
 | |
| 	PublicKey
 | |
| 	privateKey
 | |
| 	signer
 | |
| }
 | |
| 
 | |
| // ED25519PrivateKey represents a private ED25519 key
 | |
| type ED25519PrivateKey struct {
 | |
| 	ED25519PublicKey
 | |
| 	privateKey
 | |
| }
 | |
| 
 | |
| // UnknownPrivateKey is a catchall for unsupported key types
 | |
| type UnknownPrivateKey struct {
 | |
| 	TUFKey
 | |
| 	privateKey
 | |
| }
 | |
| 
 | |
| // NewECDSAPrivateKey initializes a new ECDSA private key
 | |
| func NewECDSAPrivateKey(public PublicKey, private []byte) (*ECDSAPrivateKey, error) {
 | |
| 	switch public.(type) {
 | |
| 	case *ECDSAPublicKey, *ECDSAx509PublicKey:
 | |
| 	default:
 | |
| 		return nil, errors.New("invalid public key type provided to NewECDSAPrivateKey")
 | |
| 	}
 | |
| 	ecdsaPrivKey, err := x509.ParseECPrivateKey(private)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &ECDSAPrivateKey{
 | |
| 		PublicKey:  public,
 | |
| 		privateKey: privateKey{private: private},
 | |
| 		signer:     signer{signer: ecdsaPrivKey},
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // NewRSAPrivateKey initialized a new RSA private key
 | |
| func NewRSAPrivateKey(public PublicKey, private []byte) (*RSAPrivateKey, error) {
 | |
| 	switch public.(type) {
 | |
| 	case *RSAPublicKey, *RSAx509PublicKey:
 | |
| 	default:
 | |
| 		return nil, errors.New("invalid public key type provided to NewRSAPrivateKey")
 | |
| 	}
 | |
| 	rsaPrivKey, err := x509.ParsePKCS1PrivateKey(private)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &RSAPrivateKey{
 | |
| 		PublicKey:  public,
 | |
| 		privateKey: privateKey{private: private},
 | |
| 		signer:     signer{signer: rsaPrivKey},
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // NewED25519PrivateKey initialized a new ED25519 private key
 | |
| func NewED25519PrivateKey(public ED25519PublicKey, private []byte) (*ED25519PrivateKey, error) {
 | |
| 	return &ED25519PrivateKey{
 | |
| 		ED25519PublicKey: public,
 | |
| 		privateKey:       privateKey{private: private},
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // Private return the serialized private bytes of the key
 | |
| func (k privateKey) Private() []byte {
 | |
| 	return k.private
 | |
| }
 | |
| 
 | |
| // CryptoSigner returns the underlying crypto.Signer for use cases where we need the default
 | |
| // signature or public key functionality (like when we generate certificates)
 | |
| func (s signer) CryptoSigner() crypto.Signer {
 | |
| 	return s.signer
 | |
| }
 | |
| 
 | |
| // CryptoSigner returns the ED25519PrivateKey which already implements crypto.Signer
 | |
| func (k ED25519PrivateKey) CryptoSigner() crypto.Signer {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CryptoSigner returns the UnknownPrivateKey which already implements crypto.Signer
 | |
| func (k UnknownPrivateKey) CryptoSigner() crypto.Signer {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type ecdsaSig struct {
 | |
| 	R *big.Int
 | |
| 	S *big.Int
 | |
| }
 | |
| 
 | |
| // Sign creates an ecdsa signature
 | |
| func (k ECDSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
 | |
| 	ecdsaPrivKey, ok := k.CryptoSigner().(*ecdsa.PrivateKey)
 | |
| 	if !ok {
 | |
| 		return nil, errors.New("signer was based on the wrong key type")
 | |
| 	}
 | |
| 	hashed := sha256.Sum256(msg)
 | |
| 	sigASN1, err := ecdsaPrivKey.Sign(rand, hashed[:], opts)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	sig := ecdsaSig{}
 | |
| 	_, err = asn1.Unmarshal(sigASN1, &sig)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	rBytes, sBytes := sig.R.Bytes(), sig.S.Bytes()
 | |
| 	octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3
 | |
| 
 | |
| 	// MUST include leading zeros in the output
 | |
| 	rBuf := make([]byte, octetLength-len(rBytes), octetLength)
 | |
| 	sBuf := make([]byte, octetLength-len(sBytes), octetLength)
 | |
| 
 | |
| 	rBuf = append(rBuf, rBytes...)
 | |
| 	sBuf = append(sBuf, sBytes...)
 | |
| 	return append(rBuf, sBuf...), nil
 | |
| }
 | |
| 
 | |
| // Sign creates an rsa signature
 | |
| func (k RSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
 | |
| 	hashed := sha256.Sum256(msg)
 | |
| 	if opts == nil {
 | |
| 		opts = &rsa.PSSOptions{
 | |
| 			SaltLength: rsa.PSSSaltLengthEqualsHash,
 | |
| 			Hash:       crypto.SHA256,
 | |
| 		}
 | |
| 	}
 | |
| 	return k.CryptoSigner().Sign(rand, hashed[:], opts)
 | |
| }
 | |
| 
 | |
| // Sign creates an ed25519 signature
 | |
| func (k ED25519PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
 | |
| 	priv := [ed25519.PrivateKeySize]byte{}
 | |
| 	copy(priv[:], k.private[ed25519.PublicKeySize:])
 | |
| 	return ed25519.Sign(&priv, msg)[:], nil
 | |
| }
 | |
| 
 | |
| // Sign on an UnknownPrivateKey raises an error because the client does not
 | |
| // know how to sign with this key type.
 | |
| func (k UnknownPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
 | |
| 	return nil, errors.New("unknown key type, cannot sign")
 | |
| }
 | |
| 
 | |
| // SignatureAlgorithm returns the SigAlgorithm for a ECDSAPrivateKey
 | |
| func (k ECDSAPrivateKey) SignatureAlgorithm() SigAlgorithm {
 | |
| 	return ECDSASignature
 | |
| }
 | |
| 
 | |
| // SignatureAlgorithm returns the SigAlgorithm for a RSAPrivateKey
 | |
| func (k RSAPrivateKey) SignatureAlgorithm() SigAlgorithm {
 | |
| 	return RSAPSSSignature
 | |
| }
 | |
| 
 | |
| // SignatureAlgorithm returns the SigAlgorithm for a ED25519PrivateKey
 | |
| func (k ED25519PrivateKey) SignatureAlgorithm() SigAlgorithm {
 | |
| 	return EDDSASignature
 | |
| }
 | |
| 
 | |
| // SignatureAlgorithm returns the SigAlgorithm for an UnknownPrivateKey
 | |
| func (k UnknownPrivateKey) SignatureAlgorithm() SigAlgorithm {
 | |
| 	return ""
 | |
| }
 | |
| 
 | |
| // PublicKeyFromPrivate returns a new TUFKey based on a private key, with
 | |
| // the private key bytes guaranteed to be nil.
 | |
| func PublicKeyFromPrivate(pk PrivateKey) PublicKey {
 | |
| 	return typedPublicKey(TUFKey{
 | |
| 		Type: pk.Algorithm(),
 | |
| 		Value: KeyPair{
 | |
| 			Public:  pk.Public(),
 | |
| 			Private: nil,
 | |
| 		},
 | |
| 	})
 | |
| }
 | 
