Skip to content

Commit

Permalink
verify: verify checkpoint's STH against the inclusion proof root hash (
Browse files Browse the repository at this point in the history
…#1092)

* verify: verify checkpoint signature STH against the inclusion proof root hash

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa authored Oct 3, 2022
1 parent a859807 commit e4a7a41
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
10 changes: 10 additions & 0 deletions pkg/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ func VerifyCheckpointSignature(e *models.LogEntryAnon, verifier signature.Verifi
if !sth.Verify(verifier) {
return errors.New("signature on checkpoint did not verify")
}
rootHash, err := hex.DecodeString(*e.Verification.InclusionProof.RootHash)
if err != nil {
return errors.New("decoding inclusion proof root has")
}

if !bytes.EqualFold(rootHash, sth.Hash) {
return fmt.Errorf("proof root hash does not match signed tree head, expected %s got %s",
*e.Verification.InclusionProof.RootHash,
hex.EncodeToString(sth.Hash))
}
return nil
}

Expand Down
82 changes: 82 additions & 0 deletions pkg/verify/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ package verify

import (
"context"
"crypto/sha256"
"encoding/hex"
"testing"

"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/google/trillian/types"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/tlog"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/rekor/pkg/util"
"github.com/sigstore/sigstore/pkg/signature"
)

type TlogClient struct {
Expand Down Expand Up @@ -223,3 +226,82 @@ func TestInclusion(t *testing.T) {
})
}
}

func TestCheckpoint(t *testing.T) {
hostname := "rekor.localhost"
treeID := int64(123)
rootHash := sha256.Sum256([]byte{1, 2, 3})
rootHashString := hex.EncodeToString(rootHash[:])
treeSize := uint64(42)
signer, _, err := signature.NewDefaultECDSASignerVerifier()
if err != nil {
t.Fatalf("error generating signer: %v", err)
}
ctx := context.Background()
scBytes, err := util.CreateAndSignCheckpoint(ctx, hostname, treeID, &types.LogRootV1{TreeSize: treeSize, RootHash: rootHash[:]}, signer)
if err != nil {
t.Fatalf("error creating signed checkpoint: %v", err)
}

time := int64(1661794812)
logID := "1701474e8cb504dbb853a5887bc2cf66936b0f36d2641bfb61f1abae80088e6a"

for _, test := range []struct {
name string
e models.LogEntryAnon
wantErr bool
}{
{
name: "valid checkpoint",
e: models.LogEntryAnon{
Body: "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJlY2RjNTUzNmY3M2JkYWU4ODE2ZjBlYTQwNzI2ZWY1ZTliODEwZDkxNDQ5MzA3NTkwM2JiOTA2MjNkOTdiMWQ4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUQvUGRQUW1LV0MxKzBCTkVkNWdLdlFHcjF4eGwzaWVVZmZ2M2prMXp6Skt3SWhBTEJqM3hmQXlXeGx6NGpwb0lFSVYxVWZLOXZua1VVT1NvZVp4QlpQSEtQQyIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQlFWVUpNU1VNZ1MwVlpMUzB0TFMwS1RVWnJkMFYzV1VoTGIxcEplbW93UTBGUldVbExiMXBKZW1vd1JFRlJZMFJSWjBGRlRVOWpWR1pTUWxNNWFtbFlUVGd4UmxvNFoyMHZNU3R2YldWTmR3cHRiaTh6TkRjdk5UVTJaeTlzY21sVE56SjFUV2haT1V4alZDczFWVW8yWmtkQ1oyeHlOVm80VERCS1RsTjFZWE41WldRNVQzUmhVblozUFQwS0xTMHRMUzFGVGtRZ1VGVkNURWxESUV0RldTMHRMUzB0Q2c9PSJ9fX19",
IntegratedTime: &time,
LogID: &logID,
LogIndex: swag.Int64(1),
Verification: &models.LogEntryAnonVerification{
InclusionProof: &models.InclusionProof{
TreeSize: swag.Int64(int64(2)),
RootHash: swag.String(rootHashString),
LogIndex: swag.Int64(1),
Hashes: []string{
"59a575f157274702c38de3ab1e1784226f391fb79500ebf9f02b4439fb77574c",
},
Checkpoint: swag.String(string(scBytes)),
},
SignedEntryTimestamp: strfmt.Base64("MEUCIHJj8xP+oPTd4BAXhO2lcbRplnKW2FafMiFo0gIDGUcYAiEA80BJ8QikiupGAv3R3dtSvZ1ICsAOQat10cFKPqBkLBM="),
},
},
wantErr: false,
},
{
name: "root hash mismatch",
e: models.LogEntryAnon{
Body: "ayJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJlY2RjNTUzNmY3M2JkYWU4ODE2ZjBlYTQwNzI2ZWY1ZTliODEwZDkxNDQ5MzA3NTkwM2JiOTA2MjNkOTdiMWQ4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUQvUGRQUW1LV0MxKzBCTkVkNWdLdlFHcjF4eGwzaWVVZmZ2M2prMXp6Skt3SWhBTEJqM3hmQXlXeGx6NGpwb0lFSVYxVWZLOXZua1VVT1NvZVp4QlpQSEtQQyIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQlFWVUpNU1VNZ1MwVlpMUzB0TFMwS1RVWnJkMFYzV1VoTGIxcEplbW93UTBGUldVbExiMXBKZW1vd1JFRlJZMFJSWjBGRlRVOWpWR1pTUWxNNWFtbFlUVGd4UmxvNFoyMHZNU3R2YldWTmR3cHRiaTh6TkRjdk5UVTJaeTlzY21sVE56SjFUV2haT1V4alZDczFWVW8yWmtkQ1oyeHlOVm80VERCS1RsTjFZWE41WldRNVQzUmhVblozUFQwS0xTMHRMUzFGVGtRZ1VGVkNURWxESUV0RldTMHRMUzB0Q2c9PSJ9fX19",
IntegratedTime: &time,
LogID: &logID,
LogIndex: swag.Int64(1),
Verification: &models.LogEntryAnonVerification{
InclusionProof: &models.InclusionProof{
TreeSize: swag.Int64(int64(2)),
RootHash: swag.String("5be1758dd2228acfaf2546b4b6ce8aa40c82a3748f3dcb550e0d67ba34f02a45"),
LogIndex: swag.Int64(1),
Hashes: []string{
"59a575f157274702c38de3ab1e1784226f391fb79500ebf9f02b4439fb77574c",
},
Checkpoint: swag.String(string(scBytes)),
},
SignedEntryTimestamp: strfmt.Base64("MEUCIHJj8xP+oPTd4BAXhO2lcbRplnKW2FafMiFo0gIDGUcYAiEA80BJ8QikiupGAv3R3dtSvZ1ICsAOQat10cFKPqBkLBM="),
},
},
wantErr: true,
},
} {
t.Run(string(test.name), func(t *testing.T) {
gotErr := VerifyCheckpointSignature(&test.e, signer)

if (gotErr != nil) != test.wantErr {
t.Fatalf("VerifyCheckpointSignature = %t, wantErr %t", gotErr, test.wantErr)
}
})
}
}

0 comments on commit e4a7a41

Please sign in to comment.