@@ -3,6 +3,7 @@ package main
33import (
44 "context"
55 "crypto/rand"
6+ "encoding/base64"
67 "encoding/json"
78 "fmt"
89 "html/template"
@@ -16,6 +17,7 @@ import (
1617 "time"
1718
1819 "filippo.io/age"
20+ "filippo.io/mostly-harmless/vrf-r255"
1921 "filippo.io/torchwood"
2022 "filippo.io/torchwood/tesserax"
2123 "github.com/transparency-dev/tessera"
@@ -33,6 +35,7 @@ type Server struct {
3335 dbpool * sqlitex.Pool
3436 templates * template.Template
3537 hmacKey []byte
38+ vrf * vrf.PrivateKey
3639 reader tessera.LogReader
3740 appender * tessera.Appender
3841 awaiter * tessera.PublicationAwaiter
@@ -43,6 +46,7 @@ type KeyData struct {
4346 Pubkey string `json:"pubkey"`
4447 UpdatedAt int64 `json:"updated_at"`
4548 LogIndex int64 `json:"log_index"`
49+ VRFProof []byte `json:"vrf_proof"`
4650}
4751
4852const schema = `CREATE TABLE IF NOT EXISTS keys (email TEXT PRIMARY KEY, json_data BLOB) STRICT;`
@@ -101,13 +105,17 @@ func TestCLIDirect(t *testing.T) {
101105 defer shutdown (context .Background ())
102106 awaiter := tessera .NewPublicationAwaiter (ctx , logReader .ReadCheckpoint , 250 * time .Millisecond )
103107
108+ // Generate test VRF key
109+ vrfKey := vrf .GenerateKey ()
110+
104111 // Create minimal templates
105112 tmpl := template .Must (template .New ("test" ).Parse ("" ))
106113
107114 srv := & Server {
108115 dbpool : dbpool ,
109116 templates : tmpl ,
110117 hmacKey : hmacKey ,
118+ vrf : vrfKey ,
111119 reader : logReader ,
112120 appender : appender ,
113121 awaiter : awaiter ,
@@ -140,8 +148,12 @@ func TestCLIDirect(t *testing.T) {
140148 testKey := identity .Recipient ().String ()
141149 testEmail := "test@example.com"
142150
151+ // Compute VRF hash and proof
152+ vrfProof := srv .vrf .Prove ([]byte (testEmail ))
153+ vrfHash := base64 .StdEncoding .EncodeToString (vrfProof .Hash ())
154+
143155 // Add to transparency log
144- entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , testEmail , testKey ))
156+ entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , vrfHash , testKey ))
145157 index , _ , err := srv .awaiter .Await (ctx , srv .appender .Add (ctx , entry ))
146158 if err != nil {
147159 t .Fatal (err )
@@ -152,6 +164,7 @@ func TestCLIDirect(t *testing.T) {
152164 Pubkey : testKey ,
153165 UpdatedAt : time .Now ().Unix (),
154166 LogIndex : int64 (index .Index ),
167+ VRFProof : vrfProof .Bytes (),
155168 }
156169 jsonData , _ := json .Marshal (data )
157170
@@ -171,7 +184,7 @@ func TestCLIDirect(t *testing.T) {
171184 }
172185
173186 // Test the lookup function
174- pubkey , err := lookupKey (serverURL , verifier , testEmail )
187+ pubkey , err := lookupKey (serverURL , verifier , srv . vrf . PublicKey (), testEmail )
175188 if err != nil {
176189 t .Fatalf ("lookup failed: %v" , err )
177190 }
@@ -182,7 +195,7 @@ func TestCLIDirect(t *testing.T) {
182195 })
183196
184197 t .Run ("lookup non-existent key" , func (t * testing.T ) {
185- _ , err := lookupKey (serverURL , verifier , "nonexistent@example.com" )
198+ _ , err := lookupKey (serverURL , verifier , srv . vrf . PublicKey (), "nonexistent@example.com" )
186199 if err == nil {
187200 t .Error ("expected error for non-existent key" )
188201 }
@@ -204,8 +217,12 @@ func TestCLIDirect(t *testing.T) {
204217 testKey := identity .Recipient ().String ()
205218 expectedKeys [email ] = testKey
206219
220+ // Compute VRF hash and proof
221+ vrfProof := srv .vrf .Prove ([]byte (email ))
222+ vrfHash := base64 .StdEncoding .EncodeToString (vrfProof .Hash ())
223+
207224 // Add to transparency log
208- entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , email , testKey ))
225+ entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , vrfHash , testKey ))
209226 index , _ , err := srv .awaiter .Await (ctx , srv .appender .Add (ctx , entry ))
210227 if err != nil {
211228 t .Fatal (err )
@@ -216,6 +233,7 @@ func TestCLIDirect(t *testing.T) {
216233 Pubkey : testKey ,
217234 UpdatedAt : time .Now ().Unix (),
218235 LogIndex : int64 (index .Index ),
236+ VRFProof : vrfProof .Bytes (),
219237 }
220238 jsonData , _ := json .Marshal (data )
221239
@@ -237,7 +255,7 @@ func TestCLIDirect(t *testing.T) {
237255
238256 // Test lookup for each key
239257 for _ , email := range emails {
240- pubkey , err := lookupKey (serverURL , verifier , email )
258+ pubkey , err := lookupKey (serverURL , verifier , srv . vrf . PublicKey (), email )
241259 if err != nil {
242260 t .Fatalf ("lookup failed for %s: %v" , email , err )
243261 }
@@ -264,7 +282,7 @@ func (s *Server) handleLookup(w http.ResponseWriter, r *http.Request) {
264282 }
265283
266284 // Generate proof
267- proof , err := s .makeSpicySignature (r .Context (), email , data .Pubkey , data .LogIndex )
285+ proof , err := s .makeSpicySignature (r .Context (), data .LogIndex , data .VRFProof )
268286 if err != nil {
269287 http .Error (w , "Failed to create proof" , http .StatusInternalServerError )
270288 log .Printf ("proof error: %v" , err )
@@ -315,7 +333,7 @@ func (s *Server) getKeyData(email string) *KeyData {
315333 return & data
316334}
317335
318- func (s * Server ) makeSpicySignature (ctx context.Context , email , pubkey string , index int64 ) ([]byte , error ) {
336+ func (s * Server ) makeSpicySignature (ctx context.Context , index int64 , vrfProof [] byte ) ([]byte , error ) {
319337 checkpoint , err := s .reader .ReadCheckpoint (ctx )
320338 if err != nil {
321339 return nil , fmt .Errorf ("failed to read checkpoint: %v" , err )
@@ -333,7 +351,7 @@ func (s *Server) makeSpicySignature(ctx context.Context, email, pubkey string, i
333351 if err != nil {
334352 return nil , fmt .Errorf ("failed to create proof: %v" , err )
335353 }
336- return torchwood .FormatProof (index , p , checkpoint ), nil
354+ return torchwood .FormatProofWithHint (index , vrfProof , p , checkpoint ), nil
337355}
338356
339357// scripttest integration tests
@@ -389,6 +407,7 @@ type testEnv struct {
389407 serverURL string
390408 dbPath string
391409 verifier note.Verifier
410+ vrfPubKey * vrf.PublicKey
392411 server * Server
393412 cleanup func ()
394413}
@@ -462,13 +481,17 @@ func startServerCmd() script.Cmd {
462481 }
463482 awaiter := tessera .NewPublicationAwaiter (ctx , logReader .ReadCheckpoint , 250 * time .Millisecond )
464483
484+ // Generate test VRF key
485+ vrfKey := vrf .GenerateKey ()
486+
465487 // Create minimal templates
466488 tmpl := template .Must (template .New ("test" ).Parse ("" ))
467489
468490 srv := & Server {
469491 dbpool : dbpool ,
470492 templates : tmpl ,
471493 hmacKey : hmacKey ,
494+ vrf : vrfKey ,
472495 reader : logReader ,
473496 appender : appender ,
474497 awaiter : awaiter ,
@@ -495,6 +518,7 @@ func startServerCmd() script.Cmd {
495518 globalEnv .serverURL = serverURL
496519 globalEnv .dbPath = dbPath
497520 globalEnv .verifier = verifier
521+ globalEnv .vrfPubKey = vrfKey .PublicKey ()
498522 globalEnv .server = srv
499523 globalEnv .cleanup = func () {
500524 testServer .Close ()
@@ -536,8 +560,12 @@ func insertKeyCmd() script.Cmd {
536560
537561 ctx := context .Background ()
538562
563+ // Compute VRF hash and proof
564+ vrfProof := globalEnv .server .vrf .Prove ([]byte (email ))
565+ vrfHash := base64 .StdEncoding .EncodeToString (vrfProof .Hash ())
566+
539567 // Add to transparency log
540- entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , email , pubkey ))
568+ entry := tessera .NewEntry (fmt .Appendf (nil , "%s\n %s\n " , vrfHash , pubkey ))
541569 index , _ , err := globalEnv .server .awaiter .Await (ctx , globalEnv .server .appender .Add (ctx , entry ))
542570 if err != nil {
543571 return nil , fmt .Errorf ("failed to add to transparency log: %w" , err )
@@ -548,6 +576,7 @@ func insertKeyCmd() script.Cmd {
548576 Pubkey : pubkey ,
549577 UpdatedAt : time .Now ().Unix (),
550578 LogIndex : int64 (index .Index ),
579+ VRFProof : vrfProof .Bytes (),
551580 }
552581
553582 jsonData , err := json .Marshal (data )
@@ -600,9 +629,12 @@ func cliCmd() script.Cmd {
600629 if globalEnv .verifier == nil {
601630 return nil , fmt .Errorf ("no verifier available (use startserver first)" )
602631 }
632+ if globalEnv .vrfPubKey == nil {
633+ return nil , fmt .Errorf ("no VRF public key available (use startserver first)" )
634+ }
603635
604636 // Call the lookup function directly
605- pubkey , err := lookupKey (serverURL , globalEnv .verifier , email )
637+ pubkey , err := lookupKey (serverURL , globalEnv .verifier , globalEnv . vrfPubKey , email )
606638 if err != nil {
607639 return nil , err
608640 }
@@ -632,6 +664,7 @@ func stopServerCmd() script.Cmd {
632664 globalEnv .serverURL = ""
633665 globalEnv .dbPath = ""
634666 globalEnv .verifier = nil
667+ globalEnv .vrfPubKey = nil
635668 globalEnv .server = nil
636669 }
637670
0 commit comments