mirror of
https://github.com/arnaucube/go-blindsecp256k1.git
synced 2026-02-06 19:16:40 +01:00
Abstract curve from impl to use elliptic.Curve interface
This commit is contained in:
@@ -11,11 +11,11 @@ package blindsecp256k1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
@@ -28,27 +28,13 @@ import (
|
||||
|
||||
var (
|
||||
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
|
||||
type Point struct {
|
||||
X *big.Int
|
||||
@@ -56,8 +42,8 @@ type Point struct {
|
||||
}
|
||||
|
||||
// Add performs the Point addition
|
||||
func (p *Point) Add(q *Point) *Point {
|
||||
x, y := btcec.S256().Add(p.X, p.Y, q.X, q.Y)
|
||||
func (c Curve) Add(p, q *Point) *Point {
|
||||
x, y := c.c.Add(p.X, p.Y, q.X, q.Y)
|
||||
return &Point{
|
||||
X: x,
|
||||
Y: y,
|
||||
@@ -65,17 +51,17 @@ func (p *Point) Add(q *Point) *Point {
|
||||
}
|
||||
|
||||
// Mul performs the Point scalar multiplication
|
||||
func (p *Point) Mul(scalar *big.Int) *Point {
|
||||
x, y := btcec.S256().ScalarMult(p.X, p.Y, scalar.Bytes())
|
||||
func (c Curve) Mul(p *Point, scalar *big.Int) *Point {
|
||||
x, y := c.c.ScalarMult(p.X, p.Y, scalar.Bytes())
|
||||
return &Point{
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Point) isValid() error {
|
||||
if !btcec.S256().IsOnCurve(p.X, p.Y) {
|
||||
return fmt.Errorf("Point is not on secp256k1")
|
||||
func (c Curve) isValid(p *Point) error {
|
||||
if !c.c.IsOnCurve(p.X, p.Y) {
|
||||
return fmt.Errorf("Point is not on curve %s", c.c.Params().Name)
|
||||
}
|
||||
|
||||
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
|
||||
// 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])
|
||||
var odd bool
|
||||
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)
|
||||
params := curv.Params()
|
||||
B := params.B
|
||||
P := params.P
|
||||
|
||||
// compute x^3 + B mod p
|
||||
x3 := new(big.Int).Mul(x, x)
|
||||
@@ -147,14 +136,14 @@ func DecompressPoint(b [33]byte) (*Point, error) {
|
||||
}
|
||||
|
||||
// WIP
|
||||
func newRand() *big.Int {
|
||||
func newRand(curv elliptic.Curve) *big.Int {
|
||||
var b [32]byte
|
||||
_, err := rand.Read(b[:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
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
|
||||
@@ -164,8 +153,8 @@ type PrivateKey big.Int
|
||||
type PublicKey Point
|
||||
|
||||
// NewPrivateKey returns a new random private key
|
||||
func NewPrivateKey() *PrivateKey {
|
||||
k := newRand()
|
||||
func NewPrivateKey(curv elliptic.Curve) *PrivateKey {
|
||||
k := newRand(curv)
|
||||
sk := PrivateKey(*k)
|
||||
return &sk
|
||||
}
|
||||
@@ -176,9 +165,16 @@ func (sk *PrivateKey) BigInt() *big.Int {
|
||||
}
|
||||
|
||||
// Public returns the PublicKey from the PrivateKey
|
||||
func (sk *PrivateKey) Public() *PublicKey {
|
||||
Q := G.Mul(sk.BigInt())
|
||||
pk := PublicKey(*Q)
|
||||
func (sk *PrivateKey) Public(curv elliptic.Curve) *PublicKey {
|
||||
// TODO change impl to use directly X, Y instead
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -188,16 +184,24 @@ func (pk *PublicKey) Point() *Point {
|
||||
}
|
||||
|
||||
// NewRequestParameters returns a new random k (secret) & R (public) parameters
|
||||
func NewRequestParameters() (*big.Int, *Point) {
|
||||
k := newRand()
|
||||
return k, G.Mul(k) // R = kG
|
||||
func NewRequestParameters(curv elliptic.Curve) (*big.Int, *Point) {
|
||||
k := newRand(curv)
|
||||
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
|
||||
// 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
|
||||
if mBlinded.Cmp(N) != -1 {
|
||||
if mBlinded.Cmp(n) != -1 {
|
||||
return nil, fmt.Errorf("mBlinded not inside the finite field")
|
||||
}
|
||||
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(
|
||||
new(big.Int).Mul(sk.BigInt(), mBlinded),
|
||||
k)
|
||||
sBlind = new(big.Int).Mod(sBlind, N)
|
||||
sBlind = new(big.Int).Mod(sBlind, n)
|
||||
return sBlind, nil
|
||||
}
|
||||
|
||||
@@ -226,34 +230,43 @@ type UserSecretData struct {
|
||||
}
|
||||
|
||||
// Blind performs the blinding operation on m using signerR parameter
|
||||
func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData, error) {
|
||||
if err := signerR.isValid(); err != nil {
|
||||
func Blind(curv elliptic.Curve, m *big.Int, signerR *Point) (*big.Int, *UserSecretData, error) {
|
||||
c := Curve{curv}
|
||||
if err := c.isValid(signerR); err != nil {
|
||||
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.A = newRand()
|
||||
u.B = newRand()
|
||||
u.A = newRand(curv)
|
||||
u.B = newRand(curv)
|
||||
|
||||
// (R) F = aR' + bG
|
||||
aR := signerR.Mul(u.A)
|
||||
bG := G.Mul(u.B)
|
||||
u.F = aR.Add(bG)
|
||||
aR := c.Mul(signerR, u.A)
|
||||
bG := c.Mul(G, u.B)
|
||||
u.F = c.Add(aR, bG)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
hBytes := crypto.Keccak256(m.Bytes())
|
||||
h := new(big.Int).SetBytes(hBytes)
|
||||
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
|
||||
}
|
||||
@@ -276,11 +289,11 @@ func (s *Signature) Compress() [65]byte {
|
||||
}
|
||||
|
||||
// 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]))
|
||||
var fBytes [33]byte
|
||||
copy(fBytes[:], b[32:])
|
||||
f, err := DecompressPoint(fBytes)
|
||||
f, err := DecompressPoint(curve, fBytes)
|
||||
if err != nil {
|
||||
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
|
||||
// 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
|
||||
as := new(big.Int).Mul(u.A, sBlind)
|
||||
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{
|
||||
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
|
||||
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
|
||||
if err := s.F.isValid(); err != nil {
|
||||
c := Curve{curv}
|
||||
if err := c.isValid(s.F); err != nil {
|
||||
return false
|
||||
}
|
||||
if err := q.Point().isValid(); err != nil {
|
||||
if err := c.isValid(q.Point()); err != nil {
|
||||
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())
|
||||
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)
|
||||
// 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)
|
||||
if bytes.Equal(sG.X.Bytes(), right.X.Bytes()) &&
|
||||
|
||||
@@ -5,38 +5,44 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"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) {
|
||||
curv := btcec.S256()
|
||||
// signer: create new signer key pair
|
||||
sk := NewPrivateKey()
|
||||
signerPubK := sk.Public()
|
||||
sk := NewPrivateKey(curv)
|
||||
signerPubK := sk.Public(curv)
|
||||
|
||||
// signer: when user requests new R parameter to blind a new msg,
|
||||
// create new signerR (public) with its secret k
|
||||
k, signerR := NewRequestParameters()
|
||||
k, signerR := NewRequestParameters(curv)
|
||||
|
||||
// user: blinds the msg using signer's R
|
||||
msg := new(big.Int).SetBytes([]byte("test"))
|
||||
msgBlinded, userSecretData, err := Blind(msg, signerR)
|
||||
msgBlinded, userSecretData, err := Blind(curv, msg, signerR)
|
||||
require.Nil(t, err)
|
||||
|
||||
// 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)
|
||||
|
||||
// user: unblinds the blinded signature
|
||||
sig := Unblind(sBlind, userSecretData)
|
||||
sig := Unblind(curv, sBlind, userSecretData)
|
||||
sigB := sig.Bytes()
|
||||
sig2, err := NewSignatureFromBytes(sigB)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, sig, sig2)
|
||||
|
||||
// signature can be verified with signer PublicKey
|
||||
verified := Verify(msg, sig, signerPubK)
|
||||
verified := Verify(curv, msg, sig, signerPubK)
|
||||
assert.True(t, verified)
|
||||
}
|
||||
|
||||
@@ -87,27 +93,44 @@ func TestHashMOddBytes(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()
|
||||
assert.Equal(t,
|
||||
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||
hex.EncodeToString(b[:]))
|
||||
p2, err := DecompressPoint(b)
|
||||
p2, err := DecompressPoint(curv, b)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, p, p2)
|
||||
|
||||
for i := 2; i < 1000; i++ {
|
||||
p := G.Mul(big.NewInt(int64(i)))
|
||||
p := c.Mul(G, big.NewInt(int64(i)))
|
||||
b := p.Compress()
|
||||
assert.Equal(t, 33, len(b))
|
||||
|
||||
p2, err := DecompressPoint(b)
|
||||
p2, err := DecompressPoint(curv, b)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, p, p2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignatureCompressDecompress(t *testing.T) {
|
||||
curv := btcec.S256()
|
||||
c := Curve{curv}
|
||||
|
||||
G := &Point{
|
||||
X: curv.Gx,
|
||||
Y: curv.Gy,
|
||||
}
|
||||
f := G
|
||||
sig := &Signature{
|
||||
S: big.NewInt(1),
|
||||
@@ -118,11 +141,15 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
||||
"01000000000000000000000000000000000000000000000000000000000000007"+
|
||||
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||
hex.EncodeToString(b[:]))
|
||||
sig2, err := DecompressSignature(b)
|
||||
sig2, err := DecompressSignature(curv, b)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, sig, sig2)
|
||||
|
||||
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{
|
||||
S: Q,
|
||||
F: f,
|
||||
@@ -132,13 +159,13 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
||||
"0cffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff3f7"+
|
||||
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||
hex.EncodeToString(b[:]))
|
||||
sig2, err = DecompressSignature(b)
|
||||
sig2, err = DecompressSignature(curv, b)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, sig, sig2)
|
||||
|
||||
for i := 2; i < 10; i++ {
|
||||
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{
|
||||
S: s,
|
||||
F: f,
|
||||
@@ -146,19 +173,26 @@ func TestSignatureCompressDecompress(t *testing.T) {
|
||||
b := sig.Compress()
|
||||
assert.Equal(t, 65, len(b))
|
||||
|
||||
sig2, err := DecompressSignature(b)
|
||||
sig2, err := DecompressSignature(curv, b)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, sig, sig2)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompressDecompress(b *testing.B) {
|
||||
curv := btcec.S256()
|
||||
c := Curve{curv}
|
||||
|
||||
const n = 256
|
||||
var points [n]*Point
|
||||
var compPoints [n][33]byte
|
||||
G := &Point{
|
||||
X: curv.Gx,
|
||||
Y: curv.Gy,
|
||||
}
|
||||
|
||||
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++ {
|
||||
compPoints[i] = points[i].Compress()
|
||||
@@ -171,7 +205,7 @@ func BenchmarkCompressDecompress(b *testing.B) {
|
||||
})
|
||||
b.Run("DecompressPoint", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = DecompressPoint(compPoints[i%n])
|
||||
_, _ = DecompressPoint(curv, compPoints[i%n])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,14 +6,21 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMarshalers(t *testing.T) {
|
||||
curv := btcec.S256()
|
||||
G := &Point{
|
||||
X: curv.Params().Gx,
|
||||
Y: curv.Params().Gy,
|
||||
}
|
||||
|
||||
// Point
|
||||
p := G.Mul(big.NewInt(1234))
|
||||
p := Curve{curv}.Mul(G, big.NewInt(1234))
|
||||
b, err := json.Marshal(p)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t,
|
||||
@@ -56,6 +63,12 @@ func TestMarshalers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBytes(t *testing.T) {
|
||||
curv := btcec.S256()
|
||||
G := &Point{
|
||||
X: curv.Params().Gx,
|
||||
Y: curv.Params().Gy,
|
||||
}
|
||||
|
||||
// Point
|
||||
p := &Point{
|
||||
X: big.NewInt(3),
|
||||
@@ -67,7 +80,7 @@ func TestBytes(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, p, p2)
|
||||
|
||||
p = G.Mul(big.NewInt(1234))
|
||||
p = Curve{curv}.Mul(G, big.NewInt(1234))
|
||||
b = p.Bytes()
|
||||
assert.Equal(t, "f258163f65f65865a79a4279e2ebabb5a57b85501dd4b381d1dc605c434876e34c308bd3f18f062d5cc07f34948ced82f9a76f9c3e65ae64f158412da8e92e6d", hex.EncodeToString(b)) //nolint:lll
|
||||
p2, err = NewPointFromBytes(b)
|
||||
@@ -112,6 +125,8 @@ func TestBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestImportECDSApubKey(t *testing.T) {
|
||||
curv := btcec.S256()
|
||||
|
||||
// Generate an ECDSA key
|
||||
k, err := crypto.GenerateKey()
|
||||
assert.Nil(t, err)
|
||||
@@ -121,5 +136,5 @@ func TestImportECDSApubKey(t *testing.T) {
|
||||
// Set the ECDSA Private key point as a blindsecp256k1 PrivateKey type
|
||||
bk := PrivateKey(*k.D)
|
||||
// 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