From 1846d569ac7ffa74af8464a4e59036b63e92497b Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 30 Jan 2021 20:22:44 +0100 Subject: [PATCH] Add byte parsers for Point, PubK, Signature --- blindsecp256k1.go | 107 ----------------------- blindsecp256k1_test.go | 46 ---------- parsers.go | 193 +++++++++++++++++++++++++++++++++++++++++ parsers_test.go | 94 ++++++++++++++++++++ 4 files changed, 287 insertions(+), 153 deletions(-) create mode 100644 parsers.go create mode 100644 parsers_test.go diff --git a/blindsecp256k1.go b/blindsecp256k1.go index 40c25d4..add3d78 100644 --- a/blindsecp256k1.go +++ b/blindsecp256k1.go @@ -12,8 +12,6 @@ package blindsecp256k1 import ( "bytes" "crypto/rand" - "encoding/json" - "fmt" "math/big" "github.com/btcsuite/btcd/btcec" @@ -55,40 +53,6 @@ func (p *Point) Mul(scalar *big.Int) *Point { } } -// MarshalJSON implements the json marshaler for the Point -func (p Point) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - X string `json:"x"` - Y string `json:"y"` - }{ - X: p.X.String(), - Y: p.Y.String(), - }) -} - -// UnmarshalJSON implements the json unmarshaler for the Point -func (p *Point) UnmarshalJSON(b []byte) error { - aux := &struct { - X string `json:"x"` - Y string `json:"y"` - }{} - err := json.Unmarshal(b, &aux) - if err != nil { - return err - } - x, ok := new(big.Int).SetString(aux.X, 10) - if !ok { - return fmt.Errorf("Can not parse Point.X %s", aux.X) - } - y, ok := new(big.Int).SetString(aux.Y, 10) - if !ok { - return fmt.Errorf("Can not parse Point.Y %s", aux.Y) - } - p.X = x - p.Y = y - return nil -} - // WIP func newRand() *big.Int { var b [32]byte @@ -106,23 +70,6 @@ type PrivateKey big.Int // PublicKey represents the signer's public key type PublicKey Point -// MarshalJSON implements the json marshaler for the PublicKey -func (pk PublicKey) MarshalJSON() ([]byte, error) { - return json.Marshal(pk.Point()) -} - -// UnmarshalJSON implements the json unmarshaler for the PublicKey -func (pk *PublicKey) UnmarshalJSON(b []byte) error { - var point *Point - err := json.Unmarshal(b, &point) - if err != nil { - return err - } - pk.X = point.X - pk.Y = point.Y - return nil -} - // NewPrivateKey returns a new random private key func NewPrivateKey() *PrivateKey { k := newRand() @@ -204,60 +151,6 @@ type Signature struct { F *Point } -// MarshalJSON implements the json marshaler for the Signature -func (sig Signature) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - S string `json:"s"` - F struct { - X string `json:"x"` - Y string `json:"y"` - } `json:"f"` - }{ - S: sig.S.String(), - F: struct { - X string `json:"x"` - Y string `json:"y"` - }{ - X: sig.F.X.String(), - Y: sig.F.Y.String(), - }, - }) -} - -// UnmarshalJSON implements the json unmarshaler for the Signature -func (sig *Signature) UnmarshalJSON(b []byte) error { - aux := &struct { - S string `json:"s"` - F struct { - X string `json:"x"` - Y string `json:"y"` - } `json:"f"` - }{} - err := json.Unmarshal(b, &aux) - if err != nil { - return err - } - - s, ok := new(big.Int).SetString(aux.S, 10) - if !ok { - return fmt.Errorf("Can not parse sig.S %s", aux.S) - } - sig.S = s - - x, ok := new(big.Int).SetString(aux.F.X, 10) - if !ok { - return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X) - } - y, ok := new(big.Int).SetString(aux.F.Y, 10) - if !ok { - return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y) - } - sig.F = &Point{} - sig.F.X = x - sig.F.Y = y - return nil -} - // Unblind performs the unblinding operation of the blinded signature for the // given message m and the UserSecretData func Unblind(sBlind, m *big.Int, u *UserSecretData) *Signature { diff --git a/blindsecp256k1_test.go b/blindsecp256k1_test.go index 65ac5ff..6175d36 100644 --- a/blindsecp256k1_test.go +++ b/blindsecp256k1_test.go @@ -1,12 +1,10 @@ package blindsecp256k1 import ( - "encoding/json" "math/big" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestFlow(t *testing.T) { @@ -32,47 +30,3 @@ func TestFlow(t *testing.T) { verified := Verify(msg, sig, signerPubK) assert.True(t, verified) } - -func TestMarshalers(t *testing.T) { - // Point - p := G.Mul(big.NewInt(1234)) - b, err := json.Marshal(p) - require.Nil(t, err) - assert.Equal(t, - `{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}`, //nolint:lll - string(b)) - - var p2 *Point - err = json.Unmarshal(b, &p2) - require.Nil(t, err) - assert.Equal(t, p, p2) - - // PublicKey - pk := PublicKey(*p) - b, err = json.Marshal(pk) - require.Nil(t, err) - assert.Equal(t, - `{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}`, //nolint:lll - string(b)) - - var pk2 PublicKey - err = json.Unmarshal(b, &pk2) - require.Nil(t, err) - assert.Equal(t, pk, pk2) - - // Signature - sig := Signature{ - S: big.NewInt(9876), - F: p, - } - b, err = json.Marshal(sig) - require.Nil(t, err) - assert.Equal(t, - `{"s":"9876","f":{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}}`, //nolint:lll - string(b)) - - var sig2 Signature - err = json.Unmarshal(b, &sig2) - require.Nil(t, err) - assert.Equal(t, sig, sig2) -} diff --git a/parsers.go b/parsers.go new file mode 100644 index 0000000..1b1e67a --- /dev/null +++ b/parsers.go @@ -0,0 +1,193 @@ +package blindsecp256k1 + +import ( + "encoding/json" + "fmt" + "math/big" +) + +// swapEndianness swaps the order of the bytes in the slice. +func swapEndianness(b []byte) []byte { + o := make([]byte, len(b)) + for i := range b { + o[len(b)-1-i] = b[i] + } + return o +} + +// MarshalJSON implements the json marshaler for the Point +func (p Point) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + X string `json:"x"` + Y string `json:"y"` + }{ + X: p.X.String(), + Y: p.Y.String(), + }) +} + +// UnmarshalJSON implements the json unmarshaler for the Point +func (p *Point) UnmarshalJSON(b []byte) error { + aux := &struct { + X string `json:"x"` + Y string `json:"y"` + }{} + err := json.Unmarshal(b, &aux) + if err != nil { + return err + } + x, ok := new(big.Int).SetString(aux.X, 10) + if !ok { + return fmt.Errorf("Can not parse Point.X %s", aux.X) + } + y, ok := new(big.Int).SetString(aux.Y, 10) + if !ok { + return fmt.Errorf("Can not parse Point.Y %s", aux.Y) + } + p.X = x + p.Y = y + return nil +} + +// Bytes returns a byte array of length 64, with the X & Y coordinates of the +// Point encoded in little-endian. [ X (32 bytes) | Y (32 bytes)] +func (p *Point) Bytes() []byte { + var b [64]byte + copy(b[:32], swapEndianness(p.X.Bytes())) + copy(b[32:], swapEndianness(p.Y.Bytes())) + return b[:] +} + +// NewPointFromBytes returns a new *Point from a given byte array with length +// 64 which has encoded the point coordinates each one as 32 bytes in +// little-endian. +func NewPointFromBytes(b []byte) (*Point, error) { + if len(b) != 64 { //nolint:gomnd + return nil, + fmt.Errorf("Can not parse bytes to Point, expected byte array of length %d, current %d", + 64, len(b)) + } + p := &Point{} + p.X = new(big.Int).SetBytes(swapEndianness(b[:32])) + p.Y = new(big.Int).SetBytes(swapEndianness(b[32:])) + return p, nil +} + +// MarshalJSON implements the json marshaler for the PublicKey +func (pk PublicKey) MarshalJSON() ([]byte, error) { + return json.Marshal(pk.Point()) +} + +// UnmarshalJSON implements the json unmarshaler for the PublicKey +func (pk *PublicKey) UnmarshalJSON(b []byte) error { + var point *Point + err := json.Unmarshal(b, &point) + if err != nil { + return err + } + pk.X = point.X + pk.Y = point.Y + return nil +} + +// Bytes returns a byte array of length 64, with the X & Y coordinates of the +// PublicKey encoded in little-endian. [ X (32 bytes) | Y (32 bytes)] +func (pk *PublicKey) Bytes() []byte { + return pk.Point().Bytes() +} + +// NewPublicKeyFromBytes returns a new *PublicKey from a given byte array with +// length 64 which has encoded the public key coordinates each one as 32 bytes +// in little-endian. +func NewPublicKeyFromBytes(b []byte) (*PublicKey, error) { + p, err := NewPointFromBytes(b) + if err != nil { + return nil, err + } + pk := PublicKey(*p) + return &pk, nil +} + +// MarshalJSON implements the json marshaler for the Signature +func (sig Signature) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + S string `json:"s"` + F struct { + X string `json:"x"` + Y string `json:"y"` + } `json:"f"` + }{ + S: sig.S.String(), + F: struct { + X string `json:"x"` + Y string `json:"y"` + }{ + X: sig.F.X.String(), + Y: sig.F.Y.String(), + }, + }) +} + +// UnmarshalJSON implements the json unmarshaler for the Signature +func (sig *Signature) UnmarshalJSON(b []byte) error { + aux := &struct { + S string `json:"s"` + F struct { + X string `json:"x"` + Y string `json:"y"` + } `json:"f"` + }{} + err := json.Unmarshal(b, &aux) + if err != nil { + return err + } + + s, ok := new(big.Int).SetString(aux.S, 10) + if !ok { + return fmt.Errorf("Can not parse sig.S %s", aux.S) + } + sig.S = s + + x, ok := new(big.Int).SetString(aux.F.X, 10) + if !ok { + return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X) + } + y, ok := new(big.Int).SetString(aux.F.Y, 10) + if !ok { + return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y) + } + sig.F = &Point{} + sig.F.X = x + sig.F.Y = y + return nil +} + +// Bytes returns a byte array of length 96, with the S, F.X and F.Y coordinates +// of the Signature encoded in little-endian. +// [ S (32 bytes | F.X (32 bytes) | F.Y (32 bytes)] +func (sig *Signature) Bytes() []byte { + var b [96]byte + copy(b[:32], swapEndianness(sig.S.Bytes())) + copy(b[32:96], sig.F.Bytes()) + return b[:] +} + +// NewSignatureFromBytes returns a new *Signature from a given byte array with +// length 96 which has encoded S and the F point coordinates each one as 32 +// bytes in little-endian. +func NewSignatureFromBytes(b []byte) (*Signature, error) { + if len(b) != 96 { //nolint:gomnd + return nil, + fmt.Errorf("Can not parse bytes to Signature, expected byte array of length %d, current %d", + 96, len(b)) + } + s := new(big.Int).SetBytes(swapEndianness(b[:32])) + f, err := NewPointFromBytes(b[32:96]) + if err != nil { + return nil, err + } + return &Signature{ + S: s, + F: f, + }, nil +} diff --git a/parsers_test.go b/parsers_test.go new file mode 100644 index 0000000..41a466a --- /dev/null +++ b/parsers_test.go @@ -0,0 +1,94 @@ +package blindsecp256k1 + +import ( + "encoding/hex" + "encoding/json" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMarshalers(t *testing.T) { + // Point + p := G.Mul(big.NewInt(1234)) + b, err := json.Marshal(p) + require.Nil(t, err) + assert.Equal(t, + `{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}`, //nolint:lll + string(b)) + + var p2 *Point + err = json.Unmarshal(b, &p2) + require.Nil(t, err) + assert.Equal(t, p, p2) + + // PublicKey + pk := PublicKey(*p) + b, err = json.Marshal(pk) + require.Nil(t, err) + assert.Equal(t, + `{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}`, //nolint:lll + string(b)) + + var pk2 PublicKey + err = json.Unmarshal(b, &pk2) + require.Nil(t, err) + assert.Equal(t, pk, pk2) + + // Signature + sig := Signature{ + S: big.NewInt(9876), + F: p, + } + b, err = json.Marshal(sig) + require.Nil(t, err) + assert.Equal(t, + `{"s":"9876","f":{"x":"102884003323827292915668239759940053105992008087520207150474896054185180420338","y":"49384988101491619794462775601349526588349137780292274540231125201115197157452"}}`, //nolint:lll + string(b)) + + var sig2 Signature + err = json.Unmarshal(b, &sig2) + require.Nil(t, err) + assert.Equal(t, sig, sig2) +} + +func TestBytes(t *testing.T) { + // Point + p := &Point{ + X: big.NewInt(3), + Y: big.NewInt(3), + } + b := p.Bytes() + assert.Equal(t, "03000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(b)) //nolint:lll + p2, err := NewPointFromBytes(b) + assert.Nil(t, err) + assert.Equal(t, p, p2) + + p = G.Mul(big.NewInt(1234)) + b = p.Bytes() + assert.Equal(t, "f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll + p2, err = NewPointFromBytes(b) + assert.Nil(t, err) + assert.Equal(t, p, p2) + + // PublicKey + pk := PublicKey(*p) + b = pk.Bytes() + assert.Equal(t, "f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll + pk2, err := NewPublicKeyFromBytes(b) + assert.Nil(t, err) + assert.Equal(t, &pk, pk2) + + // Signature + sig := Signature{ + S: big.NewInt(9876), + F: p, + } + b = sig.Bytes() + assert.Equal(t, "9426000000000000000000000000000000000000000000000000000000000000f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll + sig2, err := NewSignatureFromBytes(b) + assert.Nil(t, err) + assert.Equal(t, &sig, sig2) +}