11package main
22
33import (
4+ "bytes"
45 "context"
6+ "crypto/sha256"
57 "encoding/base64"
68 "encoding/json"
79 "flag"
@@ -164,8 +166,9 @@ func lookupKey(serverURL string, policy torchwood.Policy, vrfKey *vrf.PublicKey,
164166 }
165167
166168 // Verify spicy signature
167- vrfHashB64 := base64 .StdEncoding .EncodeToString (vrfHash )
168- entry := fmt .Appendf (nil , "%s\n %s\n " , vrfHashB64 , result .Pubkey )
169+ h := sha256 .New ()
170+ h .Write ([]byte (result .Pubkey ))
171+ entry := h .Sum (vrfHash ) // vrf-r255(email) || SHA-256(pubkey)
169172 if err := torchwood .VerifyProof (policy , tlog .RecordHash (entry ), []byte (result .Proof )); err != nil {
170173 return "" , fmt .Errorf ("failed to verify key proof: %w" , err )
171174 }
@@ -174,7 +177,7 @@ func lookupKey(serverURL string, policy torchwood.Policy, vrfKey *vrf.PublicKey,
174177}
175178
176179func monitorLog (serverURL string , policy torchwood.Policy , vrfKey * vrf.PublicKey , email string ) ([]string , error ) {
177- // Request the VRF proof from the monitor endpoint
180+ // Request the VRF proof and history from the monitor endpoint
178181 monitorURL := serverURL + "/api/monitor?email=" + url .QueryEscape (email )
179182 client := & http.Client {
180183 Timeout : 10 * time .Second ,
@@ -192,8 +195,9 @@ func monitorLog(serverURL string, policy torchwood.Policy, vrfKey *vrf.PublicKey
192195 return nil , fmt .Errorf ("keyserver error: %s - %s" , resp .Status , string (body ))
193196 }
194197 var result struct {
195- Email string `json:"email"`
196- VRFProof []byte `json:"vrf_proof"`
198+ Email string `json:"email"`
199+ VRFProof []byte `json:"vrf_proof"`
200+ History []string `json:"history"`
197201 }
198202 if err := json .NewDecoder (resp .Body ).Decode (& result ); err != nil {
199203 return nil , fmt .Errorf ("failed to parse response: %w" , err )
@@ -202,6 +206,13 @@ func monitorLog(serverURL string, policy torchwood.Policy, vrfKey *vrf.PublicKey
202206 return nil , fmt .Errorf ("keyserver returned unexpected email: %q" , result .Email )
203207 }
204208
209+ // Prepare map of hashes of historical keys
210+ historyHashes := make (map [[32 ]byte ]string )
211+ for _ , pk := range result .History {
212+ h := sha256 .Sum256 ([]byte (pk ))
213+ historyHashes [h ] = pk
214+ }
215+
205216 // Compute and verify VRF hash
206217 vrfProof , err := vrf .NewProof (result .VRFProof )
207218 if err != nil {
@@ -234,17 +245,17 @@ func monitorLog(serverURL string, policy torchwood.Policy, vrfKey *vrf.PublicKey
234245 // Fetch all entries up to the checkpoint size
235246 var pubkeys []string
236247 for i , entry := range c .AllEntries (context .Background (), checkpoint .Tree , 0 ) {
237- e , rest , ok := strings .Cut (string (entry ), "\n " )
238- if ! ok {
239- return nil , fmt .Errorf ("malformed log entry %d: %q" , i , string (entry ))
248+ if len (entry ) != 64 + 32 {
249+ return nil , fmt .Errorf ("invalid entry size at index %d" , i )
240250 }
241- k , rest , ok := strings .Cut (rest , "\n " )
242- if ! ok || rest != "" {
243- return nil , fmt .Errorf ("malformed log entry %d: %q" , i , string (entry ))
251+ if ! bytes .Equal (entry [:64 ], vrfHash ) {
252+ continue
244253 }
245- if e == base64 .StdEncoding .EncodeToString (vrfHash ) {
246- pubkeys = append (pubkeys , k )
254+ pk , ok := historyHashes [([32 ]byte )(entry [64 :])]
255+ if ! ok {
256+ return nil , fmt .Errorf ("found unknown public key hash in log at index %d" , i )
247257 }
258+ pubkeys = append (pubkeys , pk )
248259 }
249260 if c .Err () != nil {
250261 return nil , fmt .Errorf ("error fetching log entries: %w" , c .Err ())
0 commit comments