Skip to content

Commit

Permalink
add set signature and verification on get (#333)
Browse files Browse the repository at this point in the history
Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa authored Jun 16, 2021
1 parent fe5a7d3 commit f8449e8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
10 changes: 10 additions & 0 deletions cmd/rekor-cli/app/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package app

import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
Expand Down Expand Up @@ -88,6 +89,10 @@ var getCmd = &cobra.Command{
return nil, err
}
for ix, entry := range resp.Payload {
if verified, err := verifyLogEntry(context.Background(), rekorClient, entry); err != nil || !verified {
return nil, fmt.Errorf("unable to verify entry was added to log %w", err)
}

return parseEntry(ix, entry)
}
}
Expand All @@ -106,6 +111,11 @@ var getCmd = &cobra.Command{
if k != uuid {
continue
}

if verified, err := verifyLogEntry(context.Background(), rekorClient, entry); err != nil || !verified {
return nil, fmt.Errorf("unable to verify entry was added to log %w", err)
}

return parseEntry(k, entry)
}
}
Expand Down
4 changes: 4 additions & 0 deletions cmd/rekor-cli/app/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ func verifyLogEntry(ctx context.Context, rekorClient *client.Rekor, logEntry mod
return false, nil
}
// verify the entry
if logEntry.Verification.SignedEntryTimestamp == nil {
return false, fmt.Errorf("signature missing")
}

le := &models.LogEntryAnon{
IntegratedTime: logEntry.IntegratedTime,
LogIndex: logEntry.LogIndex,
Expand Down
75 changes: 47 additions & 28 deletions pkg/api/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,28 @@ import (
"github.com/sigstore/rekor/pkg/generated/restapi/operations/entries"
"github.com/sigstore/rekor/pkg/log"
"github.com/sigstore/rekor/pkg/types"
"github.com/sigstore/sigstore/pkg/signature"
)

// logEntryFromLeaf creates LogEntry struct from trillian structs
func logEntryFromLeaf(tc TrillianClient, leaf *trillian.LogLeaf, signedLogRoot *trillian.SignedLogRoot, proof *trillian.Proof) (models.LogEntry, error) {
func signEntry(ctx context.Context, signer signature.Signer, entry models.LogEntryAnon) ([]byte, error) {
payload, err := entry.MarshalBinary()
if err != nil {
return nil, fmt.Errorf("marshalling error: %v", err)
}
canonicalized, err := jsoncanonicalizer.Transform(payload)
if err != nil {
return nil, fmt.Errorf("canonicalizing error: %v", err)
}
signature, _, err := signer.Sign(ctx, canonicalized)
if err != nil {
return nil, fmt.Errorf("signing error: %v", err)
}
return signature, nil
}

// logEntryFromLeaf creates a signed LogEntry struct from trillian structs
func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc TrillianClient, leaf *trillian.LogLeaf,
signedLogRoot *trillian.SignedLogRoot, proof *trillian.Proof) (models.LogEntry, error) {

root := &ttypes.LogRootV1{}
if err := root.UnmarshalBinary(signedLogRoot.LogRoot); err != nil {
Expand All @@ -53,31 +71,38 @@ func logEntryFromLeaf(tc TrillianClient, leaf *trillian.LogLeaf, signedLogRoot *
hashes = append(hashes, hex.EncodeToString(hash))
}

logEntryAnon := models.LogEntryAnon{
LogID: swag.String(api.pubkeyHash),
LogIndex: &leaf.LeafIndex,
Body: leaf.LeafValue,
IntegratedTime: swag.Int64(leaf.IntegrateTimestamp.AsTime().Unix()),
}

signature, err := signEntry(ctx, signer, logEntryAnon)
if err != nil {
return nil, fmt.Errorf("signing entry error: %w", err)
}

inclusionProof := models.InclusionProof{
TreeSize: swag.Int64(int64(root.TreeSize)),
RootHash: swag.String(hex.EncodeToString(root.RootHash)),
LogIndex: swag.Int64(proof.GetLeafIndex()),
Hashes: hashes,
}

logEntry := models.LogEntry{
hex.EncodeToString(leaf.MerkleLeafHash): models.LogEntryAnon{
LogID: swag.String(api.pubkeyHash),
LogIndex: &leaf.LeafIndex,
Body: leaf.LeafValue,
IntegratedTime: swag.Int64(leaf.IntegrateTimestamp.AsTime().Unix()),
Verification: &models.LogEntryAnonVerification{
InclusionProof: &inclusionProof,
},
},
logEntryAnon.Verification = &models.LogEntryAnonVerification{
InclusionProof: &inclusionProof,
SignedEntryTimestamp: strfmt.Base64(signature),
}

return logEntry, nil
return models.LogEntry{
hex.EncodeToString(leaf.MerkleLeafHash): logEntryAnon}, nil
}

// GetLogEntryAndProofByIndexHandler returns the entry and inclusion proof for a specified log index
func GetLogEntryByIndexHandler(params entries.GetLogEntryByIndexParams) middleware.Responder {
tc := NewTrillianClient(params.HTTPRequest.Context())
ctx := params.HTTPRequest.Context()
tc := NewTrillianClient(ctx)

resp := tc.getLeafAndProofByIndex(params.LogIndex)
switch resp.status {
Expand All @@ -94,7 +119,7 @@ func GetLogEntryByIndexHandler(params entries.GetLogEntryByIndexParams) middlewa
return handleRekorAPIError(params, http.StatusNotFound, errors.New("grpc returned 0 leaves with success code"), "")
}

logEntry, err := logEntryFromLeaf(tc, leaf, result.SignedLogRoot, result.Proof)
logEntry, err := logEntryFromLeaf(ctx, api.signer, tc, leaf, result.SignedLogRoot, result.Proof)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, err, err.Error())
}
Expand Down Expand Up @@ -174,18 +199,11 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
}()
}

payload, err := logEntryAnon.MarshalBinary()
signature, err := signEntry(ctx, api.signer, logEntryAnon)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing error: %v", err), signingError)
}
canonicalized, err := jsoncanonicalizer.Transform(payload)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("canonicalizing error: %v", err), signingError)
}
signature, _, err := api.signer.Sign(ctx, canonicalized)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing error: %v", err), signingError)
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing entry error: %v", err), signingError)
}

logEntryAnon.Verification = &models.LogEntryAnonVerification{
SignedEntryTimestamp: strfmt.Base64(signature),
}
Expand All @@ -210,6 +228,7 @@ func getEntryURL(locationURL url.URL, uuid string) strfmt.URI {

// GetLogEntryByUUIDHandler gets log entry and inclusion proof for specified UUID aka merkle leaf hash
func GetLogEntryByUUIDHandler(params entries.GetLogEntryByUUIDParams) middleware.Responder {
ctx := params.HTTPRequest.Context()
hashValue, _ := hex.DecodeString(params.EntryUUID)
tc := NewTrillianClient(params.HTTPRequest.Context())

Expand All @@ -228,7 +247,7 @@ func GetLogEntryByUUIDHandler(params entries.GetLogEntryByUUIDParams) middleware
return handleRekorAPIError(params, http.StatusNotFound, errors.New("grpc returned 0 leaves with success code"), "")
}

logEntry, err := logEntryFromLeaf(tc, leaf, result.SignedLogRoot, result.Proof)
logEntry, err := logEntryFromLeaf(ctx, api.signer, tc, leaf, result.SignedLogRoot, result.Proof)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, err, "")
}
Expand Down Expand Up @@ -313,7 +332,7 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo

for _, leafResp := range searchByHashResults {
if leafResp != nil {
logEntry, err := logEntryFromLeaf(tc, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof)
logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tc, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof)
if err != nil {
return handleRekorAPIError(params, code, err, err.Error())
}
Expand Down Expand Up @@ -350,7 +369,7 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo

for _, result := range leafResults {
if result != nil {
logEntry, err := logEntryFromLeaf(tc, result.Leaf, result.SignedLogRoot, result.Proof)
logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tc, result.Leaf, result.SignedLogRoot, result.Proof)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, err, trillianUnexpectedResult)
}
Expand Down

0 comments on commit f8449e8

Please sign in to comment.