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