From 3a873b220c62f52d102efffbc6731a15d7a4640d Mon Sep 17 00:00:00 2001 From: chaosinthecrd Date: Wed, 20 Dec 2023 16:02:54 +0000 Subject: [PATCH] got changes to a point of no errors - need to test functionality with witness Signed-off-by: chaosinthecrd --- run.go | 50 +++++++++++++++++++++++++-------- sign.go | 39 ++++++++++++++++++++++--- signature/envelope/dsse/dsse.go | 49 +++++++++++++++++++------------- signature/envelope/envelope.go | 16 +++++------ source/source.go | 2 +- verify.go | 2 +- 6 files changed, 112 insertions(+), 46 deletions(-) diff --git a/run.go b/run.go index b6ccd2ca..f85c3ca2 100644 --- a/run.go +++ b/run.go @@ -15,7 +15,6 @@ package witness import ( - "bytes" "encoding/json" "fmt" @@ -23,20 +22,29 @@ import ( "github.com/in-toto/go-witness/attestation/environment" "github.com/in-toto/go-witness/attestation/git" "github.com/in-toto/go-witness/cryptoutil" - "github.com/in-toto/go-witness/dsse" + idsse "github.com/in-toto/go-witness/dsse" "github.com/in-toto/go-witness/intoto" + "github.com/in-toto/go-witness/signature/envelope" + dsse "github.com/in-toto/go-witness/signature/envelope/dsse" ) type runOptions struct { stepName string signer cryptoutil.Signer + envelopeType string attestors []attestation.Attestor attestationOpts []attestation.AttestationContextOption - timestampers []dsse.Timestamper + timestampers []idsse.Timestamper } type RunOption func(ro *runOptions) +func RunWithEnvelopeType(envelopeType string) RunOption { + return func(ro *runOptions) { + ro.envelopeType = envelopeType + } +} + func RunWithAttestors(attestors []attestation.Attestor) RunOption { return func(ro *runOptions) { ro.attestors = attestors @@ -49,7 +57,7 @@ func RunWithAttestationOpts(opts ...attestation.AttestationContextOption) RunOpt } } -func RunWithTimestampers(ts ...dsse.Timestamper) RunOption { +func RunWithTimestampers(ts ...idsse.Timestamper) RunOption { return func(ro *runOptions) { ro.timestampers = ts } @@ -57,7 +65,7 @@ func RunWithTimestampers(ts ...dsse.Timestamper) RunOption { type RunResult struct { Collection attestation.Collection - SignedEnvelope dsse.Envelope + SignedEnvelope envelope.Envelope } func Run(stepName string, signer cryptoutil.Signer, opts ...RunOption) (RunResult, error) { @@ -86,11 +94,13 @@ func Run(stepName string, signer cryptoutil.Signer, opts ...RunOption) (RunResul } result.Collection = attestation.NewCollection(ro.stepName, runCtx.CompletedAttestors()) - result.SignedEnvelope, err = signCollection(result.Collection, dsse.SignWithSigners(ro.signer), dsse.SignWithTimestampers(ro.timestampers...)) + se, err := signCollection(result.Collection, ro.signer, ro.envelopeType) if err != nil { return result, fmt.Errorf("failed to sign collection: %w", err) } + result.SignedEnvelope = *se + return result, nil } @@ -106,21 +116,39 @@ func validateRunOpts(ro runOptions) error { return nil } -func signCollection(collection attestation.Collection, opts ...dsse.SignOption) (dsse.Envelope, error) { +func signCollection(collection attestation.Collection, signer cryptoutil.Signer, envelopeType string) (*envelope.Envelope, error) { data, err := json.Marshal(&collection) if err != nil { - return dsse.Envelope{}, err + return nil, err } stmt, err := intoto.NewStatement(attestation.CollectionType, data, collection.Subjects()) if err != nil { - return dsse.Envelope{}, err + return nil, err } stmtJson, err := json.Marshal(&stmt) if err != nil { - return dsse.Envelope{}, err + return nil, err + } + + var env envelope.Envelope + switch envelopeType { + case "dsse": + env = &dsse.Envelope{ + Envelope: &idsse.Envelope{ + PayloadType: intoto.PayloadType, + Payload: string(stmtJson), + }, + } + default: + return nil, fmt.Errorf("envelope type %s not recognized", envelopeType) + } + + err = env.Sign(&signer) + if err != nil { + return nil, err } - return dsse.Sign(intoto.PayloadType, bytes.NewReader(stmtJson), opts...) + return &env, nil } diff --git a/sign.go b/sign.go index c2d0a58e..2ff3dd66 100644 --- a/sign.go +++ b/sign.go @@ -16,17 +16,48 @@ package witness import ( "encoding/json" + "fmt" "io" - "github.com/in-toto/go-witness/dsse" + "github.com/in-toto/go-witness/cryptoutil" + idsse "github.com/in-toto/go-witness/dsse" + "github.com/in-toto/go-witness/intoto" + "github.com/in-toto/go-witness/signature/envelope" + dsse "github.com/in-toto/go-witness/signature/envelope/dsse" ) -func Sign(r io.Reader, dataType string, w io.Writer, opts ...dsse.SignOption) error { - env, err := dsse.Sign(dataType, r, opts...) +type signOptions struct { + signer cryptoutil.Signer + envelopeType string +} + +type SignOption func(ro *signOptions) + +func SignWithEnvelopeType(envelopeType string) SignOption { + return func(so *signOptions) { + so.envelopeType = envelopeType + } +} + +func Sign(s cryptoutil.Signer, r io.Reader, dataType string, w io.Writer, envelopeType string) error { + stmtJson, err := io.ReadAll(r) + var env envelope.Envelope + switch envelopeType { + case "dsse": + env = &dsse.Envelope{ + Envelope: &idsse.Envelope{ + PayloadType: intoto.PayloadType, + Payload: string([]byte(stmtJson)), + }, + } + default: + return fmt.Errorf("envelope type %s not recognized", envelopeType) + } + + err = env.Sign(&s) if err != nil { return err } - encoder := json.NewEncoder(w) return encoder.Encode(&env) } diff --git a/signature/envelope/dsse/dsse.go b/signature/envelope/dsse/dsse.go index 50c924f3..67d446f3 100644 --- a/signature/envelope/dsse/dsse.go +++ b/signature/envelope/dsse/dsse.go @@ -1,49 +1,58 @@ package dsse import ( - "crypto" "fmt" "github.com/in-toto/go-witness/cryptoutil" + "github.com/in-toto/go-witness/signature/envelope" + // Eventually we will migrate to using github.com/securesystemslab/dsse // but for now it doesn't support timestamps and intermediates idsse "github.com/in-toto/go-witness/dsse" ) -type DSSEEnvelope struct { +type Envelope struct { Envelope *idsse.Envelope } -func (e *DSSEEnvelope) Sign(signer *crypto.Signer, opts ...cryptoutil.SignerOption) (interface{}, error) { +func (e *Envelope) Sign(signer *cryptoutil.Signer) error { if e.Envelope.PayloadType == "" || e.Envelope.Payload == "" { - return nil, fmt.Errorf("PayloadType and Payload not populated correctly") + return fmt.Errorf("PayloadType and Payload not populated correctly") } - s, err := cryptoutil.NewSigner(signer, opts...) + se, err := idsse.Sign(e.Envelope.PayloadType, []byte(e.Envelope.Payload), idsse.SignWithSigners(*signer)) if err != nil { - return nil, err + return err } - se, err := idsse.Sign(e.Envelope.PayloadType, []byte(e.Envelope.Payload), idsse.SignWithSigners(s)) - if err != nil { - return nil, err - } + e.Envelope = &se - return se, nil + return nil } -func (e *DSSEEnvelope) Verify(pub *crypto.PublicKey, opts ...cryptoutil.VerifierOption) (interface{}, error) { - v, err := cryptoutil.NewVerifier(pub, opts...) +func (e *Envelope) Verify(v *cryptoutil.Verifier) error { + _, err := e.Envelope.Verify(idsse.VerifyWithVerifiers(*v)) if err != nil { - return nil, err + return err } - ve, err := e.Envelope.Verify(idsse.VerifyWithVerifiers(v)) - if err != nil { - return nil, err + return nil +} + +func (e *Envelope) Content() (*envelope.EnvelopeContent, error) { + env := envelope.EnvelopeContent{} + env.Payload = e.Envelope.Payload + env.PayloadType = e.Envelope.PayloadType + for _, sig := range e.Envelope.Signatures { + s := envelope.SignatureInfo{ + KeyID: sig.KeyID, + Signature: sig.Signature, + Certificate: sig.Certificate, + Intermediates: sig.Intermediates, + } + + env.Signatures = append(env.Signatures, s) } - return ve, nil + return &env, nil } - -func (e *DSSEEnvelope) Content() (interface{}, error) diff --git a/signature/envelope/envelope.go b/signature/envelope/envelope.go index 2693003a..d0ff7298 100644 --- a/signature/envelope/envelope.go +++ b/signature/envelope/envelope.go @@ -1,23 +1,21 @@ package envelope import ( - "crypto" - "github.com/in-toto/go-witness/cryptoutil" ) // Envelope provides basic functions to manipulate signatures. type Envelope interface { // Sign generates and sign the envelope according to the sign request. - Sign(signer *crypto.Signer, opts ...cryptoutil.SignerOption) (interface{}, error) + Sign(signer *cryptoutil.Signer) error // Verify verifies the envelope and returns its enclosed payload and signer // info. - Verify(pub *crypto.PublicKey, opts ...cryptoutil.VerifierOption) (interface{}, error) + Verify(pub *cryptoutil.Verifier) error // Content returns the payload and signer information of the envelope. // Content is trusted only after the successful call to `Verify()`. - Content() (EnvelopeContent, error) + Content() (*EnvelopeContent, error) } type EnvelopeContent struct { @@ -27,8 +25,8 @@ type EnvelopeContent struct { } type SignatureInfo struct { - // NOTE: Made this a string for now but I think it might be better in antother form later - SignatureAlgorithm string - - Signature []byte + KeyID string `json:"keyid"` + Signature []byte `json:"sig"` + Certificate []byte `json:"certificate,omitempty"` + Intermediates [][]byte `json:"intermediates,omitempty"` } diff --git a/source/source.go b/source/source.go index 1aad2bbd..3b7d3fcf 100644 --- a/source/source.go +++ b/source/source.go @@ -36,7 +36,7 @@ type Sourcer interface { func envelopeToCollectionEnvelope(reference string, env dsse.Envelope) (CollectionEnvelope, error) { statement := intoto.Statement{} - if err := json.Unmarshal(env.Payload, &statement); err != nil { + if err := json.Unmarshal([]byte(env.Payload), &statement); err != nil { return CollectionEnvelope{}, err } diff --git a/verify.go b/verify.go index bb20df6b..e8c89910 100644 --- a/verify.go +++ b/verify.go @@ -81,7 +81,7 @@ func Verify(ctx context.Context, policyEnvelope dsse.Envelope, policyVerifiers [ } pol := policy.Policy{} - if err := json.Unmarshal(vo.policyEnvelope.Payload, &pol); err != nil { + if err := json.Unmarshal([]byte(vo.policyEnvelope.Payload), &pol); err != nil { return nil, fmt.Errorf("failed to unmarshal policy from envelope: %w", err) }