Skip to content

Commit 3d5115c

Browse files
committedMar 17, 2024·
cmd/spicy: implement verification
1 parent e430fdd commit 3d5115c

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed
 

‎cmd/spicy/spicy.go

+67
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
)
1717

1818
func main() {
19+
verifyFlag := flag.String("verify", "",
20+
"verify the file's spicy signature with the given public key")
1921
keyFlag := flag.String("key", "",
2022
"the log's private key path (written by -init)")
2123
initFlag := flag.String("init", "",
@@ -24,6 +26,71 @@ func main() {
2426
"directory where log entries and metadata are stored")
2527
flag.Parse()
2628

29+
if *verifyFlag != "" {
30+
if len(flag.Args()) == 0 {
31+
log.Fatalf("no files to verify")
32+
}
33+
vkey, err := note.NewVerifier(*verifyFlag)
34+
if err != nil {
35+
log.Fatalf("could not parse public key: %v", err)
36+
}
37+
for _, path := range flag.Args() {
38+
f, err := os.ReadFile(path)
39+
if err != nil {
40+
log.Fatalf("could not read %q: %v", path, err)
41+
}
42+
sig, err := os.ReadFile(path + ".spicy")
43+
if err != nil {
44+
log.Fatalf("could not read %q: %v", path+".spicy", err)
45+
}
46+
s := string(sig)
47+
s, ok := strings.CutPrefix(s, "index ")
48+
if !ok {
49+
log.Fatalf("malformed spicy signature for %q", path)
50+
}
51+
i, s, ok := strings.Cut(s, "\n")
52+
if !ok {
53+
log.Fatalf("malformed spicy signature for %q", path)
54+
}
55+
index, err := strconv.ParseInt(i, 10, 64)
56+
if err != nil {
57+
log.Fatalf("malformed spicy signature for %q: %v", path, err)
58+
}
59+
var proof tlog.RecordProof
60+
for {
61+
var h string
62+
h, s, ok = strings.Cut(s, "\n")
63+
if !ok {
64+
log.Fatalf("malformed spicy signature for %q", path)
65+
}
66+
if h == "" {
67+
break
68+
}
69+
hh, err := tlog.ParseHash(h)
70+
if err != nil {
71+
log.Fatalf("malformed spicy signature for %q: %v", path, err)
72+
}
73+
proof = append(proof, hh)
74+
}
75+
m, err := note.Open([]byte(s), note.VerifierList(vkey))
76+
if err != nil {
77+
log.Fatalf("could not verify checkpoint for %q: %v", path, err)
78+
}
79+
c, err := tlogx.ParseCheckpoint(m.Text)
80+
if err != nil {
81+
log.Fatalf("could not parse checkpoint for %q: %v", path, err)
82+
}
83+
if c.Origin != vkey.Name() {
84+
log.Fatalf("spicy signature for %q is for a different log: got %q, want %q", path, c.Origin, vkey.Name())
85+
}
86+
if err := tlog.CheckRecord(proof, c.N, c.Hash, index, tlog.RecordHash(f)); err != nil {
87+
log.Fatalf("could not verify inclusion for %q: %v", path, err)
88+
}
89+
}
90+
fmt.Fprintf(os.Stderr, "Spicy signature(s) verified! 🌶️\n")
91+
return
92+
}
93+
2794
if *initFlag != "" {
2895
latestPath := filepath.Join(*assetsFlag, "latest")
2996
if _, err := os.Stat(latestPath); err == nil {

0 commit comments

Comments
 (0)
Please sign in to comment.