@@ -28,6 +28,7 @@ import (
2828 "github.com/go-openapi/swag"
2929 "github.com/google/trillian/merkle/logverifier"
3030 "github.com/google/trillian/merkle/rfc6962"
31+ rclient "github.com/sigstore/rekor/pkg/generated/client"
3132 "github.com/spf13/cobra"
3233 "github.com/spf13/viper"
3334
@@ -81,89 +82,112 @@ var logInfoCmd = &cobra.Command{
8182 logInfo := result .GetPayload ()
8283
8384 sth := util.SignedCheckpoint {}
84- if err := sth .UnmarshalText ([]byte (* logInfo .SignedTreeHead )); err != nil {
85+ signedTreeHead := swag .StringValue (logInfo .SignedTreeHead )
86+ if err := sth .UnmarshalText ([]byte (signedTreeHead )); err != nil {
8587 return nil , err
8688 }
8789
88- publicKey := viper .GetString ("rekor_server_public_key" )
89- if publicKey == "" {
90- // fetch key from server
91- keyResp , err := rekorClient .Pubkey .GetPublicKey (nil )
92- if err != nil {
93- return nil , err
94- }
95- publicKey = keyResp .Payload
96- }
97-
98- block , _ := pem .Decode ([]byte (publicKey ))
99- if block == nil {
100- return nil , errors .New ("failed to decode public key of server" )
101- }
102-
103- pub , err := x509 .ParsePKIXPublicKey (block .Bytes )
104- if err != nil {
90+ if err := verifyTree (rekorClient , signedTreeHead , serverURL ); err != nil {
10591 return nil , err
10692 }
10793
108- verifier , err := signature .LoadVerifier (pub , crypto .SHA256 )
109- if err != nil {
110- return nil , err
111- }
112-
113- if ! sth .Verify (verifier ) {
114- return nil , errors .New ("signature on tree head did not verify" )
115- }
116-
11794 cmdOutput := & logInfoCmdOutput {
11895 TreeSize : swag .Int64Value (logInfo .TreeSize ),
11996 RootHash : swag .StringValue (logInfo .RootHash ),
12097 TimestampNanos : sth .GetTimestamp (),
12198 TreeID : swag .StringValue (logInfo .TreeID ),
12299 }
100+ return cmdOutput , nil
101+ }),
102+ }
123103
124- oldState := state .Load (serverURL )
125- if oldState != nil {
126- persistedSize := oldState .Size
127- if persistedSize < sth .Size {
128- log .CliLogger .Infof ("Found previous log state, proving consistency between %d and %d" , oldState .Size , sth .Size )
129- params := tlog .NewGetLogProofParams ()
130- firstSize := int64 (persistedSize )
131- params .FirstSize = & firstSize
132- params .LastSize = int64 (sth .Size )
133- proof , err := rekorClient .Tlog .GetLogProof (params )
134- if err != nil {
135- return nil , err
136- }
137- hashes := [][]byte {}
138- for _ , h := range proof .Payload .Hashes {
139- b , _ := hex .DecodeString (h )
140- hashes = append (hashes , b )
141- }
142- v := logverifier .New (rfc6962 .DefaultHasher )
143- if err := v .VerifyConsistencyProof (firstSize , int64 (sth .Size ), oldState .Hash ,
144- sth .Hash , hashes ); err != nil {
145- return nil , err
146- }
147- log .CliLogger .Infof ("Consistency proof valid!" )
148- } else if persistedSize == sth .Size {
149- if ! bytes .Equal (oldState .Hash , sth .Hash ) {
150- return nil , errors .New ("root hash returned from server does not match previously persisted state" )
151- }
152- log .CliLogger .Infof ("Persisted log state matches the current state of the log" )
153- } else if persistedSize > sth .Size {
154- return nil , fmt .Errorf ("current size of tree reported from server %d is less than previously persisted state %d" , sth .Size , persistedSize )
155- }
156- } else {
157- log .CliLogger .Infof ("No previous log state stored, unable to prove consistency" )
104+ func verifyTree (rekorClient * rclient.Rekor , signedTreeHead , serverURL string ) error {
105+ oldState := state .Load (serverURL )
106+ sth := util.SignedCheckpoint {}
107+ if err := sth .UnmarshalText ([]byte (signedTreeHead )); err != nil {
108+ return err
109+ }
110+ verifier , err := loadVerifier (rekorClient )
111+ if err != nil {
112+ return err
113+ }
114+ if ! sth .Verify (verifier ) {
115+ return errors .New ("signature on tree head did not verify" )
116+ }
117+
118+ if err := proveConsistency (rekorClient , oldState , sth ); err != nil {
119+ return err
120+ }
121+
122+ if viper .GetBool ("store_tree_state" ) {
123+ if err := state .Dump (serverURL , & sth ); err != nil {
124+ log .CliLogger .Infof ("Unable to store previous state: %v" , err )
158125 }
126+ }
127+ return nil
128+ }
159129
160- if viper .GetBool ("store_tree_state" ) {
161- if err := state .Dump (serverURL , & sth ); err != nil {
162- log .CliLogger .Infof ("Unable to store previous state: %v" , err )
163- }
130+ func proveConsistency (rekorClient * rclient.Rekor , oldState * util.SignedCheckpoint , sth util.SignedCheckpoint ) error {
131+ if oldState == nil {
132+ log .CliLogger .Infof ("No previous log state stored, unable to prove consistency" )
133+ return nil
134+ }
135+ persistedSize := oldState .Size
136+ switch {
137+ case persistedSize < sth .Size :
138+ log .CliLogger .Infof ("Found previous log state, proving consistency between %d and %d" , oldState .Size , sth .Size )
139+ params := tlog .NewGetLogProofParams ()
140+ firstSize := int64 (persistedSize )
141+ params .FirstSize = & firstSize
142+ params .LastSize = int64 (sth .Size )
143+ proof , err := rekorClient .Tlog .GetLogProof (params )
144+ if err != nil {
145+ return err
164146 }
165- return cmdOutput , nil
166- }),
147+ hashes := [][]byte {}
148+ for _ , h := range proof .Payload .Hashes {
149+ b , _ := hex .DecodeString (h )
150+ hashes = append (hashes , b )
151+ }
152+ v := logverifier .New (rfc6962 .DefaultHasher )
153+ if err := v .VerifyConsistencyProof (firstSize , int64 (sth .Size ), oldState .Hash ,
154+ sth .Hash , hashes ); err != nil {
155+ return err
156+ }
157+ log .CliLogger .Infof ("Consistency proof valid!" )
158+ case persistedSize == sth .Size :
159+ if ! bytes .Equal (oldState .Hash , sth .Hash ) {
160+ return errors .New ("root hash returned from server does not match previously persisted state" )
161+ }
162+ log .CliLogger .Infof ("Persisted log state matches the current state of the log" )
163+ default :
164+ return fmt .Errorf ("current size of tree reported from server %d is less than previously persisted state %d" , sth .Size , persistedSize )
165+ }
166+ return nil
167+ }
168+
169+ func loadVerifier (rekorClient * rclient.Rekor ) (signature.Verifier , error ) {
170+ publicKey := viper .GetString ("rekor_server_public_key" )
171+ if publicKey == "" {
172+ // fetch key from server
173+ keyResp , err := rekorClient .Pubkey .GetPublicKey (nil )
174+ if err != nil {
175+ return nil , err
176+ }
177+ publicKey = keyResp .Payload
178+ }
179+
180+ block , _ := pem .Decode ([]byte (publicKey ))
181+ if block == nil {
182+ return nil , errors .New ("failed to decode public key of server" )
183+ }
184+
185+ pub , err := x509 .ParsePKIXPublicKey (block .Bytes )
186+ if err != nil {
187+ return nil , err
188+ }
189+
190+ return signature .LoadVerifier (pub , crypto .SHA256 )
167191}
168192
169193func init () {
0 commit comments