Browse Source

Add checks to inputs at Blind & BlindSign

feature/add-checks
arnaucube 3 years ago
parent
commit
2b8e15988a
5 changed files with 91 additions and 12 deletions
  1. +5
    -3
      README.md
  2. +53
    -6
      blindsecp256k1.go
  3. +29
    -2
      blindsecp256k1_test.go
  4. +4
    -1
      wasm/blindsecp256k1-wasm.go
  5. BIN
      wasm/webtest/blindsecp256k1.wasm

+ 5
- 3
README.md

@ -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)

+ 53
- 6
blindsecp256k1.go

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

+ 29
- 2
blindsecp256k1_test.go

@ -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())
}

+ 4
- 1
wasm/blindsecp256k1-wasm.go

@ -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()

BIN
wasm/webtest/blindsecp256k1.wasm


Loading…
Cancel
Save