-
Notifications
You must be signed in to change notification settings - Fork 35
/
signature.go
132 lines (117 loc) · 2.64 KB
/
signature.go
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
package crypto
import (
"bytes"
"fmt"
"io"
"math"
cbg "github.com/whyrusleeping/cbor-gen"
)
type SigType byte
const (
SigTypeUnknown = SigType(math.MaxUint8)
SigTypeSecp256k1 = SigType(iota)
SigTypeBLS
SigTypeDelegated
)
func (t SigType) Name() (string, error) {
switch t {
case SigTypeUnknown:
return "unknown", nil
case SigTypeSecp256k1:
return "secp256k1", nil
case SigTypeBLS:
return "bls", nil
case SigTypeDelegated:
return "delegated", nil
default:
return "", fmt.Errorf("invalid signature type: %d", t)
}
}
const SignatureMaxLength = 200
type Signature struct {
Type SigType
Data []byte
}
func (s *Signature) Equals(o *Signature) bool {
if s == nil || o == nil {
return s == o
}
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
}
func (s *Signature) MarshalCBOR(w io.Writer) error {
if s == nil {
_, err := w.Write(cbg.CborNull)
return err
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write([]byte{byte(s.Type)}); err != nil {
return err
}
if _, err := w.Write(s.Data); err != nil {
return err
}
return nil
}
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
maj, l, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("not a byte string")
}
if l > SignatureMaxLength {
return fmt.Errorf("string too long")
}
if l == 0 {
return fmt.Errorf("string empty")
}
buf := make([]byte, l)
if _, err = io.ReadFull(br, buf); err != nil {
return err
}
switch SigType(buf[0]) {
default:
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
case SigTypeDelegated:
s.Type = SigTypeDelegated
}
s.Data = buf[1:]
return nil
}
func (s *Signature) MarshalBinary() ([]byte, error) {
bs := make([]byte, len(s.Data)+1)
bs[0] = byte(s.Type)
copy(bs[1:], s.Data)
return bs, nil
}
func (s *Signature) UnmarshalBinary(bs []byte) error {
if len(bs) > SignatureMaxLength {
return fmt.Errorf("invalid signature bytes, too long (%d)", len(bs))
}
if len(bs) == 0 {
return fmt.Errorf("invalid signature bytes of length 0")
}
switch SigType(bs[0]) {
default:
// Do not error during unmarshal but leave a standard value.
// unmarshal(marshal(zero valued sig)) is valuable for test
// and type needs to be checked by caller anyway.
s.Type = SigTypeUnknown
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
case SigTypeDelegated:
s.Type = SigTypeDelegated
}
s.Data = bs[1:]
return nil
}