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 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}