Add checks to inputs at Blind & BlindSign
arnaucube root@arnaucube.com
Mon, 08 Feb 2021 23:05:21 +0100
5 files changed,
91 insertions(+),
12 deletions(-)
M
README.md
→
README.md
@@ -17,13 +17,15 @@ k, signerR := NewRequestParameters()
// user: blinds the msg using signer's R 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 -sBlind := sk.BlindSign(msgBlinded, k) +sBlind, err := sk.BlindSign(msgBlinded, k) +require.Nil(t, err) // user: unblinds the blinded signature -sig := Unblind(sBlind, msg, userSecretData) +sig := Unblind(sBlind, userSecretData) // signature can be verified with signer PublicKey verified := Verify(msg, sig, signerPubK)
M
blindsecp256k1.go
→
blindsecp256k1.go
@@ -12,11 +12,19 @@
import ( "bytes" "crypto/rand" + "fmt" "math/big" "github.com/btcsuite/btcd/btcec" "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 ( // G represents the base point of secp256k1@@ -27,6 +35,8 @@ }
// N represents the order of G of secp256k1 N *big.Int = btcec.S256().N + + zero *big.Int = big.NewInt(0) ) // Point represents a point on the secp256k1 curve@@ -53,6 +63,19 @@ Y: y,
} } +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 func newRand() *big.Int { var b [32]byte@@ -102,27 +125,42 @@ }
// 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 { +func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) (*big.Int, error) { // 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 sBlind := new(big.Int).Add( new(big.Int).Mul(sk.BigInt(), mBlinded), k) 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 type UserSecretData struct { A *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 -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.A = newRand() u.B = newRand()@@ -133,6 +171,9 @@ bG := G.Mul(u.B)
u.F = aR.Add(bG) // 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)@@ -144,7 +185,7 @@ h := new(big.Int).SetBytes(hBytes)
mBlinded := new(big.Int).Mul(ainvrx, h) mBlinded = new(big.Int).Mod(mBlinded, N) - return mBlinded, u + return mBlinded, u, nil } // Signature contains the signature values S & F@@ -170,6 +211,12 @@
// Verify checks the signature of the message m for the given PublicKey func Verify(m *big.Int, s *Signature, q *PublicKey) bool { // 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
M
blindsecp256k1_test.go
→
blindsecp256k1_test.go
@@ -5,6 +5,7 @@ "math/big"
"testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFlow(t *testing.T) {@@ -18,10 +19,12 @@ k, signerR := NewRequestParameters()
// user: blinds the msg using signer's R 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 - sBlind := sk.BlindSign(msgBlinded, k) + sBlind, err := sk.BlindSign(msgBlinded, k) + require.Nil(t, err) // user: unblinds the blinded signature sig := Unblind(sBlind, userSecretData)@@ -34,3 +37,27 @@ // signature can be verified with signer PublicKey
verified := Verify(msg, sig, signerPubK) 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()) +// }
M
wasm/blindsecp256k1-wasm.go
→
wasm/blindsecp256k1-wasm.go
@@ -159,7 +159,10 @@ X: signerRx,
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["mBlinded"] = mBlinded.String()