arnaucube
arnaucube/go-blindsecp256k1Public Self-hosted repository
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}