api: add functions to transparently handle signatures upon API interaction (#2142)

This commit is contained in:
Otto Bittner 2023-08-01 16:48:13 +02:00 committed by GitHub
parent 002c3a9a32
commit dac690656e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 707 additions and 472 deletions

View file

@ -12,37 +12,47 @@ import (
"encoding/base64"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/sigstore/sigstore/pkg/cryptoutils"
sigsig "github.com/sigstore/sigstore/pkg/signature"
)
// Verifier checks if the signature of content can be verified.
type Verifier interface {
VerifySignature(content, signature, publicKey []byte) error
VerifySignature(content, signature []byte) error
}
// CosignVerifier checks if the signature of content can be verified
// using a cosign public key.
type CosignVerifier struct{}
// CosignVerifier wraps a public key that can be used for verifying signatures.
type CosignVerifier struct {
publicKey crypto.PublicKey
}
// NewCosignVerifier unmarshalls and validates the given pem encoded public key and returns a new CosignVerifier.
func NewCosignVerifier(pem []byte) (Verifier, error) {
pubkey, err := cryptoutils.UnmarshalPEMToPublicKey(pem)
if err != nil {
return CosignVerifier{}, fmt.Errorf("unable to parse public key: %w", err)
}
if err := cryptoutils.ValidatePubKey(pubkey); err != nil {
return CosignVerifier{}, fmt.Errorf("unable to validate public key: %w", err)
}
return CosignVerifier{pubkey}, nil
}
// VerifySignature checks if the signature of content can be verified
// using publicKey.
// signature is expected to be base64 encoded.
// publicKey is expected to be PEM encoded.
func (CosignVerifier) VerifySignature(content, signature, publicKey []byte) error {
func (c CosignVerifier) VerifySignature(content, signature []byte) error {
// LoadVerifier would also error if no public key is set.
// However, this error message should be easier to debug.
if c.publicKey == nil {
return fmt.Errorf("no public key set")
}
sigRaw := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(signature))
pubKeyRaw, err := cryptoutils.UnmarshalPEMToPublicKey(publicKey)
if err != nil {
return fmt.Errorf("unable to parse public key: %w", err)
}
if err := cryptoutils.ValidatePubKey(pubKeyRaw); err != nil {
return fmt.Errorf("unable to validate public key: %w", err)
}
verifier, err := sigsig.LoadVerifier(pubKeyRaw, crypto.SHA256)
verifier, err := sigsig.LoadVerifier(c.publicKey, crypto.SHA256)
if err != nil {
return fmt.Errorf("unable to load verifier: %w", err)
}
@ -53,14 +63,3 @@ func (CosignVerifier) VerifySignature(content, signature, publicKey []byte) erro
return nil
}
// CosignPublicKeyForVersion returns the public key for the given version.
func CosignPublicKeyForVersion(ver versionsapi.Version) ([]byte, error) {
if err := ver.Validate(); err != nil {
return nil, fmt.Errorf("selecting public key: invalid version %s: %w", ver.ShortPath(), err)
}
if ver.Ref == versionsapi.ReleaseRef && ver.Stream == "stable" {
return []byte(constants.CosignPublicKeyReleases), nil
}
return []byte(constants.CosignPublicKeyDev), nil
}