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