...

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

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

     1  package signerverifier
     2  
     3  import (
     4  	"context"
     5  	"crypto"
     6  	"crypto/ed25519"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"os"
    10  )
    11  
    12  const ED25519KeyType = "ed25519"
    13  
    14  // ED25519SignerVerifier is a dsse.SignerVerifier compliant interface to sign
    15  // and verify signatures using ED25519 keys.
    16  type ED25519SignerVerifier struct {
    17  	keyID   string
    18  	private ed25519.PrivateKey
    19  	public  ed25519.PublicKey
    20  }
    21  
    22  // NewED25519SignerVerifierFromSSLibKey creates an Ed25519SignerVerifier from an
    23  // SSLibKey.
    24  func NewED25519SignerVerifierFromSSLibKey(key *SSLibKey) (*ED25519SignerVerifier, error) {
    25  	if len(key.KeyVal.Public) == 0 {
    26  		return nil, ErrInvalidKey
    27  	}
    28  
    29  	public, err := hex.DecodeString(key.KeyVal.Public)
    30  	if err != nil {
    31  		return nil, fmt.Errorf("unable to create ED25519 signerverifier: %w", err)
    32  	}
    33  
    34  	var private []byte
    35  	if len(key.KeyVal.Private) > 0 {
    36  		private, err = hex.DecodeString(key.KeyVal.Private)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("unable to create ED25519 signerverifier: %w", err)
    39  		}
    40  
    41  		// python-securesystemslib provides an interface to generate ed25519
    42  		// keys but it differs slightly in how it serializes the key to disk.
    43  		// Specifically, the keyval.private field includes _only_ the private
    44  		// portion of the key while libraries such as crypto/ed25519 also expect
    45  		// the public portion. So, if the private portion is half of what we
    46  		// expect, we append the public portion as well.
    47  		if len(private) == ed25519.PrivateKeySize/2 {
    48  			private = append(private, public...)
    49  		}
    50  	}
    51  
    52  	return &ED25519SignerVerifier{
    53  		keyID:   key.KeyID,
    54  		public:  ed25519.PublicKey(public),
    55  		private: ed25519.PrivateKey(private),
    56  	}, nil
    57  }
    58  
    59  // Sign creates a signature for `data`.
    60  func (sv *ED25519SignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
    61  	if len(sv.private) == 0 {
    62  		return nil, ErrNotPrivateKey
    63  	}
    64  
    65  	signature := ed25519.Sign(sv.private, data)
    66  	return signature, nil
    67  }
    68  
    69  // Verify verifies the `sig` value passed in against `data`.
    70  func (sv *ED25519SignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
    71  	if ok := ed25519.Verify(sv.public, data, sig); ok {
    72  		return nil
    73  	}
    74  	return ErrSignatureVerificationFailed
    75  }
    76  
    77  // KeyID returns the identifier of the key used to create the
    78  // ED25519SignerVerifier instance.
    79  func (sv *ED25519SignerVerifier) KeyID() (string, error) {
    80  	return sv.keyID, nil
    81  }
    82  
    83  // Public returns the public portion of the key used to create the
    84  // ED25519SignerVerifier instance.
    85  func (sv *ED25519SignerVerifier) Public() crypto.PublicKey {
    86  	return sv.public
    87  }
    88  
    89  // LoadED25519KeyFromFile returns an SSLibKey instance for an ED25519 key stored
    90  // in a file in the custom securesystemslib format.
    91  func LoadED25519KeyFromFile(path string) (*SSLibKey, error) {
    92  	contents, err := os.ReadFile(path)
    93  	if err != nil {
    94  		return nil, fmt.Errorf("unable to load ED25519 key from file: %w", err)
    95  	}
    96  
    97  	return LoadKeyFromSSLibBytes(contents)
    98  }
    99  

View as plain text