Files
attest/pkg/signerverifier/common.go
Jonny Stoten 1a7897a052 Return VSA and rich errors from verification (#38)
* Start of richer results from verification

* Pull out VSA code from signing

* Expose attestation signing fns

* Add VSA test

* Notes for policy result

* Require separate policy for VSA creation

* Load test signing key from tests

* Return rich object from policy

* Add result object schema and fix tests

* Ensure example test runs

* Remove data.yaml files from mock policies

* Don't run example - TUF policy isn't compatible

* Add attestation to manifests for all subjects

* Ensure adding attestation doesn't touch statements

* Don't export sign function

* Remove attestations from VerificationResult

* Change bool to Outcome enum in result

* Use outputLayout directly

* Make clearer that Outcome strings are for VSA

* Return multiple SLSA levels from policy

* Fix unmarshalling of policy-id (#39)

* Rename function

* Rename policy.VerificationResult -> policy.Result

* Re-add test for canonical input

---------

Co-authored-by: James Carnegie <james.carnegie@docker.com>
Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
2024-05-22 14:49:23 +01:00

85 lines
1.9 KiB
Go

package signerverifier
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/docker/attest/internal/util"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
type ECDSA256_SignerVerifier struct {
crypto.Signer
}
// implement keyid function
func (s *ECDSA256_SignerVerifier) KeyID() (string, error) {
keyid, err := KeyID(s.Signer.Public())
if err != nil {
return "", fmt.Errorf("error getting keyid: %w", err)
}
return keyid, nil
}
func (s *ECDSA256_SignerVerifier) Public() crypto.PublicKey {
return s.Signer.Public()
}
func (s *ECDSA256_SignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
return s.Signer.Sign(rand.Reader, data, crypto.SHA256)
}
func (s *ECDSA256_SignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
pub, ok := s.Signer.Public().(*ecdsa.PublicKey)
if !ok {
return fmt.Errorf("public key is not ecdsa")
}
ok = ecdsa.VerifyASN1(pub, util.SHA256(data), sig)
if !ok {
return fmt.Errorf("payload signature is not valid")
}
return nil
}
func LoadKeyPair(priv []byte) (dsse.SignerVerifier, error) {
privateKey, err := parsePriv(priv)
if err != nil {
return nil, err
}
return &ECDSA256_SignerVerifier{
Signer: privateKey,
}, nil
}
func parsePriv(privkeyBytes []byte) (*ecdsa.PrivateKey, error) {
p, _ := pem.Decode(privkeyBytes)
if p == nil {
return nil, fmt.Errorf("privkey file does not contain any PEM data")
}
if p.Type != "EC PRIVATE KEY" {
return nil, fmt.Errorf("privkey file does not contain a priavte key")
}
privKey, err := x509.ParseECPrivateKey(p.Bytes)
if err != nil {
return nil, fmt.Errorf("error failed to parse public key: %w", err)
}
return privKey, nil
}
func GenKeyPair() (dsse.SignerVerifier, error) {
signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
return &ECDSA256_SignerVerifier{
Signer: signer,
}, nil
}