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

Verify signedEntryTimestamp on (#295)

parent 2b4d1ba5
No related branches found
No related tags found
No related merge requests found
......@@ -16,18 +16,24 @@
package app
import (
"context"
"crypto/ecdsa"
"crypto/sha256"
"errors"
"fmt"
"os"
"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
"github.com/go-openapi/swag"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/sigstore/rekor/cmd/rekor-cli/app/format"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/entries"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/rekor/pkg/log"
"github.com/sigstore/rekor/pkg/util"
)
type uploadCmdOutput struct {
......@@ -60,6 +66,7 @@ var uploadCmd = &cobra.Command{
},
Long: `This command takes the public key, signature and URL of the release artifact and uploads it to the rekor server.`,
Run: format.WrapCmd(func(args []string) (interface{}, error) {
ctx := context.Background()
rekorClient, err := GetRekorClient(viper.GetString("rekor_server"))
if err != nil {
return nil, err
......@@ -103,8 +110,15 @@ var uploadCmd = &cobra.Command{
}
var newIndex int64
var logEntry models.LogEntryAnon
for _, entry := range resp.Payload {
newIndex = swag.Int64Value(entry.LogIndex)
logEntry = entry
}
// verify log entry
if verified, err := verifyLogEntry(ctx, rekorClient, logEntry); err != nil || !verified {
fmt.Fprintf(os.Stderr, "unable to verify entry was added to log: %v", err)
}
return &uploadCmdOutput{
......@@ -114,6 +128,39 @@ var uploadCmd = &cobra.Command{
}),
}
func verifyLogEntry(ctx context.Context, rekorClient *client.Rekor, logEntry models.LogEntryAnon) (bool, error) {
if logEntry.Verification == nil {
return false, nil
}
// verify the entry
le := &models.LogEntryAnon{
IntegratedTime: logEntry.IntegratedTime,
LogIndex: logEntry.LogIndex,
Body: logEntry.Body,
}
payload, err := le.MarshalBinary()
if err != nil {
return false, err
}
canonicalized, err := jsoncanonicalizer.Transform(payload)
if err != nil {
return false, err
}
// get rekor's public key
rekorPubKey, err := util.PublicKey(ctx, rekorClient)
if err != nil {
return false, err
}
// verify the SET against the public key
hash := sha256.Sum256(canonicalized)
if !ecdsa.VerifyASN1(rekorPubKey, hash[:], []byte(logEntry.Verification.SignedEntryTimestamp)) {
return false, fmt.Errorf("unable to verify")
}
return true, nil
}
func init() {
if err := addArtifactPFlags(uploadCmd); err != nil {
log.Logger.Fatal("Error parsing cmd line args:", err)
......
//
// Copyright 2021 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package util
import (
"context"
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"errors"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/pubkey"
)
func PublicKey(ctx context.Context, c *client.Rekor) (*ecdsa.PublicKey, error) {
resp, err := c.Pubkey.GetPublicKey(&pubkey.GetPublicKeyParams{Context: ctx})
if err != nil {
return nil, err
}
pubKey := resp.GetPayload()
// marshal the pubkey
p, _ := pem.Decode([]byte(pubKey))
if p == nil {
return nil, errors.New("public key shouldn't be nil")
}
decoded, err := x509.ParsePKIXPublicKey(p.Bytes)
if err != nil {
return nil, err
}
ed, ok := decoded.(*ecdsa.PublicKey)
if !ok {
return nil, err
}
return ed, nil
}
......@@ -40,12 +40,11 @@ import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/sigstore/rekor/cmd/rekor-cli/app"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/entries"
"github.com/sigstore/rekor/pkg/generated/client/pubkey"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/rekor/pkg/signer"
rekord "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1"
"github.com/sigstore/rekor/pkg/util"
)
func getUUIDFromUploadOutput(t *testing.T, out string) string {
......@@ -460,7 +459,10 @@ func TestSignedEntryTimestamp(t *testing.T) {
t.Fatal(err)
}
// get rekor's public key
rekorPubKey := rekorPublicKey(t, ctx, rekorClient)
rekorPubKey, err := util.PublicKey(ctx, rekorClient)
if err != nil {
t.Fatal(err)
}
// verify the signature against the public key
h := crypto.SHA256.New()
......@@ -473,27 +475,3 @@ func TestSignedEntryTimestamp(t *testing.T) {
t.Fatal("unable to verify")
}
}
func rekorPublicKey(t *testing.T, ctx context.Context, c *client.Rekor) *ecdsa.PublicKey {
resp, err := c.Pubkey.GetPublicKey(&pubkey.GetPublicKeyParams{Context: ctx})
if err != nil {
t.Fatal(err)
}
pubKey := resp.GetPayload()
// marshal the pubkey
p, _ := pem.Decode([]byte(pubKey))
if p == nil {
t.Fatal("shouldn't be nil")
}
decoded, err := x509.ParsePKIXPublicKey(p.Bytes)
if err != nil {
t.Fatal(err)
}
ed, ok := decoded.(*ecdsa.PublicKey)
if !ok {
t.Fatal("not ecdsa public key")
}
return ed
}
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