...

Source file src/github.com/theupdateframework/go-tuf/pkg/keys/ecdsa.go

Documentation: github.com/theupdateframework/go-tuf/pkg/keys

     1  package keys
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"crypto/x509"
    10  	"encoding/json"
    11  	"encoding/pem"
    12  	"errors"
    13  	"fmt"
    14  	"io"
    15  
    16  	"github.com/theupdateframework/go-tuf/data"
    17  )
    18  
    19  func init() {
    20  	// Note: we use LoadOrStore here to prevent accidentally overriding the
    21  	// an explicit deprecated ECDSA verifier.
    22  	// TODO: When deprecated ECDSA is removed, this can switch back to Store.
    23  	VerifierMap.LoadOrStore(data.KeyTypeECDSA_SHA2_P256_OLD_FMT, NewEcdsaVerifier)
    24  	VerifierMap.LoadOrStore(data.KeyTypeECDSA_SHA2_P256, NewEcdsaVerifier)
    25  	SignerMap.Store(data.KeyTypeECDSA_SHA2_P256_OLD_FMT, newEcdsaSigner)
    26  	SignerMap.Store(data.KeyTypeECDSA_SHA2_P256, newEcdsaSigner)
    27  }
    28  
    29  func NewEcdsaVerifier() Verifier {
    30  	return &EcdsaVerifier{}
    31  }
    32  
    33  func newEcdsaSigner() Signer {
    34  	return &ecdsaSigner{}
    35  }
    36  
    37  type EcdsaVerifier struct {
    38  	PublicKey *PKIXPublicKey `json:"public"`
    39  	ecdsaKey  *ecdsa.PublicKey
    40  	key       *data.PublicKey
    41  }
    42  
    43  func (p *EcdsaVerifier) Public() string {
    44  	// This is already verified to succeed when unmarshalling a public key.
    45  	r, err := x509.MarshalPKIXPublicKey(p.ecdsaKey)
    46  	if err != nil {
    47  		// TODO: Gracefully handle these errors.
    48  		// See https://github.com/theupdateframework/go-tuf/issues/363
    49  		panic(err)
    50  	}
    51  	return string(r)
    52  }
    53  
    54  func (p *EcdsaVerifier) Verify(msg, sigBytes []byte) error {
    55  	hash := sha256.Sum256(msg)
    56  
    57  	if !ecdsa.VerifyASN1(p.ecdsaKey, hash[:], sigBytes) {
    58  		return errors.New("tuf: ecdsa signature verification failed")
    59  	}
    60  	return nil
    61  }
    62  
    63  func (p *EcdsaVerifier) MarshalPublicKey() *data.PublicKey {
    64  	return p.key
    65  }
    66  
    67  func (p *EcdsaVerifier) UnmarshalPublicKey(key *data.PublicKey) error {
    68  	// Prepare decoder limited to 512Kb
    69  	dec := json.NewDecoder(io.LimitReader(bytes.NewReader(key.Value), MaxJSONKeySize))
    70  
    71  	// Unmarshal key value
    72  	if err := dec.Decode(p); err != nil {
    73  		if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
    74  			return fmt.Errorf("tuf: the public key is truncated or too large: %w", err)
    75  		}
    76  		return err
    77  	}
    78  
    79  	ecdsaKey, ok := p.PublicKey.PublicKey.(*ecdsa.PublicKey)
    80  	if !ok {
    81  		return fmt.Errorf("invalid public key")
    82  	}
    83  
    84  	if _, err := x509.MarshalPKIXPublicKey(ecdsaKey); err != nil {
    85  		return fmt.Errorf("marshalling to PKIX key: invalid public key")
    86  	}
    87  
    88  	p.ecdsaKey = ecdsaKey
    89  	p.key = key
    90  	return nil
    91  }
    92  
    93  type ecdsaSigner struct {
    94  	*ecdsa.PrivateKey
    95  }
    96  
    97  type ecdsaPrivateKeyValue struct {
    98  	Private string         `json:"private"`
    99  	Public  *PKIXPublicKey `json:"public"`
   100  }
   101  
   102  func (s *ecdsaSigner) PublicData() *data.PublicKey {
   103  	// This uses a trusted public key JSON format with a trusted Public value.
   104  	keyValBytes, _ := json.Marshal(EcdsaVerifier{PublicKey: &PKIXPublicKey{PublicKey: s.Public()}})
   105  	return &data.PublicKey{
   106  		Type:       data.KeyTypeECDSA_SHA2_P256,
   107  		Scheme:     data.KeySchemeECDSA_SHA2_P256,
   108  		Algorithms: data.HashAlgorithms,
   109  		Value:      keyValBytes,
   110  	}
   111  }
   112  
   113  func (s *ecdsaSigner) SignMessage(message []byte) ([]byte, error) {
   114  	hash := sha256.Sum256(message)
   115  	return ecdsa.SignASN1(rand.Reader, s.PrivateKey, hash[:])
   116  }
   117  
   118  func (s *ecdsaSigner) MarshalPrivateKey() (*data.PrivateKey, error) {
   119  	priv, err := x509.MarshalECPrivateKey(s.PrivateKey)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	pemKey := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: priv})
   124  	val, err := json.Marshal(ecdsaPrivateKeyValue{
   125  		Private: string(pemKey),
   126  		Public:  &PKIXPublicKey{PublicKey: s.Public()},
   127  	})
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	return &data.PrivateKey{
   132  		Type:       data.KeyTypeECDSA_SHA2_P256,
   133  		Scheme:     data.KeySchemeECDSA_SHA2_P256,
   134  		Algorithms: data.HashAlgorithms,
   135  		Value:      val,
   136  	}, nil
   137  }
   138  
   139  func (s *ecdsaSigner) UnmarshalPrivateKey(key *data.PrivateKey) error {
   140  	val := ecdsaPrivateKeyValue{}
   141  	if err := json.Unmarshal(key.Value, &val); err != nil {
   142  		return err
   143  	}
   144  	block, _ := pem.Decode([]byte(val.Private))
   145  	if block == nil {
   146  		return errors.New("invalid PEM value")
   147  	}
   148  	if block.Type != "EC PRIVATE KEY" {
   149  		return fmt.Errorf("invalid block type: %s", block.Type)
   150  	}
   151  	k, err := x509.ParseECPrivateKey(block.Bytes)
   152  	if err != nil {
   153  		return err
   154  	}
   155  	if k.Curve != elliptic.P256() {
   156  		return errors.New("unsupported ecdsa curve")
   157  	}
   158  	if _, err := json.Marshal(EcdsaVerifier{
   159  		PublicKey: &PKIXPublicKey{PublicKey: k.Public()}}); err != nil {
   160  		return fmt.Errorf("invalid public key: %s", err)
   161  	}
   162  
   163  	s.PrivateKey = k
   164  	return nil
   165  }
   166  
   167  func GenerateEcdsaKey() (*ecdsaSigner, error) {
   168  	privkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	return &ecdsaSigner{privkey}, nil
   173  }
   174  

View as plain text