go-blindsecp256k1/parsers.go
parsers.goRaw
1package blindsecp256k1
2
3import (
4 "encoding/json"
5 "fmt"
6 "math/big"
7
8 "github.com/ethereum/go-ethereum/crypto"
9)
10
11// swapEndianness swaps the order of the bytes in the slice.
12func swapEndianness(b []byte) []byte {
13 o := make([]byte, len(b))
14 for i := range b {
15 o[len(b)-1-i] = b[i]
16 }
17 return o
18}
19
20// MarshalJSON implements the json marshaler for the Point
21func (p Point) MarshalJSON() ([]byte, error) {
22 return json.Marshal(&struct {
23 X string `json:"x"`
24 Y string `json:"y"`
25 }{
26 X: p.X.String(),
27 Y: p.Y.String(),
28 })
29}
30
31// UnmarshalJSON implements the json unmarshaler for the Point
32func (p *Point) UnmarshalJSON(b []byte) error {
33 aux := &struct {
34 X string `json:"x"`
35 Y string `json:"y"`
36 }{}
37 err := json.Unmarshal(b, &aux)
38 if err != nil {
39 return err
40 }
41 x, ok := new(big.Int).SetString(aux.X, 10)
42 if !ok {
43 return fmt.Errorf("Can not parse Point.X %s", aux.X)
44 }
45 y, ok := new(big.Int).SetString(aux.Y, 10)
46 if !ok {
47 return fmt.Errorf("Can not parse Point.Y %s", aux.Y)
48 }
49 p.X = x
50 p.Y = y
51 return nil
52}
53
54// Bytes returns the compressed Point in a little-endian byte array
55func (p *Point) Bytes() []byte {
56 b := p.Compress()
57 return b[:]
58}
59
60// NewPointFromBytes returns a new *Point from a given byte array with length
61// 64 which has encoded the point coordinates each one as 32 bytes in
62// little-endian.
63func NewPointFromBytes(b []byte) (*Point, error) {
64 if len(b) != 33 { //nolint:gomnd
65 return nil, fmt.Errorf("Can not parse bytes to Point,"+
66 " expected byte array of length %d, current %d",
67 33, len(b))
68 }
69
70 var pBytes [33]byte
71 copy(pBytes[:], b[:])
72 return DecompressPoint(pBytes)
73}
74
75// BytesUncompressed returns a byte array of length 64, with the X & Y
76// coordinates of the Point encoded in little-endian. [ X (32 bytes) | Y (32
77// bytes)]
78func (p *Point) BytesUncompressed() []byte {
79 var b [64]byte
80 copy(b[:32], swapEndianness(p.X.Bytes()))
81 copy(b[32:], swapEndianness(p.Y.Bytes()))
82 return b[:]
83}
84
85// NewPointFromBytesUncompressed returns a new *Point from a given byte array
86// with length 64 which has encoded the point coordinates each one as 32 bytes
87// in little-endian.
88func NewPointFromBytesUncompressed(b []byte) (*Point, error) {
89 if len(b) != 64 { //nolint:gomnd
90 return nil, fmt.Errorf("Can not parse bytes to Point,"+
91 " expected byte array of length %d, current %d",
92 64, len(b))
93 }
94 p := &Point{}
95 p.X = new(big.Int).SetBytes(swapEndianness(b[:32]))
96 p.Y = new(big.Int).SetBytes(swapEndianness(b[32:]))
97 return p, nil
98}
99
100// MarshalJSON implements the json marshaler for the PublicKey
101func (pk PublicKey) MarshalJSON() ([]byte, error) {
102 return json.Marshal(pk.Point())
103}
104
105// UnmarshalJSON implements the json unmarshaler for the PublicKey
106func (pk *PublicKey) UnmarshalJSON(b []byte) error {
107 var point *Point
108 err := json.Unmarshal(b, &point)
109 if err != nil {
110 return err
111 }
112 pk.X = point.X
113 pk.Y = point.Y
114 return nil
115}
116
117// Bytes returns the compressed PublicKey in a little-endian byte array
118func (pk *PublicKey) Bytes() []byte {
119 return pk.Point().Bytes()
120}
121
122// NewPublicKeyFromBytes returns a new *PublicKey from a given byte array with
123// length 64 which has encoded the public key coordinates each one as 32 bytes
124// in little-endian.
125func NewPublicKeyFromBytes(b []byte) (*PublicKey, error) {
126 p, err := NewPointFromBytes(b)
127 if err != nil {
128 return nil, err
129 }
130 pk := PublicKey(*p)
131 return &pk, nil
132}
133
134// BytesUncompressed returns a byte array of length 64, with the X & Y
135// coordinates of the PublicKey encoded in little-endian.
136// [ X (32 bytes) | Y (32 bytes)]
137func (pk *PublicKey) BytesUncompressed() []byte {
138 return pk.Point().BytesUncompressed()
139}
140
141// NewPublicKeyFromBytesUncompressed returns a new *PublicKey from a given byte array with
142// length 64 which has encoded the public key coordinates each one as 32 bytes
143// in little-endian.
144func NewPublicKeyFromBytesUncompressed(b []byte) (*PublicKey, error) {
145 p, err := NewPointFromBytesUncompressed(b)
146 if err != nil {
147 return nil, err
148 }
149 pk := PublicKey(*p)
150 return &pk, nil
151}
152
153// NewPublicKeyFromECDSA returns a *PublicKey from a serialized/marshaled array
154// of bytes generated by the ethereum/standard ECDSA PubKey implementation.
155func NewPublicKeyFromECDSA(b []byte) (*PublicKey, error) {
156 pub, err := crypto.UnmarshalPubkey(b)
157 if err != nil {
158 return nil, err
159 }
160 pk := new(PublicKey)
161 pk.X = pub.X
162 pk.Y = pub.Y
163 return pk, nil
164}
165
166// MarshalJSON implements the json marshaler for the Signature
167func (sig Signature) MarshalJSON() ([]byte, error) {
168 return json.Marshal(&struct {
169 S string `json:"s"`
170 F struct {
171 X string `json:"x"`
172 Y string `json:"y"`
173 } `json:"f"`
174 }{
175 S: sig.S.String(),
176 F: struct {
177 X string `json:"x"`
178 Y string `json:"y"`
179 }{
180 X: sig.F.X.String(),
181 Y: sig.F.Y.String(),
182 },
183 })
184}
185
186// UnmarshalJSON implements the json unmarshaler for the Signature
187func (sig *Signature) UnmarshalJSON(b []byte) error {
188 aux := &struct {
189 S string `json:"s"`
190 F struct {
191 X string `json:"x"`
192 Y string `json:"y"`
193 } `json:"f"`
194 }{}
195 err := json.Unmarshal(b, &aux)
196 if err != nil {
197 return err
198 }
199
200 s, ok := new(big.Int).SetString(aux.S, 10)
201 if !ok {
202 return fmt.Errorf("Can not parse sig.S %s", aux.S)
203 }
204 sig.S = s
205
206 x, ok := new(big.Int).SetString(aux.F.X, 10)
207 if !ok {
208 return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X)
209 }
210 y, ok := new(big.Int).SetString(aux.F.Y, 10)
211 if !ok {
212 return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y)
213 }
214 sig.F = &Point{}
215 sig.F.X = x
216 sig.F.Y = y
217 return nil
218}
219
220// Bytes returns the compressed Signature in a little-endian byte array
221func (sig *Signature) Bytes() []byte {
222 s := sig.Compress()
223 return s[:]
224}
225
226// NewSignatureFromBytes returns a new *Signature from a given byte array with
227// length 96 which has encoded S and the F point coordinates each one as 32
228// bytes in little-endian.
229func NewSignatureFromBytes(b []byte) (*Signature, error) {
230 if len(b) != 65 { //nolint:gomnd
231 return nil,
232 fmt.Errorf("Can not parse bytes to Signature,"+
233 " expected byte array of length %d, current %d",
234 65, len(b))
235 }
236 s := new(big.Int).SetBytes(swapEndianness(b[:32]))
237 f, err := NewPointFromBytes(b[32:65])
238 if err != nil {
239 return nil, err
240 }
241 return &Signature{
242 S: s,
243 F: f,
244 }, nil
245}
246
247// BytesUncompressed returns a byte array of length 96, with the S, F.X and F.Y
248// coordinates of the Signature encoded in little-endian.
249// [ S (32 bytes | F.X (32 bytes) | F.Y (32 bytes)]
250func (sig *Signature) BytesUncompressed() []byte {
251 var b [96]byte
252 copy(b[:32], swapEndianness(sig.S.Bytes()))
253 copy(b[32:96], sig.F.BytesUncompressed())
254 return b[:]
255}
256
257// NewSignatureFromBytesUncompressed returns a new *Signature from a given byte array with
258// length 96 which has encoded S and the F point coordinates each one as 32
259// bytes in little-endian.
260func NewSignatureFromBytesUncompressed(b []byte) (*Signature, error) {
261 if len(b) != 96 { //nolint:gomnd
262 return nil,
263 fmt.Errorf("Can not parse bytes to Signature,"+
264 " expected byte array of length %d, current %d",
265 96, len(b))
266 }
267 s := new(big.Int).SetBytes(swapEndianness(b[:32]))
268 f, err := NewPointFromBytesUncompressed(b[32:96])
269 if err != nil {
270 return nil, err
271 }
272 return &Signature{
273 S: s,
274 F: f,
275 }, nil
276}