aboutsummaryrefslogtreecommitdiff
path: root/pkg/types/leaf.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/types/leaf.go')
-rw-r--r--pkg/types/leaf.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/pkg/types/leaf.go b/pkg/types/leaf.go
new file mode 100644
index 0000000..1476ead
--- /dev/null
+++ b/pkg/types/leaf.go
@@ -0,0 +1,111 @@
+package types
+
+import (
+ "crypto"
+ "crypto/ed25519"
+ "encoding/binary"
+ "fmt"
+ "io"
+
+ "git.sigsum.org/sigsum-lib-go/pkg/ascii"
+)
+
+type Statement struct {
+ ShardHint uint64 `ascii:"shard_hint"`
+ Checksum Hash `ascii:"checksum"`
+}
+
+type Leaf struct {
+ Statement
+ Signature Signature `ascii:"signature"`
+ KeyHash Hash `ascii:"key_hash"`
+}
+
+type Leaves []Leaf
+
+func (s *Statement) ToBinary() []byte {
+ b := make([]byte, 40)
+ binary.BigEndian.PutUint64(b[0:8], s.ShardHint)
+ copy(b[8:40], s.Checksum[:])
+ return b
+}
+
+func (s *Statement) Sign(signer crypto.Signer) (*Signature, error) {
+ sig, err := signer.Sign(nil, s.ToBinary(), crypto.Hash(0))
+ if err != nil {
+ return nil, fmt.Errorf("types: failed signing statement")
+ }
+
+ var signature Signature
+ copy(signature[:], sig)
+ return &signature, nil
+}
+
+func (s *Statement) Verify(key *PublicKey, sig *Signature) bool {
+ return ed25519.Verify(ed25519.PublicKey(key[:]), s.ToBinary(), sig[:])
+}
+
+func (l *Leaf) ToBinary() []byte {
+ b := make([]byte, 136)
+ binary.BigEndian.PutUint64(b[0:8], l.ShardHint)
+ copy(b[8:40], l.Checksum[:])
+ copy(b[40:104], l.Signature[:])
+ copy(b[104:136], l.KeyHash[:])
+ return b
+}
+
+func (l *Leaf) FromBinary(b []byte) error {
+ if len(b) != 136 {
+ return fmt.Errorf("types: invalid leaf size: %d", len(b))
+ }
+
+ l.ShardHint = binary.BigEndian.Uint64(b[0:8])
+ copy(l.Checksum[:], b[8:40])
+ copy(l.Signature[:], b[40:104])
+ copy(l.KeyHash[:], b[104:136])
+ return nil
+}
+
+func (l *Leaf) ToASCII(w io.Writer) error {
+ return ascii.StdEncoding.Serialize(w, l)
+}
+
+func (l *Leaf) FromASCII(r io.Reader) error {
+ return ascii.StdEncoding.Deserialize(r, l)
+}
+
+func (l *Leaves) FromASCII(r io.Reader) error {
+ leaves := &struct {
+ ShardHint []uint64 `ascii:"shard_hint"`
+ Checksum []Hash `ascii:"checksum"`
+ Signature []Signature `ascii:"signature"`
+ KeyHash []Hash `ascii:"key_hash"`
+ }{}
+
+ if err := ascii.StdEncoding.Deserialize(r, leaves); err != nil {
+ return err
+ }
+ n := len(leaves.ShardHint)
+ if n != len(leaves.Checksum) {
+ return fmt.Errorf("types: mismatched leaf field counts")
+ }
+ if n != len(leaves.Signature) {
+ return fmt.Errorf("types: mismatched leaf field counts")
+ }
+ if n != len(leaves.KeyHash) {
+ return fmt.Errorf("types: mismatched leaf field counts")
+ }
+
+ *l = make([]Leaf, 0, n)
+ for i := 0; i < n; i++ {
+ *l = append(*l, Leaf{
+ Statement: Statement{
+ ShardHint: leaves.ShardHint[i],
+ Checksum: leaves.Checksum[i],
+ },
+ Signature: leaves.Signature[i],
+ KeyHash: leaves.KeyHash[i],
+ })
+ }
+ return nil
+}