mirror of
https://github.com/arnaucube/go-blindsecp256k1.git
synced 2026-02-06 19:16:40 +01:00
Add checks to inputs at Blind & BlindSign
This commit is contained in:
@@ -17,13 +17,15 @@ k, signerR := NewRequestParameters()
|
|||||||
|
|
||||||
// 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 := Blind(msg, signerR)
|
msgBlinded, userSecretData, err := Blind(msg, signerR)
|
||||||
|
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 := sk.BlindSign(msgBlinded, k)
|
sBlind, err := sk.BlindSign(msgBlinded, k)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
// user: unblinds the blinded signature
|
// user: unblinds the blinded signature
|
||||||
sig := Unblind(sBlind, msg, userSecretData)
|
sig := Unblind(sBlind, userSecretData)
|
||||||
|
|
||||||
// signature can be verified with signer PublicKey
|
// signature can be verified with signer PublicKey
|
||||||
verified := Verify(msg, sig, signerPubK)
|
verified := Verify(msg, sig, signerPubK)
|
||||||
|
|||||||
@@ -12,12 +12,20 @@ package blindsecp256k1
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TMP
|
||||||
|
// const (
|
||||||
|
// // MinBigIntBytesLen defines the minimum bytes length of the minimum
|
||||||
|
// // accepted value for the checked *big.Int
|
||||||
|
// MinBigIntBytesLen = 20 * 8
|
||||||
|
// )
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// G represents the base point of secp256k1
|
// G represents the base point of secp256k1
|
||||||
G *Point = &Point{
|
G *Point = &Point{
|
||||||
@@ -27,6 +35,8 @@ var (
|
|||||||
|
|
||||||
// N represents the order of G of secp256k1
|
// N represents the order of G of secp256k1
|
||||||
N *big.Int = btcec.S256().N
|
N *big.Int = btcec.S256().N
|
||||||
|
|
||||||
|
zero *big.Int = big.NewInt(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Point represents a point on the secp256k1 curve
|
// Point represents a point on the secp256k1 curve
|
||||||
@@ -53,6 +63,19 @@ func (p *Point) Mul(scalar *big.Int) *Point {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Point) isValid() error {
|
||||||
|
if !btcec.S256().IsOnCurve(p.X, p.Y) {
|
||||||
|
return fmt.Errorf("Point is not on secp256k1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(p.X.Bytes(), zero.Bytes()) &&
|
||||||
|
bytes.Equal(p.Y.Bytes(), zero.Bytes()) {
|
||||||
|
return fmt.Errorf("Point (%s, %s) can not be (0, 0)",
|
||||||
|
p.X.String(), p.Y.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// WIP
|
// WIP
|
||||||
func newRand() *big.Int {
|
func newRand() *big.Int {
|
||||||
var b [32]byte
|
var b [32]byte
|
||||||
@@ -102,27 +125,42 @@ func NewRequestParameters() (*big.Int, *Point) {
|
|||||||
|
|
||||||
// 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 {
|
func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) (*big.Int, error) {
|
||||||
// TODO add pending checks
|
// TODO add pending checks
|
||||||
|
if mBlinded.Cmp(N) != -1 {
|
||||||
|
return nil, fmt.Errorf("mBlinded not inside the finite field")
|
||||||
|
}
|
||||||
|
if bytes.Equal(mBlinded.Bytes(), big.NewInt(0).Bytes()) {
|
||||||
|
return nil, fmt.Errorf("mBlinded can not be 0")
|
||||||
|
}
|
||||||
|
// TMP
|
||||||
|
// if mBlinded.BitLen() < MinBigIntBytesLen {
|
||||||
|
// return nil, fmt.Errorf("mBlinded too small")
|
||||||
|
// }
|
||||||
|
|
||||||
// s' = dm' + k
|
// s' = dm' + k
|
||||||
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
|
return sBlind, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserSecretData contains the secret values from the User (a, b, c) and the
|
// UserSecretData contains the secret values from the User (a, b) and the
|
||||||
// public F
|
// public F
|
||||||
type UserSecretData struct {
|
type UserSecretData struct {
|
||||||
A *big.Int
|
A *big.Int
|
||||||
B *big.Int
|
B *big.Int
|
||||||
|
|
||||||
F *Point // public (in the paper is R)
|
F *Point // public (in the paper is named R)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData, error) {
|
||||||
|
if !btcec.S256().IsOnCurve(signerR.X, signerR.Y) {
|
||||||
|
return nil, nil, fmt.Errorf("signerR point is not on secp256k1")
|
||||||
|
}
|
||||||
|
|
||||||
u := &UserSecretData{}
|
u := &UserSecretData{}
|
||||||
u.A = newRand()
|
u.A = newRand()
|
||||||
u.B = newRand()
|
u.B = newRand()
|
||||||
@@ -133,6 +171,9 @@ func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData) {
|
|||||||
u.F = aR.Add(bG)
|
u.F = aR.Add(bG)
|
||||||
|
|
||||||
// TODO check that F != O (point at infinity)
|
// TODO check that F != O (point at infinity)
|
||||||
|
if err := u.F.isValid(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
rx := new(big.Int).Mod(u.F.X, N)
|
rx := new(big.Int).Mod(u.F.X, N)
|
||||||
|
|
||||||
@@ -144,7 +185,7 @@ func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData) {
|
|||||||
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, N)
|
||||||
|
|
||||||
return mBlinded, u
|
return mBlinded, u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signature contains the signature values S & F
|
// Signature contains the signature values S & F
|
||||||
@@ -170,6 +211,12 @@ 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(m *big.Int, s *Signature, q *PublicKey) bool {
|
||||||
// TODO add pending checks
|
// TODO add pending checks
|
||||||
|
if err := s.F.isValid(); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err := q.Point().isValid(); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
sG := G.Mul(s.S) // sG
|
sG := G.Mul(s.S) // sG
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFlow(t *testing.T) {
|
func TestFlow(t *testing.T) {
|
||||||
@@ -18,10 +19,12 @@ func TestFlow(t *testing.T) {
|
|||||||
|
|
||||||
// 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 := Blind(msg, signerR)
|
msgBlinded, userSecretData, err := Blind(msg, signerR)
|
||||||
|
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 := sk.BlindSign(msgBlinded, k)
|
sBlind, err := sk.BlindSign(msgBlinded, k)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
// user: unblinds the blinded signature
|
// user: unblinds the blinded signature
|
||||||
sig := Unblind(sBlind, userSecretData)
|
sig := Unblind(sBlind, userSecretData)
|
||||||
@@ -34,3 +37,27 @@ func TestFlow(t *testing.T) {
|
|||||||
verified := Verify(msg, sig, signerPubK)
|
verified := Verify(msg, sig, signerPubK)
|
||||||
assert.True(t, verified)
|
assert.True(t, verified)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newBigIntWithBitLen(n int) *big.Int {
|
||||||
|
b := make([]byte, n/8)
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
b[i] = 255
|
||||||
|
}
|
||||||
|
bi := new(big.Int).SetBytes(b[:])
|
||||||
|
return bi
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMinBigIntBytesLen(t *testing.T) {
|
||||||
|
k := big.NewInt(1)
|
||||||
|
sk := PrivateKey(*k)
|
||||||
|
|
||||||
|
mBlinded := newBigIntWithBitLen(MinBigIntBytesLen)
|
||||||
|
require.Equal(t, MinBigIntBytesLen, mBlinded.BitLen())
|
||||||
|
_, err := sk.BlindSign(mBlinded, k)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
mBlinded = new(big.Int).Div(mBlinded, big.NewInt(2))
|
||||||
|
require.Equal(t, MinBigIntBytesLen-1, mBlinded.BitLen())
|
||||||
|
_, err = sk.BlindSign(mBlinded, k)
|
||||||
|
assert.Equal(t, "mBlinded too small", err.Error())
|
||||||
|
}
|
||||||
|
|||||||
@@ -159,7 +159,10 @@ func blind(this js.Value, values []js.Value) interface{} {
|
|||||||
Y: signerRy,
|
Y: signerRy,
|
||||||
}
|
}
|
||||||
|
|
||||||
mBlinded, user := blindsecp256k1.Blind(m, signerR)
|
mBlinded, user, err := blindsecp256k1.Blind(m, signerR)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
r := make(map[string]interface{})
|
r := make(map[string]interface{})
|
||||||
r["mBlinded"] = mBlinded.String()
|
r["mBlinded"] = mBlinded.String()
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user