/
signature.go
132 lines (111 loc) · 3.17 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 gotez
import (
"encoding/json"
"fmt"
"math/big"
"math/bits"
"unsafe"
)
type Signature interface {
Base58Encoder
Signature()
}
type ConventionalSignature interface {
Signature
Generic() *GenericSignature
}
func (sig *GenericSignature) Signature() {}
func (sig *GenericSignature) Generic() *GenericSignature { return sig }
func (sig *Ed25519Signature) Signature() {}
func (sig *Ed25519Signature) Generic() *GenericSignature { return (*GenericSignature)(sig) }
func (sig *Secp256k1Signature) Signature() {}
func (sig *Secp256k1Signature) Generic() *GenericSignature { return (*GenericSignature)(sig) }
func (sig *P256Signature) Signature() {}
func (sig *P256Signature) Generic() *GenericSignature { return (*GenericSignature)(sig) }
func (sig *BLSSignature) Signature() {}
func NewEd25519Signature(sig []byte) *Ed25519Signature {
var out Ed25519Signature
if len(sig) != len(out) {
panic("gotez: invalid ed25519 signature length length")
}
copy(out[:], sig)
return &out
}
func bigByteLen(x *big.Int) int {
return len(x.Bits()) * (bits.UintSize / 8)
}
func NewSecp256k1Signature(r, s *big.Int) *Secp256k1Signature {
if bigByteLen(r) > 32 || bigByteLen(s) > 32 {
panic("gotez: invalid ECDSA signature size")
}
var out Secp256k1Signature
r.FillBytes(out[:32])
s.FillBytes(out[32:])
return &out
}
func (sig *Secp256k1Signature) Point() (r, s *big.Int) {
return new(big.Int).SetBytes(sig[:32]), new(big.Int).SetBytes(sig[32:])
}
func NewP256Signature(r, s *big.Int) *P256Signature {
if bigByteLen(r) > 32 || bigByteLen(s) > 32 {
panic("gotez: invalid ECDSA signature size")
}
var out P256Signature
r.FillBytes(out[:32])
s.FillBytes(out[32:])
return &out
}
func (sig *P256Signature) Point() (r, s *big.Int) {
return new(big.Int).SetBytes(sig[:32]), new(big.Int).SetBytes(sig[32:])
}
func NewBLSSignature(compressedPoint []byte) *BLSSignature {
var out BLSSignature
if len(compressedPoint) != len(out) {
panic("gotez: invalid ed25519 signature length length")
}
copy(out[:], compressedPoint)
return &out
}
func (sig *BLSSignature) Split() (prefix *[32]byte, suffix *GenericSignature) {
return (*[32]byte)(unsafe.Pointer(&sig[0])), (*GenericSignature)(unsafe.Pointer(&sig[32]))
}
type AnySignature []byte
func (sig AnySignature) Signature() (Signature, error) {
switch len(sig) {
case GenericSignatureBytesLen:
return (*GenericSignature)(unsafe.Pointer(&sig[0])), nil
case BLSSignatureBytesLen:
return (*BLSSignature)(unsafe.Pointer(&sig[0])), nil
default:
return nil, fmt.Errorf("gotez: invalid signature length: %d", len(sig))
}
}
func (sig AnySignature) String() string {
s, err := sig.Signature()
if err != nil {
return fmt.Sprintf("<%v>", err)
}
return string(s.ToBase58())
}
func (sig AnySignature) MarshalText() ([]byte, error) {
if len(sig) == 0 {
return []byte{}, nil
}
s, err := sig.Signature()
if err != nil {
return nil, err
}
return s.ToBase58(), nil
}
func (sig AnySignature) MarshalJSON() ([]byte, error) {
var x *string
if len(sig) != 0 {
buf, err := sig.MarshalText()
if err != nil {
return nil, err
}
val := string(buf)
x = &val
}
return json.Marshal(x)
}