Skip to content
Snippets Groups Projects
Unverified Commit f8449e8a authored by asraa's avatar asraa Committed by GitHub
Browse files

add set signature and verification on get (#333)


Signed-off-by: default avatarAsra Ali <asraa@google.com>
parent fe5a7d39
No related branches found
Tags v0.2.0
No related merge requests found
Pipeline #35211 failed
......@@ -17,6 +17,7 @@ package app
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
......@@ -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)
}
}
......@@ -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)
}
}
......
......@@ -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,
......
......@@ -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 {
......@@ -53,6 +71,18 @@ 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)),
......@@ -60,24 +90,19 @@ func logEntryFromLeaf(tc TrillianClient, leaf *trillian.LogLeaf, signedLogRoot *
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 {
......@@ -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())
}
......@@ -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),
}
......@@ -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())
......@@ -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, "")
}
......@@ -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())
}
......@@ -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)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment