Skip to content

Commit f8449e8

Browse files
authored
add set signature and verification on get (sigstore#333)
Signed-off-by: Asra Ali <asraa@google.com>
1 parent fe5a7d3 commit f8449e8

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

cmd/rekor-cli/app/get.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package app
1717

1818
import (
1919
"bytes"
20+
"context"
2021
"encoding/base64"
2122
"encoding/json"
2223
"errors"
@@ -88,6 +89,10 @@ var getCmd = &cobra.Command{
8889
return nil, err
8990
}
9091
for ix, entry := range resp.Payload {
92+
if verified, err := verifyLogEntry(context.Background(), rekorClient, entry); err != nil || !verified {
93+
return nil, fmt.Errorf("unable to verify entry was added to log %w", err)
94+
}
95+
9196
return parseEntry(ix, entry)
9297
}
9398
}
@@ -106,6 +111,11 @@ var getCmd = &cobra.Command{
106111
if k != uuid {
107112
continue
108113
}
114+
115+
if verified, err := verifyLogEntry(context.Background(), rekorClient, entry); err != nil || !verified {
116+
return nil, fmt.Errorf("unable to verify entry was added to log %w", err)
117+
}
118+
109119
return parseEntry(k, entry)
110120
}
111121
}

cmd/rekor-cli/app/upload.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ func verifyLogEntry(ctx context.Context, rekorClient *client.Rekor, logEntry mod
143143
return false, nil
144144
}
145145
// verify the entry
146+
if logEntry.Verification.SignedEntryTimestamp == nil {
147+
return false, fmt.Errorf("signature missing")
148+
}
149+
146150
le := &models.LogEntryAnon{
147151
IntegratedTime: logEntry.IntegratedTime,
148152
LogIndex: logEntry.LogIndex,

pkg/api/entries.go

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,28 @@ import (
3939
"github.com/sigstore/rekor/pkg/generated/restapi/operations/entries"
4040
"github.com/sigstore/rekor/pkg/log"
4141
"github.com/sigstore/rekor/pkg/types"
42+
"github.com/sigstore/sigstore/pkg/signature"
4243
)
4344

44-
// logEntryFromLeaf creates LogEntry struct from trillian structs
45-
func logEntryFromLeaf(tc TrillianClient, leaf *trillian.LogLeaf, signedLogRoot *trillian.SignedLogRoot, proof *trillian.Proof) (models.LogEntry, error) {
45+
func signEntry(ctx context.Context, signer signature.Signer, entry models.LogEntryAnon) ([]byte, error) {
46+
payload, err := entry.MarshalBinary()
47+
if err != nil {
48+
return nil, fmt.Errorf("marshalling error: %v", err)
49+
}
50+
canonicalized, err := jsoncanonicalizer.Transform(payload)
51+
if err != nil {
52+
return nil, fmt.Errorf("canonicalizing error: %v", err)
53+
}
54+
signature, _, err := signer.Sign(ctx, canonicalized)
55+
if err != nil {
56+
return nil, fmt.Errorf("signing error: %v", err)
57+
}
58+
return signature, nil
59+
}
60+
61+
// logEntryFromLeaf creates a signed LogEntry struct from trillian structs
62+
func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc TrillianClient, leaf *trillian.LogLeaf,
63+
signedLogRoot *trillian.SignedLogRoot, proof *trillian.Proof) (models.LogEntry, error) {
4664

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

74+
logEntryAnon := models.LogEntryAnon{
75+
LogID: swag.String(api.pubkeyHash),
76+
LogIndex: &leaf.LeafIndex,
77+
Body: leaf.LeafValue,
78+
IntegratedTime: swag.Int64(leaf.IntegrateTimestamp.AsTime().Unix()),
79+
}
80+
81+
signature, err := signEntry(ctx, signer, logEntryAnon)
82+
if err != nil {
83+
return nil, fmt.Errorf("signing entry error: %w", err)
84+
}
85+
5686
inclusionProof := models.InclusionProof{
5787
TreeSize: swag.Int64(int64(root.TreeSize)),
5888
RootHash: swag.String(hex.EncodeToString(root.RootHash)),
5989
LogIndex: swag.Int64(proof.GetLeafIndex()),
6090
Hashes: hashes,
6191
}
6292

63-
logEntry := models.LogEntry{
64-
hex.EncodeToString(leaf.MerkleLeafHash): models.LogEntryAnon{
65-
LogID: swag.String(api.pubkeyHash),
66-
LogIndex: &leaf.LeafIndex,
67-
Body: leaf.LeafValue,
68-
IntegratedTime: swag.Int64(leaf.IntegrateTimestamp.AsTime().Unix()),
69-
Verification: &models.LogEntryAnonVerification{
70-
InclusionProof: &inclusionProof,
71-
},
72-
},
93+
logEntryAnon.Verification = &models.LogEntryAnonVerification{
94+
InclusionProof: &inclusionProof,
95+
SignedEntryTimestamp: strfmt.Base64(signature),
7396
}
7497

75-
return logEntry, nil
98+
return models.LogEntry{
99+
hex.EncodeToString(leaf.MerkleLeafHash): logEntryAnon}, nil
76100
}
77101

78102
// GetLogEntryAndProofByIndexHandler returns the entry and inclusion proof for a specified log index
79103
func GetLogEntryByIndexHandler(params entries.GetLogEntryByIndexParams) middleware.Responder {
80-
tc := NewTrillianClient(params.HTTPRequest.Context())
104+
ctx := params.HTTPRequest.Context()
105+
tc := NewTrillianClient(ctx)
81106

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

97-
logEntry, err := logEntryFromLeaf(tc, leaf, result.SignedLogRoot, result.Proof)
122+
logEntry, err := logEntryFromLeaf(ctx, api.signer, tc, leaf, result.SignedLogRoot, result.Proof)
98123
if err != nil {
99124
return handleRekorAPIError(params, http.StatusInternalServerError, err, err.Error())
100125
}
@@ -174,18 +199,11 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
174199
}()
175200
}
176201

177-
payload, err := logEntryAnon.MarshalBinary()
202+
signature, err := signEntry(ctx, api.signer, logEntryAnon)
178203
if err != nil {
179-
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing error: %v", err), signingError)
180-
}
181-
canonicalized, err := jsoncanonicalizer.Transform(payload)
182-
if err != nil {
183-
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("canonicalizing error: %v", err), signingError)
184-
}
185-
signature, _, err := api.signer.Sign(ctx, canonicalized)
186-
if err != nil {
187-
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing error: %v", err), signingError)
204+
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing entry error: %v", err), signingError)
188205
}
206+
189207
logEntryAnon.Verification = &models.LogEntryAnonVerification{
190208
SignedEntryTimestamp: strfmt.Base64(signature),
191209
}
@@ -210,6 +228,7 @@ func getEntryURL(locationURL url.URL, uuid string) strfmt.URI {
210228

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

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

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

314333
for _, leafResp := range searchByHashResults {
315334
if leafResp != nil {
316-
logEntry, err := logEntryFromLeaf(tc, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof)
335+
logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tc, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof)
317336
if err != nil {
318337
return handleRekorAPIError(params, code, err, err.Error())
319338
}
@@ -350,7 +369,7 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo
350369

351370
for _, result := range leafResults {
352371
if result != nil {
353-
logEntry, err := logEntryFromLeaf(tc, result.Leaf, result.SignedLogRoot, result.Proof)
372+
logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tc, result.Leaf, result.SignedLogRoot, result.Proof)
354373
if err != nil {
355374
return handleRekorAPIError(params, http.StatusInternalServerError, err, trillianUnexpectedResult)
356375
}

0 commit comments

Comments
 (0)