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

Merge pull request #129 from dlorenc/prove

Store the last tree state during loginfo so we can prove the tree state.
parents 5e61cc2d dab1d83d
No related branches found
No related tags found
No related merge requests found
......@@ -19,16 +19,22 @@ import (
"crypto"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"github.com/projectrekor/rekor/cmd/cli/app/state"
"github.com/google/trillian"
tclient "github.com/google/trillian/client"
tcrypto "github.com/google/trillian/crypto"
"github.com/google/trillian/merkle"
"github.com/google/trillian/merkle/rfc6962"
"github.com/projectrekor/rekor/cmd/cli/app/format"
"github.com/projectrekor/rekor/pkg/generated/client/tlog"
"github.com/projectrekor/rekor/pkg/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
......@@ -104,9 +110,42 @@ var logInfoCmd = &cobra.Command{
}
verifier := tclient.NewLogVerifier(rfc6962.DefaultHasher, pub, crypto.SHA256)
if _, err := tcrypto.VerifySignedLogRoot(verifier.PubKey, verifier.SigHash, &sth); err != nil {
lr, err := tcrypto.VerifySignedLogRoot(verifier.PubKey, verifier.SigHash, &sth)
if err != nil {
return nil, err
}
oldState := state.Load()
if oldState != nil {
log.CliLogger.Infof("Found previous log state, proving consistency between %d and %d", oldState.TreeSize, lr.TreeSize)
params := tlog.NewGetLogProofParams()
firstSize := int64(oldState.TreeSize)
params.FirstSize = &firstSize
params.LastSize = int64(lr.TreeSize)
proof, err := rekorClient.Tlog.GetLogProof(params)
if err != nil {
return nil, err
}
hashes := [][]byte{}
for _, h := range proof.Payload.Hashes {
b, _ := hex.DecodeString(h)
hashes = append(hashes, b)
}
v := merkle.NewLogVerifier(rfc6962.DefaultHasher)
if err := v.VerifyConsistencyProof(firstSize, int64(lr.TreeSize), oldState.RootHash,
lr.RootHash, hashes); err != nil {
return nil, err
}
log.CliLogger.Infof("Consistency proof valid!")
} else {
log.CliLogger.Infof("No previous log state stored, unable to prove consistency")
}
if viper.GetBool("store_tree_state") {
if err := state.Dump(lr); err != nil {
log.CliLogger.Infof("Unable to store previous state: %v", err)
}
}
return cmdOutput, nil
}),
}
......
......@@ -34,6 +34,7 @@ import (
)
var cfgFile string
var storeState bool
var rootCmd = &cobra.Command{
Use: "rekor",
......@@ -53,6 +54,7 @@ func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.rekor.yaml)")
rootCmd.PersistentFlags().BoolVar(&storeState, "store_tree_state", true, "whether to store tree state in between invocations for additional verification")
rootCmd.PersistentFlags().Var(&urlFlag{url: "https://api.rekor.dev"}, "rekor_server", "Server address:port")
rootCmd.PersistentFlags().Var(&formatFlag{format: "default"}, "format", "Command output format")
......
/*
Copyright © 2021 Dan Lorenc <lorenc.d@gmail.com>
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 state
import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"github.com/google/trillian/types"
"github.com/mitchellh/go-homedir"
)
func Dump(lr *types.LogRootV1) error {
rekorDir, err := getRekorDir()
if err != nil {
return err
}
statePath := filepath.Join(rekorDir, "state.json")
b, err := json.Marshal(lr)
if err != nil {
return err
}
if err := ioutil.WriteFile(statePath, b, 0600); err != nil {
return err
}
return nil
}
func Load() *types.LogRootV1 {
rekorDir, err := getRekorDir()
if err != nil {
return nil
}
fp := filepath.Join(rekorDir, "state.json")
b, err := ioutil.ReadFile(filepath.Clean(fp))
if err != nil {
return nil
}
result := &types.LogRootV1{}
if err := json.Unmarshal(b, result); err != nil {
return nil
}
return result
}
func getRekorDir() (string, error) {
home, err := homedir.Dir()
if err != nil {
return "", err
}
rekorDir := filepath.Join(home, ".rekor")
if _, err := os.Stat(rekorDir); os.IsNotExist(err) {
if err := os.MkdirAll(rekorDir, 0644); err != nil {
return "", err
}
}
return rekorDir, nil
}
......@@ -32,6 +32,21 @@ func ConfigureLogger(logType string) {
Logger = logger.Sugar()
}
var CliLogger = createCliLogger()
func createCliLogger() *zap.SugaredLogger {
cfg := zap.NewDevelopmentConfig()
cfg.EncoderConfig.TimeKey = ""
cfg.EncoderConfig.LevelKey = ""
cfg.DisableCaller = true
logger, err := cfg.Build()
if err != nil {
log.Fatalln("createLogger", err)
}
return logger.Sugar()
}
func WithRequestID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, middleware.RequestIDKey, id)
}
......
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