...

Source file src/github.com/secure-systems-lab/go-securesystemslib/signerverifier/ecdsa.go

Documentation: github.com/secure-systems-lab/go-securesystemslib/signerverifier

     1  package signerverifier
     2  
     3  import (
     4  	"context"
     5  	"crypto"
     6  	"crypto/ecdsa"
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"crypto/sha512"
    10  	"fmt"
    11  	"os"
    12  )
    13  
    14  const ECDSAKeyType = "ecdsa"
    15  
    16  // ECDSASignerVerifier is a dsse.SignerVerifier compliant interface to sign and
    17  // verify signatures using ECDSA keys.
    18  type ECDSASignerVerifier struct {
    19  	keyID     string
    20  	curveSize int
    21  	private   *ecdsa.PrivateKey
    22  	public    *ecdsa.PublicKey
    23  }
    24  
    25  // NewECDSASignerVerifierFromSSLibKey creates an ECDSASignerVerifier from an
    26  // SSLibKey.
    27  func NewECDSASignerVerifierFromSSLibKey(key *SSLibKey) (*ECDSASignerVerifier, error) {
    28  	if len(key.KeyVal.Public) == 0 {
    29  		return nil, ErrInvalidKey
    30  	}
    31  
    32  	_, publicParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Public))
    33  	if err != nil {
    34  		return nil, fmt.Errorf("unable to create ECDSA signerverifier: %w", err)
    35  	}
    36  
    37  	sv := &ECDSASignerVerifier{
    38  		keyID:     key.KeyID,
    39  		curveSize: publicParsedKey.(*ecdsa.PublicKey).Params().BitSize,
    40  		public:    publicParsedKey.(*ecdsa.PublicKey),
    41  		private:   nil,
    42  	}
    43  
    44  	if len(key.KeyVal.Private) > 0 {
    45  		_, privateParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Private))
    46  		if err != nil {
    47  			return nil, fmt.Errorf("unable to create ECDSA signerverifier: %w", err)
    48  		}
    49  
    50  		sv.private = privateParsedKey.(*ecdsa.PrivateKey)
    51  	}
    52  
    53  	return sv, nil
    54  }
    55  
    56  // Sign creates a signature for `data`.
    57  func (sv *ECDSASignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
    58  	if sv.private == nil {
    59  		return nil, ErrNotPrivateKey
    60  	}
    61  
    62  	hashedData := getECDSAHashedData(data, sv.curveSize)
    63  
    64  	return ecdsa.SignASN1(rand.Reader, sv.private, hashedData)
    65  }
    66  
    67  // Verify verifies the `sig` value passed in against `data`.
    68  func (sv *ECDSASignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
    69  	hashedData := getECDSAHashedData(data, sv.curveSize)
    70  
    71  	if ok := ecdsa.VerifyASN1(sv.public, hashedData, sig); !ok {
    72  		return ErrSignatureVerificationFailed
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  // KeyID returns the identifier of the key used to create the
    79  // ECDSASignerVerifier instance.
    80  func (sv *ECDSASignerVerifier) KeyID() (string, error) {
    81  	return sv.keyID, nil
    82  }
    83  
    84  // Public returns the public portion of the key used to create the
    85  // ECDSASignerVerifier instance.
    86  func (sv *ECDSASignerVerifier) Public() crypto.PublicKey {
    87  	return sv.public
    88  }
    89  
    90  // LoadECDSAKeyFromFile returns an SSLibKey instance for an ECDSA key stored in
    91  // a file in the custom securesystemslib format.
    92  func LoadECDSAKeyFromFile(path string) (*SSLibKey, error) {
    93  	contents, err := os.ReadFile(path)
    94  	if err != nil {
    95  		return nil, fmt.Errorf("unable to load ECDSA key from file: %w", err)
    96  	}
    97  
    98  	return LoadKeyFromSSLibBytes(contents)
    99  }
   100  
   101  func getECDSAHashedData(data []byte, curveSize int) []byte {
   102  	switch {
   103  	case curveSize <= 256:
   104  		return hashBeforeSigning(data, sha256.New())
   105  	case 256 < curveSize && curveSize <= 384:
   106  		return hashBeforeSigning(data, sha512.New384())
   107  	case curveSize > 384:
   108  		return hashBeforeSigning(data, sha512.New())
   109  	}
   110  	return []byte{}
   111  }
   112  

View as plain text