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