go-blindsecp256k1/parsers.go
parsers.goRaw
1package blindsecp256k1
2
3import (
4 "encoding/json"
5 "fmt"
6 "math/big"
7)
8
9// swapEndianness swaps the order of the bytes in the slice.
10func swapEndianness(b []byte) []byte {
11 o := make([]byte, len(b))
12 for i := range b {
13 o[len(b)-1-i] = b[i]
14 }
15 return o
16}
17
18// MarshalJSON implements the json marshaler for the Point
19func (p Point) MarshalJSON() ([]byte, error) {
20 return json.Marshal(&struct {
21 X string `json:"x"`
22 Y string `json:"y"`
23 }{
24 X: p.X.String(),
25 Y: p.Y.String(),
26 })
27}
28
29// UnmarshalJSON implements the json unmarshaler for the Point
30func (p *Point) UnmarshalJSON(b []byte) error {
31 aux := &struct {
32 X string `json:"x"`
33 Y string `json:"y"`
34 }{}
35 err := json.Unmarshal(b, &aux)
36 if err != nil {
37 return err
38 }
39 x, ok := new(big.Int).SetString(aux.X, 10)
40 if !ok {
41 return fmt.Errorf("Can not parse Point.X %s", aux.X)
42 }
43 y, ok := new(big.Int).SetString(aux.Y, 10)
44 if !ok {
45 return fmt.Errorf("Can not parse Point.Y %s", aux.Y)
46 }
47 p.X = x
48 p.Y = y
49 return nil
50}
51
52// Bytes returns a byte array of length 64, with the X & Y coordinates of the
53// Point encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
54func (p *Point) Bytes() []byte {
55 var b [64]byte
56 copy(b[:32], swapEndianness(p.X.Bytes()))
57 copy(b[32:], swapEndianness(p.Y.Bytes()))
58 return b[:]
59}
60
61// NewPointFromBytes returns a new *Point from a given byte array with length
62// 64 which has encoded the point coordinates each one as 32 bytes in
63// little-endian.
64func NewPointFromBytes(b []byte) (*Point, error) {
65 if len(b) != 64 { //nolint:gomnd
66 return nil,
67 fmt.Errorf("Can not parse bytes to Point, expected byte array of length %d, current %d",
68 64, len(b))
69 }
70 p := &Point{}
71 p.X = new(big.Int).SetBytes(swapEndianness(b[:32]))
72 p.Y = new(big.Int).SetBytes(swapEndianness(b[32:]))
73 return p, nil
74}
75
76// MarshalJSON implements the json marshaler for the PublicKey
77func (pk PublicKey) MarshalJSON() ([]byte, error) {
78 return json.Marshal(pk.Point())
79}
80
81// UnmarshalJSON implements the json unmarshaler for the PublicKey
82func (pk *PublicKey) UnmarshalJSON(b []byte) error {
83 var point *Point
84 err := json.Unmarshal(b, &point)
85 if err != nil {
86 return err
87 }
88 pk.X = point.X
89 pk.Y = point.Y
90 return nil
91}
92
93// Bytes returns a byte array of length 64, with the X & Y coordinates of the
94// PublicKey encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
95func (pk *PublicKey) Bytes() []byte {
96 return pk.Point().Bytes()
97}
98
99// NewPublicKeyFromBytes returns a new *PublicKey from a given byte array with
100// length 64 which has encoded the public key coordinates each one as 32 bytes
101// in little-endian.
102func NewPublicKeyFromBytes(b []byte) (*PublicKey, error) {
103 p, err := NewPointFromBytes(b)
104 if err != nil {
105 return nil, err
106 }
107 pk := PublicKey(*p)
108 return &pk, nil
109}
110
111// MarshalJSON implements the json marshaler for the Signature
112func (sig Signature) MarshalJSON() ([]byte, error) {
113 return json.Marshal(&struct {
114 S string `json:"s"`
115 F struct {
116 X string `json:"x"`
117 Y string `json:"y"`
118 } `json:"f"`
119 }{
120 S: sig.S.String(),
121 F: struct {
122 X string `json:"x"`
123 Y string `json:"y"`
124 }{
125 X: sig.F.X.String(),
126 Y: sig.F.Y.String(),
127 },
128 })
129}
130
131// UnmarshalJSON implements the json unmarshaler for the Signature
132func (sig *Signature) UnmarshalJSON(b []byte) error {
133 aux := &struct {
134 S string `json:"s"`
135 F struct {
136 X string `json:"x"`
137 Y string `json:"y"`
138 } `json:"f"`
139 }{}
140 err := json.Unmarshal(b, &aux)
141 if err != nil {
142 return err
143 }
144
145 s, ok := new(big.Int).SetString(aux.S, 10)
146 if !ok {
147 return fmt.Errorf("Can not parse sig.S %s", aux.S)
148 }
149 sig.S = s
150
151 x, ok := new(big.Int).SetString(aux.F.X, 10)
152 if !ok {
153 return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X)
154 }
155 y, ok := new(big.Int).SetString(aux.F.Y, 10)
156 if !ok {
157 return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y)
158 }
159 sig.F = &Point{}
160 sig.F.X = x
161 sig.F.Y = y
162 return nil
163}
164
165// Bytes returns a byte array of length 96, with the S, F.X and F.Y coordinates
166// of the Signature encoded in little-endian.
167// [ S (32 bytes | F.X (32 bytes) | F.Y (32 bytes)]
168func (sig *Signature) Bytes() []byte {
169 var b [96]byte
170 copy(b[:32], swapEndianness(sig.S.Bytes()))
171 copy(b[32:96], sig.F.Bytes())
172 return b[:]
173}
174
175// NewSignatureFromBytes returns a new *Signature from a given byte array with
176// length 96 which has encoded S and the F point coordinates each one as 32
177// bytes in little-endian.
178func NewSignatureFromBytes(b []byte) (*Signature, error) {
179 if len(b) != 96 { //nolint:gomnd
180 return nil,
181 fmt.Errorf("Can not parse bytes to Signature, expected byte array of length %d, current %d",
182 96, len(b))
183 }
184 s := new(big.Int).SetBytes(swapEndianness(b[:32]))
185 f, err := NewPointFromBytes(b[32:96])
186 if err != nil {
187 return nil, err
188 }
189 return &Signature{
190 S: s,
191 F: f,
192 }, nil
193}