mirror of
https://github.com/arnaucube/go-blindsecp256k1.git
synced 2026-02-07 11:36:42 +01:00
Abstract curve from impl to use elliptic.Curve interface
This commit is contained in:
@@ -11,11 +11,11 @@ package blindsecp256k1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,27 +28,13 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
zero *big.Int = big.NewInt(0)
|
zero *big.Int = big.NewInt(0)
|
||||||
|
|
||||||
// B (from y^2 = x^3 + B)
|
|
||||||
B *big.Int = btcec.S256().B
|
|
||||||
|
|
||||||
// P represents the secp256k1 finite field
|
|
||||||
P *big.Int = btcec.S256().P
|
|
||||||
|
|
||||||
// Q = (P+1)/4
|
|
||||||
Q = new(big.Int).Div(new(big.Int).Add(P,
|
|
||||||
big.NewInt(1)), big.NewInt(4)) // nolint:gomnd
|
|
||||||
|
|
||||||
// G represents the base point of secp256k1
|
|
||||||
G *Point = &Point{
|
|
||||||
X: btcec.S256().Gx,
|
|
||||||
Y: btcec.S256().Gy,
|
|
||||||
}
|
|
||||||
|
|
||||||
// N represents the order of G of secp256k1
|
|
||||||
N *big.Int = btcec.S256().N
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Curve is a curve wrapper that works with Point structs
|
||||||
|
type Curve struct {
|
||||||
|
c elliptic.Curve
|
||||||
|
}
|
||||||
|
|
||||||
// Point represents a point on the secp256k1 curve
|
// Point represents a point on the secp256k1 curve
|
||||||
type Point struct {
|
type Point struct {
|
||||||
X *big.Int
|
X *big.Int
|
||||||
@@ -56,8 +42,8 @@ type Point struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add performs the Point addition
|
// Add performs the Point addition
|
||||||
func (p *Point) Add(q *Point) *Point {
|
func (c Curve) Add(p, q *Point) *Point {
|
||||||
x, y := btcec.S256().Add(p.X, p.Y, q.X, q.Y)
|
x, y := c.c.Add(p.X, p.Y, q.X, q.Y)
|
||||||
return &Point{
|
return &Point{
|
||||||
X: x,
|
X: x,
|
||||||
Y: y,
|
Y: y,
|
||||||
@@ -65,17 +51,17 @@ func (p *Point) Add(q *Point) *Point {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mul performs the Point scalar multiplication
|
// Mul performs the Point scalar multiplication
|
||||||
func (p *Point) Mul(scalar *big.Int) *Point {
|
func (c Curve) Mul(p *Point, scalar *big.Int) *Point {
|
||||||
x, y := btcec.S256().ScalarMult(p.X, p.Y, scalar.Bytes())
|
x, y := c.c.ScalarMult(p.X, p.Y, scalar.Bytes())
|
||||||
return &Point{
|
return &Point{
|
||||||
X: x,
|
X: x,
|
||||||
Y: y,
|
Y: y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Point) isValid() error {
|
func (c Curve) isValid(p *Point) error {
|
||||||
if !btcec.S256().IsOnCurve(p.X, p.Y) {
|
if !c.c.IsOnCurve(p.X, p.Y) {
|
||||||
return fmt.Errorf("Point is not on secp256k1")
|
return fmt.Errorf("Point is not on curve %s", c.c.Params().Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(p.X.Bytes(), zero.Bytes()) &&
|
if bytes.Equal(p.X.Bytes(), zero.Bytes()) &&
|
||||||
@@ -105,7 +91,7 @@ func isOdd(b *big.Int) bool {
|
|||||||
|
|
||||||
// DecompressPoint unpacks a Point from the given byte array of 33 bytes
|
// DecompressPoint unpacks a Point from the given byte array of 33 bytes
|
||||||
// https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294
|
// https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294
|
||||||
func DecompressPoint(b [33]byte) (*Point, error) {
|
func DecompressPoint(curv elliptic.Curve, b [33]byte) (*Point, error) {
|
||||||
x := new(big.Int).SetBytes(b[:32])
|
x := new(big.Int).SetBytes(b[:32])
|
||||||
var odd bool
|
var odd bool
|
||||||
if b[32] == byte(1) {
|
if b[32] == byte(1) {
|
||||||
@@ -113,6 +99,9 @@ func DecompressPoint(b [33]byte) (*Point, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// secp256k1: y2 = x3+ ax2 + b (where A==0, B==7)
|
// secp256k1: y2 = x3+ ax2 + b (where A==0, B==7)
|
||||||
|
params := curv.Params()
|
||||||
|
B := params.B
|
||||||
|
P := params.P
|
||||||
|
|
||||||
// compute x^3 + B mod p
|
// compute x^3 + B mod p
|
||||||
x3 := new(big.Int).Mul(x, x)
|
x3 := new(big.Int).Mul(x, x)
|
||||||
@@ -147,14 +136,14 @@ func DecompressPoint(b [33]byte) (*Point, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WIP
|
// WIP
|
||||||
func newRand() *big.Int {
|
func newRand(curv elliptic.Curve) *big.Int {
|
||||||
var b [32]byte
|
var b [32]byte
|
||||||
_, err := rand.Read(b[:])
|
_, err := rand.Read(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
bi := new(big.Int).SetBytes(b[:])
|
bi := new(big.Int).SetBytes(b[:])
|
||||||
return new(big.Int).Mod(bi, N)
|
return new(big.Int).Mod(bi, curv.Params().N)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivateKey represents the signer's private key
|
// PrivateKey represents the signer's private key
|
||||||
@@ -164,8 +153,8 @@ type PrivateKey big.Int
|
|||||||
type PublicKey Point
|
type PublicKey Point
|
||||||
|
|
||||||
// NewPrivateKey returns a new random private key
|
// NewPrivateKey returns a new random private key
|
||||||
func NewPrivateKey() *PrivateKey {
|
func NewPrivateKey(curv elliptic.Curve) *PrivateKey {
|
||||||
k := newRand()
|
k := newRand(curv)
|
||||||
sk := PrivateKey(*k)
|
sk := PrivateKey(*k)
|
||||||
return &sk
|
return &sk
|
||||||
}
|
}
|
||||||
@@ -176,9 +165,16 @@ func (sk *PrivateKey) BigInt() *big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Public returns the PublicKey from the PrivateKey
|
// Public returns the PublicKey from the PrivateKey
|
||||||
func (sk *PrivateKey) Public() *PublicKey {
|
func (sk *PrivateKey) Public(curv elliptic.Curve) *PublicKey {
|
||||||
Q := G.Mul(sk.BigInt())
|
// TODO change impl to use directly X, Y instead
|
||||||
pk := PublicKey(*Q)
|
// of Point wrapper. In order to have the impl more close to go interface
|
||||||
|
c := Curve{curv}
|
||||||
|
G := &Point{
|
||||||
|
X: c.c.Params().Gx,
|
||||||
|
Y: c.c.Params().Gy,
|
||||||
|
}
|
||||||
|
q := c.Mul(G, sk.BigInt())
|
||||||
|
pk := PublicKey{X: q.X, Y: q.Y}
|
||||||
return &pk
|
return &pk
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,16 +184,24 @@ func (pk *PublicKey) Point() *Point {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRequestParameters returns a new random k (secret) & R (public) parameters
|
// NewRequestParameters returns a new random k (secret) & R (public) parameters
|
||||||
func NewRequestParameters() (*big.Int, *Point) {
|
func NewRequestParameters(curv elliptic.Curve) (*big.Int, *Point) {
|
||||||
k := newRand()
|
k := newRand(curv)
|
||||||
return k, G.Mul(k) // R = kG
|
G := &Point{
|
||||||
|
X: curv.Params().Gx,
|
||||||
|
Y: curv.Params().Gy,
|
||||||
|
}
|
||||||
|
// R = kG
|
||||||
|
r := Curve{curv}.Mul(G, k)
|
||||||
|
return k, r
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlindSign performs the blind signature on the given mBlinded using the
|
// BlindSign performs the blind signature on the given mBlinded using the
|
||||||
// PrivateKey and the secret k values
|
// PrivateKey and the secret k values
|
||||||
func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) (*big.Int, error) {
|
func (sk *PrivateKey) BlindSign(curv elliptic.Curve, mBlinded *big.Int, k *big.Int) (*big.Int, error) {
|
||||||
|
c := Curve{curv}
|
||||||
|
n := c.c.Params().N
|
||||||
// TODO add pending checks
|
// TODO add pending checks
|
||||||
if mBlinded.Cmp(N) != -1 {
|
if mBlinded.Cmp(n) != -1 {
|
||||||
return nil, fmt.Errorf("mBlinded not inside the finite field")
|
return nil, fmt.Errorf("mBlinded not inside the finite field")
|
||||||
}
|
}
|
||||||
if bytes.Equal(mBlinded.Bytes(), big.NewInt(0).Bytes()) {
|
if bytes.Equal(mBlinded.Bytes(), big.NewInt(0).Bytes()) {
|
||||||
@@ -212,7 +216,7 @@ func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) (*big.Int, error)
|
|||||||
sBlind := new(big.Int).Add(
|
sBlind := new(big.Int).Add(
|
||||||
new(big.Int).Mul(sk.BigInt(), mBlinded),
|
new(big.Int).Mul(sk.BigInt(), mBlinded),
|
||||||
k)
|
k)
|
||||||
sBlind = new(big.Int).Mod(sBlind, N)
|
sBlind = new(big.Int).Mod(sBlind, n)
|
||||||
return sBlind, nil
|
return sBlind, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,34 +230,43 @@ type UserSecretData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Blind performs the blinding operation on m using signerR parameter
|
// Blind performs the blinding operation on m using signerR parameter
|
||||||
func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData, error) {
|
func Blind(curv elliptic.Curve, m *big.Int, signerR *Point) (*big.Int, *UserSecretData, error) {
|
||||||
if err := signerR.isValid(); err != nil {
|
c := Curve{curv}
|
||||||
|
if err := c.isValid(signerR); err != nil {
|
||||||
return nil, nil, fmt.Errorf("signerR %s", err)
|
return nil, nil, fmt.Errorf("signerR %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO check if curv==signerR.curv
|
||||||
|
// TODO (once the Point abstraction is removed) check that signerR is
|
||||||
|
// in the curve
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Params().Gx,
|
||||||
|
Y: curv.Params().Gy,
|
||||||
|
}
|
||||||
|
|
||||||
u := &UserSecretData{}
|
u := &UserSecretData{}
|
||||||
u.A = newRand()
|
u.A = newRand(curv)
|
||||||
u.B = newRand()
|
u.B = newRand(curv)
|
||||||
|
|
||||||
// (R) F = aR' + bG
|
// (R) F = aR' + bG
|
||||||
aR := signerR.Mul(u.A)
|
aR := c.Mul(signerR, u.A)
|
||||||
bG := G.Mul(u.B)
|
bG := c.Mul(G, u.B)
|
||||||
u.F = aR.Add(bG)
|
u.F = c.Add(aR, bG)
|
||||||
|
|
||||||
// TODO check that F != O (point at infinity)
|
// TODO check that F != O (point at infinity)
|
||||||
if err := u.F.isValid(); err != nil {
|
if err := c.isValid(u.F); err != nil {
|
||||||
return nil, nil, fmt.Errorf("u.F %s", err)
|
return nil, nil, fmt.Errorf("u.F %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rx := new(big.Int).Mod(u.F.X, N)
|
rx := new(big.Int).Mod(u.F.X, curv.Params().N)
|
||||||
|
|
||||||
// m' = a^-1 rx h(m)
|
// m' = a^-1 rx h(m)
|
||||||
ainv := new(big.Int).ModInverse(u.A, N)
|
ainv := new(big.Int).ModInverse(u.A, curv.Params().N)
|
||||||
ainvrx := new(big.Int).Mul(ainv, rx)
|
ainvrx := new(big.Int).Mul(ainv, rx)
|
||||||
hBytes := crypto.Keccak256(m.Bytes())
|
hBytes := crypto.Keccak256(m.Bytes())
|
||||||
h := new(big.Int).SetBytes(hBytes)
|
h := new(big.Int).SetBytes(hBytes)
|
||||||
mBlinded := new(big.Int).Mul(ainvrx, h)
|
mBlinded := new(big.Int).Mul(ainvrx, h)
|
||||||
mBlinded = new(big.Int).Mod(mBlinded, N)
|
mBlinded = new(big.Int).Mod(mBlinded, curv.Params().N)
|
||||||
|
|
||||||
return mBlinded, u, nil
|
return mBlinded, u, nil
|
||||||
}
|
}
|
||||||
@@ -276,11 +289,11 @@ func (s *Signature) Compress() [65]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecompressSignature unpacks a Signature from the given byte array of 65 bytes
|
// DecompressSignature unpacks a Signature from the given byte array of 65 bytes
|
||||||
func DecompressSignature(b [65]byte) (*Signature, error) {
|
func DecompressSignature(curve elliptic.Curve, b [65]byte) (*Signature, error) {
|
||||||
s := new(big.Int).SetBytes(swapEndianness(b[:32]))
|
s := new(big.Int).SetBytes(swapEndianness(b[:32]))
|
||||||
var fBytes [33]byte
|
var fBytes [33]byte
|
||||||
copy(fBytes[:], b[32:])
|
copy(fBytes[:], b[32:])
|
||||||
f, err := DecompressPoint(fBytes)
|
f, err := DecompressPoint(curve, fBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -290,11 +303,11 @@ func DecompressSignature(b [65]byte) (*Signature, error) {
|
|||||||
|
|
||||||
// Unblind performs the unblinding operation of the blinded signature for the
|
// Unblind performs the unblinding operation of the blinded signature for the
|
||||||
// given the UserSecretData
|
// given the UserSecretData
|
||||||
func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
|
func Unblind(curv elliptic.Curve, sBlind *big.Int, u *UserSecretData) *Signature {
|
||||||
// s = a s' + b
|
// s = a s' + b
|
||||||
as := new(big.Int).Mul(u.A, sBlind)
|
as := new(big.Int).Mul(u.A, sBlind)
|
||||||
s := new(big.Int).Add(as, u.B)
|
s := new(big.Int).Add(as, u.B)
|
||||||
s = new(big.Int).Mod(s, N)
|
s = new(big.Int).Mod(s, curv.Params().N)
|
||||||
|
|
||||||
return &Signature{
|
return &Signature{
|
||||||
S: s,
|
S: s,
|
||||||
@@ -303,26 +316,31 @@ func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify checks the signature of the message m for the given PublicKey
|
// Verify checks the signature of the message m for the given PublicKey
|
||||||
func Verify(m *big.Int, s *Signature, q *PublicKey) bool {
|
func Verify(curv elliptic.Curve, m *big.Int, s *Signature, q *PublicKey) bool {
|
||||||
// TODO add pending checks
|
// TODO add pending checks
|
||||||
if err := s.F.isValid(); err != nil {
|
c := Curve{curv}
|
||||||
|
if err := c.isValid(s.F); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if err := q.Point().isValid(); err != nil {
|
if err := c.isValid(q.Point()); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sG := G.Mul(s.S) // sG
|
G := &Point{
|
||||||
|
X: curv.Params().Gx,
|
||||||
|
Y: curv.Params().Gy,
|
||||||
|
}
|
||||||
|
sG := c.Mul(G, s.S) // sG
|
||||||
|
|
||||||
hBytes := crypto.Keccak256(m.Bytes())
|
hBytes := crypto.Keccak256(m.Bytes())
|
||||||
h := new(big.Int).SetBytes(hBytes)
|
h := new(big.Int).SetBytes(hBytes)
|
||||||
|
|
||||||
rx := new(big.Int).Mod(s.F.X, N)
|
rx := new(big.Int).Mod(s.F.X, curv.Params().N)
|
||||||
rxh := new(big.Int).Mul(rx, h)
|
rxh := new(big.Int).Mul(rx, h)
|
||||||
// rxhG := G.Mul(rxh) // originally the paper uses G
|
// rxhG := G.Mul(rxh) // originally the paper uses G
|
||||||
rxhG := q.Point().Mul(rxh)
|
rxhG := c.Mul(q.Point(), rxh)
|
||||||
|
|
||||||
right := s.F.Add(rxhG)
|
right := c.Add(s.F, rxhG)
|
||||||
|
|
||||||
// check sG == R + rx h(m) Q (where R in this code is F)
|
// check sG == R + rx h(m) Q (where R in this code is F)
|
||||||
if bytes.Equal(sG.X.Bytes(), right.X.Bytes()) &&
|
if bytes.Equal(sG.X.Bytes(), right.X.Bytes()) &&
|
||||||
|
|||||||
@@ -5,38 +5,44 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO abstract the test to work with any curve, and be
|
||||||
|
// called from a test that testes all the tests with the
|
||||||
|
// main curves
|
||||||
|
|
||||||
func TestFlow(t *testing.T) {
|
func TestFlow(t *testing.T) {
|
||||||
|
curv := btcec.S256()
|
||||||
// signer: create new signer key pair
|
// signer: create new signer key pair
|
||||||
sk := NewPrivateKey()
|
sk := NewPrivateKey(curv)
|
||||||
signerPubK := sk.Public()
|
signerPubK := sk.Public(curv)
|
||||||
|
|
||||||
// signer: when user requests new R parameter to blind a new msg,
|
// signer: when user requests new R parameter to blind a new msg,
|
||||||
// create new signerR (public) with its secret k
|
// create new signerR (public) with its secret k
|
||||||
k, signerR := NewRequestParameters()
|
k, signerR := NewRequestParameters(curv)
|
||||||
|
|
||||||
// user: blinds the msg using signer's R
|
// user: blinds the msg using signer's R
|
||||||
msg := new(big.Int).SetBytes([]byte("test"))
|
msg := new(big.Int).SetBytes([]byte("test"))
|
||||||
msgBlinded, userSecretData, err := Blind(msg, signerR)
|
msgBlinded, userSecretData, err := Blind(curv, msg, signerR)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// signer: signs the blinded message using its private key & secret k
|
// signer: signs the blinded message using its private key & secret k
|
||||||
sBlind, err := sk.BlindSign(msgBlinded, k)
|
sBlind, err := sk.BlindSign(curv, msgBlinded, k)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// user: unblinds the blinded signature
|
// user: unblinds the blinded signature
|
||||||
sig := Unblind(sBlind, userSecretData)
|
sig := Unblind(curv, sBlind, userSecretData)
|
||||||
sigB := sig.Bytes()
|
sigB := sig.Bytes()
|
||||||
sig2, err := NewSignatureFromBytes(sigB)
|
sig2, err := NewSignatureFromBytes(sigB)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, sig, sig2)
|
assert.Equal(t, sig, sig2)
|
||||||
|
|
||||||
// signature can be verified with signer PublicKey
|
// signature can be verified with signer PublicKey
|
||||||
verified := Verify(msg, sig, signerPubK)
|
verified := Verify(curv, msg, sig, signerPubK)
|
||||||
assert.True(t, verified)
|
assert.True(t, verified)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,27 +93,44 @@ func TestHashMOddBytes(t *testing.T) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
func TestPointCompressDecompress(t *testing.T) {
|
func TestPointCompressDecompress(t *testing.T) {
|
||||||
p := G
|
curv := btcec.S256()
|
||||||
|
c := Curve{curv}
|
||||||
|
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Gx,
|
||||||
|
Y: curv.Gy,
|
||||||
|
}
|
||||||
|
p := &Point{
|
||||||
|
X: curv.Gx,
|
||||||
|
Y: curv.Gy,
|
||||||
|
}
|
||||||
b := p.Compress()
|
b := p.Compress()
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||||
hex.EncodeToString(b[:]))
|
hex.EncodeToString(b[:]))
|
||||||
p2, err := DecompressPoint(b)
|
p2, err := DecompressPoint(curv, b)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, p, p2)
|
assert.Equal(t, p, p2)
|
||||||
|
|
||||||
for i := 2; i < 1000; i++ {
|
for i := 2; i < 1000; i++ {
|
||||||
p := G.Mul(big.NewInt(int64(i)))
|
p := c.Mul(G, big.NewInt(int64(i)))
|
||||||
b := p.Compress()
|
b := p.Compress()
|
||||||
assert.Equal(t, 33, len(b))
|
assert.Equal(t, 33, len(b))
|
||||||
|
|
||||||
p2, err := DecompressPoint(b)
|
p2, err := DecompressPoint(curv, b)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, p, p2)
|
assert.Equal(t, p, p2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSignatureCompressDecompress(t *testing.T) {
|
func TestSignatureCompressDecompress(t *testing.T) {
|
||||||
|
curv := btcec.S256()
|
||||||
|
c := Curve{curv}
|
||||||
|
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Gx,
|
||||||
|
Y: curv.Gy,
|
||||||
|
}
|
||||||
f := G
|
f := G
|
||||||
sig := &Signature{
|
sig := &Signature{
|
||||||
S: big.NewInt(1),
|
S: big.NewInt(1),
|
||||||
@@ -118,11 +141,15 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
|||||||
"01000000000000000000000000000000000000000000000000000000000000007"+
|
"01000000000000000000000000000000000000000000000000000000000000007"+
|
||||||
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||||
hex.EncodeToString(b[:]))
|
hex.EncodeToString(b[:]))
|
||||||
sig2, err := DecompressSignature(b)
|
sig2, err := DecompressSignature(curv, b)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, sig, sig2)
|
assert.Equal(t, sig, sig2)
|
||||||
|
|
||||||
f = G
|
f = G
|
||||||
|
P := curv.Params().P
|
||||||
|
// Q = (P+1)/4
|
||||||
|
Q := new(big.Int).Div(new(big.Int).Add(P,
|
||||||
|
big.NewInt(1)), big.NewInt(4)) // nolint:gomnd
|
||||||
sig = &Signature{
|
sig = &Signature{
|
||||||
S: Q,
|
S: Q,
|
||||||
F: f,
|
F: f,
|
||||||
@@ -132,13 +159,13 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
|||||||
"0cffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff3f7"+
|
"0cffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff3f7"+
|
||||||
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||||
hex.EncodeToString(b[:]))
|
hex.EncodeToString(b[:]))
|
||||||
sig2, err = DecompressSignature(b)
|
sig2, err = DecompressSignature(curv, b)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, sig, sig2)
|
require.Equal(t, sig, sig2)
|
||||||
|
|
||||||
for i := 2; i < 10; i++ {
|
for i := 2; i < 10; i++ {
|
||||||
s := new(big.Int).Mod(new(big.Int).Mul(Q, big.NewInt(int64(i))), P)
|
s := new(big.Int).Mod(new(big.Int).Mul(Q, big.NewInt(int64(i))), P)
|
||||||
f := G.Mul(big.NewInt(int64(i)))
|
f := c.Mul(G, big.NewInt(int64(i)))
|
||||||
sig := &Signature{
|
sig := &Signature{
|
||||||
S: s,
|
S: s,
|
||||||
F: f,
|
F: f,
|
||||||
@@ -146,19 +173,26 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
|||||||
b := sig.Compress()
|
b := sig.Compress()
|
||||||
assert.Equal(t, 65, len(b))
|
assert.Equal(t, 65, len(b))
|
||||||
|
|
||||||
sig2, err := DecompressSignature(b)
|
sig2, err := DecompressSignature(curv, b)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, sig, sig2)
|
assert.Equal(t, sig, sig2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCompressDecompress(b *testing.B) {
|
func BenchmarkCompressDecompress(b *testing.B) {
|
||||||
|
curv := btcec.S256()
|
||||||
|
c := Curve{curv}
|
||||||
|
|
||||||
const n = 256
|
const n = 256
|
||||||
var points [n]*Point
|
var points [n]*Point
|
||||||
var compPoints [n][33]byte
|
var compPoints [n][33]byte
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Gx,
|
||||||
|
Y: curv.Gy,
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
points[i] = G.Mul(big.NewInt(int64(i)))
|
points[i] = c.Mul(G, big.NewInt(int64(i)))
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
compPoints[i] = points[i].Compress()
|
compPoints[i] = points[i].Compress()
|
||||||
@@ -171,7 +205,7 @@ func BenchmarkCompressDecompress(b *testing.B) {
|
|||||||
})
|
})
|
||||||
b.Run("DecompressPoint", func(b *testing.B) {
|
b.Run("DecompressPoint", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, _ = DecompressPoint(compPoints[i%n])
|
_, _ = DecompressPoint(curv, compPoints[i%n])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,21 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMarshalers(t *testing.T) {
|
func TestMarshalers(t *testing.T) {
|
||||||
|
curv := btcec.S256()
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Params().Gx,
|
||||||
|
Y: curv.Params().Gy,
|
||||||
|
}
|
||||||
|
|
||||||
// Point
|
// Point
|
||||||
p := G.Mul(big.NewInt(1234))
|
p := Curve{curv}.Mul(G, big.NewInt(1234))
|
||||||
b, err := json.Marshal(p)
|
b, err := json.Marshal(p)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
@@ -56,6 +63,12 @@ func TestMarshalers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBytes(t *testing.T) {
|
func TestBytes(t *testing.T) {
|
||||||
|
curv := btcec.S256()
|
||||||
|
G := &Point{
|
||||||
|
X: curv.Params().Gx,
|
||||||
|
Y: curv.Params().Gy,
|
||||||
|
}
|
||||||
|
|
||||||
// Point
|
// Point
|
||||||
p := &Point{
|
p := &Point{
|
||||||
X: big.NewInt(3),
|
X: big.NewInt(3),
|
||||||
@@ -67,7 +80,7 @@ func TestBytes(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, p, p2)
|
assert.Equal(t, p, p2)
|
||||||
|
|
||||||
p = G.Mul(big.NewInt(1234))
|
p = Curve{curv}.Mul(G, big.NewInt(1234))
|
||||||
b = p.Bytes()
|
b = p.Bytes()
|
||||||
assert.Equal(t, "f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll
|
assert.Equal(t, "f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll
|
||||||
p2, err = NewPointFromBytes(b)
|
p2, err = NewPointFromBytes(b)
|
||||||
@@ -112,6 +125,8 @@ func TestBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestImportECDSApubKey(t *testing.T) {
|
func TestImportECDSApubKey(t *testing.T) {
|
||||||
|
curv := btcec.S256()
|
||||||
|
|
||||||
// Generate an ECDSA key
|
// Generate an ECDSA key
|
||||||
k, err := crypto.GenerateKey()
|
k, err := crypto.GenerateKey()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -121,5 +136,5 @@ func TestImportECDSApubKey(t *testing.T) {
|
|||||||
// Set the ECDSA Private key point as a blindsecp256k1 PrivateKey type
|
// Set the ECDSA Private key point as a blindsecp256k1 PrivateKey type
|
||||||
bk := PrivateKey(*k.D)
|
bk := PrivateKey(*k.D)
|
||||||
// Compare both public keys
|
// Compare both public keys
|
||||||
assert.Equal(t, bk.Public().Bytes(), pk.Bytes())
|
assert.Equal(t, bk.Public(curv).Bytes(), pk.Bytes())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user