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 a byte array of length 64, with the X & Y coordinates of the
55// Point encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
56func (p *Point) Bytes() []byte {
57 var b [64]byte
58 copy(b[:32], swapEndianness(p.X.Bytes()))
59 copy(b[32:], swapEndianness(p.Y.Bytes()))
60 return b[:]
61}
62
63// NewPointFromBytes returns a new *Point from a given byte array with length
64// 64 which has encoded the point coordinates each one as 32 bytes in
65// little-endian.
66func NewPointFromBytes(b []byte) (*Point, error) {
67 if len(b) != 64 { //nolint:gomnd
68 return nil, fmt.Errorf("Can not parse bytes to Point,"+
69 " expected byte array of length %d, current %d",
70 64, len(b))
71 }
72 p := &Point{}
73 p.X = new(big.Int).SetBytes(swapEndianness(b[:32]))
74 p.Y = new(big.Int).SetBytes(swapEndianness(b[32:]))
75 return p, nil
76}
77
78// MarshalJSON implements the json marshaler for the PublicKey
79func (pk PublicKey) MarshalJSON() ([]byte, error) {
80 return json.Marshal(pk.Point())
81}
82
83// UnmarshalJSON implements the json unmarshaler for the PublicKey
84func (pk *PublicKey) UnmarshalJSON(b []byte) error {
85 var point *Point
86 err := json.Unmarshal(b, &point)
87 if err != nil {
88 return err
89 }
90 pk.X = point.X
91 pk.Y = point.Y
92 return nil
93}
94
95// Bytes returns a byte array of length 64, with the X & Y coordinates of the
96// PublicKey encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
97func (pk *PublicKey) Bytes() []byte {
98 return pk.Point().Bytes()
99}
100
101// NewPublicKeyFromBytes returns a new *PublicKey from a given byte array with
102// length 64 which has encoded the public key coordinates each one as 32 bytes
103// in little-endian.
104func NewPublicKeyFromBytes(b []byte) (*PublicKey, error) {
105 p, err := NewPointFromBytes(b)
106 if err != nil {
107 return nil, err
108 }
109 pk := PublicKey(*p)
110 return &pk, nil
111}
112
113// NewPublicKeyFromECDSA returns a *PublicKey from a serialized/marshaled array
114// of bytes generated by the ethereum/standard ECDSA PubKey implementation.
115func NewPublicKeyFromECDSA(b []byte) (*PublicKey, error) {
116 pub, err := crypto.UnmarshalPubkey(b)
117 if err != nil {
118 return nil, err
119 }
120 pk := new(PublicKey)
121 pk.X = pub.X
122 pk.Y = pub.Y
123 return pk, nil
124}
125
126// MarshalJSON implements the json marshaler for the Signature
127func (sig Signature) MarshalJSON() ([]byte, error) {
128 return json.Marshal(&struct {
129 S string `json:"s"`
130 F struct {
131 X string `json:"x"`
132 Y string `json:"y"`
133 } `json:"f"`
134 }{
135 S: sig.S.String(),
136 F: struct {
137 X string `json:"x"`
138 Y string `json:"y"`
139 }{
140 X: sig.F.X.String(),
141 Y: sig.F.Y.String(),
142 },
143 })
144}
145
146// UnmarshalJSON implements the json unmarshaler for the Signature
147func (sig *Signature) UnmarshalJSON(b []byte) error {
148 aux := &struct {
149 S string `json:"s"`
150 F struct {
151 X string `json:"x"`
152 Y string `json:"y"`
153 } `json:"f"`
154 }{}
155 err := json.Unmarshal(b, &aux)
156 if err != nil {
157 return err
158 }
159
160 s, ok := new(big.Int).SetString(aux.S, 10)
161 if !ok {
162 return fmt.Errorf("Can not parse sig.S %s", aux.S)
163 }
164 sig.S = s
165
166 x, ok := new(big.Int).SetString(aux.F.X, 10)
167 if !ok {
168 return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X)
169 }
170 y, ok := new(big.Int).SetString(aux.F.Y, 10)
171 if !ok {
172 return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y)
173 }
174 sig.F = &Point{}
175 sig.F.X = x
176 sig.F.Y = y
177 return nil
178}
179
180// Bytes returns a byte array of length 96, with the S, F.X and F.Y coordinates
181// of the Signature encoded in little-endian.
182// [ S (32 bytes | F.X (32 bytes) | F.Y (32 bytes)]
183func (sig *Signature) Bytes() []byte {
184 var b [96]byte
185 copy(b[:32], swapEndianness(sig.S.Bytes()))
186 copy(b[32:96], sig.F.Bytes())
187 return b[:]
188}
189
190// NewSignatureFromBytes returns a new *Signature from a given byte array with
191// length 96 which has encoded S and the F point coordinates each one as 32
192// bytes in little-endian.
193func NewSignatureFromBytes(b []byte) (*Signature, error) {
194 if len(b) != 96 { //nolint:gomnd
195 return nil,
196 fmt.Errorf("Can not parse bytes to Signature,"+
197 " expected byte array of length %d, current %d",
198 96, len(b))
199 }
200 s := new(big.Int).SetBytes(swapEndianness(b[:32]))
201 f, err := NewPointFromBytes(b[32:96])
202 if err != nil {
203 return nil, err
204 }
205 return &Signature{
206 S: s,
207 F: f,
208 }, nil
209}