1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
package types
import (
"crypto"
"crypto/ed25519"
"crypto/sha256"
"fmt"
"strings"
)
const (
HashSize = sha256.Size
SignatureSize = ed25519.SignatureSize
VerificationKeySize = ed25519.PublicKeySize
EndpointAddLeaf = Endpoint("add-leaf")
EndpointAddCosignature = Endpoint("add-cosignature")
EndpointGetTreeHeadLatest = Endpoint("get-tree-head-latest")
EndpointGetTreeHeadToSign = Endpoint("get-tree-head-to-sign")
EndpointGetTreeHeadCosigned = Endpoint("get-tree-head-cosigned")
EndpointGetInclusionProof = Endpoint("get-inclusion-proof")
EndpointGetConsistencyProof = Endpoint("get-consistency-proof")
EndpointGetLeaves = Endpoint("get-leaves")
)
// Endpoint is a named HTTP API endpoint
type Endpoint string
// Path joins a number of components to form a full endpoint path. For example,
// EndpointAddLeaf.Path("example.com", "st/v0") -> example.com/st/v0/add-leaf.
func (e Endpoint) Path(components ...string) string {
return strings.Join(append(components, string(e)), "/")
}
type Leaf struct {
Message
SigIdent
}
type Message struct {
ShardHint uint64
Checksum *[HashSize]byte
}
type SigIdent struct {
Signature *[SignatureSize]byte
KeyHash *[HashSize]byte
}
type SignedTreeHead struct {
TreeHead
Signature *[SignatureSize]byte
}
type CosignedTreeHead struct {
SignedTreeHead
SigIdent []*SigIdent
}
type TreeHead struct {
Timestamp uint64
TreeSize uint64
RootHash *[HashSize]byte
KeyHash *[HashSize]byte
}
type ConsistencyProof struct {
NewSize uint64
OldSize uint64
Path []*[HashSize]byte
}
type InclusionProof struct {
TreeSize uint64
LeafIndex uint64
Path []*[HashSize]byte
}
type LeafList []*Leaf
type ConsistencyProofRequest struct {
NewSize uint64
OldSize uint64
}
type InclusionProofRequest struct {
LeafHash *[HashSize]byte
TreeSize uint64
}
type LeavesRequest struct {
StartSize uint64
EndSize uint64
}
type LeafRequest struct {
Message
Signature *[SignatureSize]byte
VerificationKey *[VerificationKeySize]byte
DomainHint string
}
type CosignatureRequest struct {
SigIdent
}
// Sign signs the tree head using the log's signature scheme
func (th *TreeHead) Sign(signer crypto.Signer) (*SignedTreeHead, error) {
sig, err := signer.Sign(nil, th.Marshal(), crypto.Hash(0))
if err != nil {
return nil, fmt.Errorf("Sign: %v", err)
}
sth := &SignedTreeHead{
TreeHead: *th,
Signature: &[SignatureSize]byte{},
}
copy(sth.Signature[:], sig)
return sth, nil
}
// Verify verifies the tree head signature using the log's signature scheme
func (th *TreeHead) Verify(vk *[VerificationKeySize]byte, sig *[SignatureSize]byte) error {
if !ed25519.Verify(ed25519.PublicKey(vk[:]), th.Marshal(), sig[:]) {
return fmt.Errorf("invalid tree head signature")
}
return nil
}
// Verify checks if a leaf is included in the log
func (p *InclusionProof) Verify(leaf *Leaf, th *TreeHead) error { // TODO
return nil
}
// Verify checks if two tree heads are consistent
func (p *ConsistencyProof) Verify(oldTH, newTH *TreeHead) error { // TODO
return nil
}
|