mirror of https://github.com/docker/buildx.git
99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
package signerverifier
|
|
|
|
import (
|
|
"context"
|
|
"crypto"
|
|
"crypto/ed25519"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
const ED25519KeyType = "ed25519"
|
|
|
|
// ED25519SignerVerifier is a dsse.SignerVerifier compliant interface to sign
|
|
// and verify signatures using ED25519 keys.
|
|
type ED25519SignerVerifier struct {
|
|
keyID string
|
|
private ed25519.PrivateKey
|
|
public ed25519.PublicKey
|
|
}
|
|
|
|
// NewED25519SignerVerifierFromSSLibKey creates an Ed25519SignerVerifier from an
|
|
// SSLibKey.
|
|
func NewED25519SignerVerifierFromSSLibKey(key *SSLibKey) (*ED25519SignerVerifier, error) {
|
|
if len(key.KeyVal.Public) == 0 {
|
|
return nil, ErrInvalidKey
|
|
}
|
|
|
|
public, err := hex.DecodeString(key.KeyVal.Public)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to create ED25519 signerverifier: %w", err)
|
|
}
|
|
|
|
var private []byte
|
|
if len(key.KeyVal.Private) > 0 {
|
|
private, err = hex.DecodeString(key.KeyVal.Private)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to create ED25519 signerverifier: %w", err)
|
|
}
|
|
|
|
// python-securesystemslib provides an interface to generate ed25519
|
|
// keys but it differs slightly in how it serializes the key to disk.
|
|
// Specifically, the keyval.private field includes _only_ the private
|
|
// portion of the key while libraries such as crypto/ed25519 also expect
|
|
// the public portion. So, if the private portion is half of what we
|
|
// expect, we append the public portion as well.
|
|
if len(private) == ed25519.PrivateKeySize/2 {
|
|
private = append(private, public...)
|
|
}
|
|
}
|
|
|
|
return &ED25519SignerVerifier{
|
|
keyID: key.KeyID,
|
|
public: ed25519.PublicKey(public),
|
|
private: ed25519.PrivateKey(private),
|
|
}, nil
|
|
}
|
|
|
|
// Sign creates a signature for `data`.
|
|
func (sv *ED25519SignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
|
|
if len(sv.private) == 0 {
|
|
return nil, ErrNotPrivateKey
|
|
}
|
|
|
|
signature := ed25519.Sign(sv.private, data)
|
|
return signature, nil
|
|
}
|
|
|
|
// Verify verifies the `sig` value passed in against `data`.
|
|
func (sv *ED25519SignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
|
|
if ok := ed25519.Verify(sv.public, data, sig); ok {
|
|
return nil
|
|
}
|
|
return ErrSignatureVerificationFailed
|
|
}
|
|
|
|
// KeyID returns the identifier of the key used to create the
|
|
// ED25519SignerVerifier instance.
|
|
func (sv *ED25519SignerVerifier) KeyID() (string, error) {
|
|
return sv.keyID, nil
|
|
}
|
|
|
|
// Public returns the public portion of the key used to create the
|
|
// ED25519SignerVerifier instance.
|
|
func (sv *ED25519SignerVerifier) Public() crypto.PublicKey {
|
|
return sv.public
|
|
}
|
|
|
|
// LoadED25519KeyFromFile returns an SSLibKey instance for an ED25519 key stored
|
|
// in a file in the custom securesystemslib format.
|
|
func LoadED25519KeyFromFile(path string) (*SSLibKey, error) {
|
|
contents, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to load ED25519 key from file: %w", err)
|
|
}
|
|
|
|
return loadKeyFromSSLibBytes(contents)
|
|
}
|