diff --git a/README.md b/README.md index fdf202b..a0e8d05 100644 --- a/README.md +++ b/README.md @@ -7,24 +7,26 @@ Blind signature over [secp256k1](https://en.bitcoin.it/wiki/Secp256k1), based on ## Usage ```go -// message to be signed -msg := new(big.Int).SetBytes([]byte("test")) +// signer: create new signer key pair +sk := NewPrivateKey() +signerPubK := sk.Public() -// create new signer -signerPrivateData := blindsecp256k1.NewSigner() -signerPublicData := signerPrivateData.PublicData() +// signer: when user requests new R parameter to blind a new msg, +// create new signerR (public) with its secret k +k, signerR := NewRequestParameters() -// user blinds the msg -msgBlinded, user := blindsecp256k1.Blind(msg, signerPublicData) +// user: blinds the msg using signer's R +msg := new(big.Int).SetBytes([]byte("test")) +msgBlinded, userSecretData := Blind(msg, signerR) -// signer signs the blinded message -sBlind := signerPrivateData.BlindSign(msgBlinded) +// signer: signs the blinded message using its private key & secret k +sBlind := sk.BlindSign(msgBlinded, k) -// user unblinds the blinded signature -sig := blindsecp256k1.Unblind(sBlind, msg, user) +// user: unblinds the blinded signature +sig := Unblind(sBlind, msg, userSecretData) // signature can be verified with signer PublicKey -verified := blindsecp256k1.Verify(msg, sig, signerPublicData.Q) +verified := Verify(msg, sig, signerPubK) assert.True(t, verified) ``` diff --git a/blindsecp256k1.go b/blindsecp256k1.go index 96d7f7b..9ec7c0d 100644 --- a/blindsecp256k1.go +++ b/blindsecp256k1.go @@ -94,46 +94,20 @@ func (pk *PublicKey) Point() *Point { return (*Point)(pk) } -// SignerPrivateData contains the secret values from the Signer -type SignerPrivateData struct { - D *PrivateKey - K *big.Int -} - -// SignerPublicData contains the public values from the Signer (generated from -// its SignerPrivateData) -type SignerPublicData struct { - // Q is the Signer Public Key - Q *PublicKey // = skG - R *Point // = kG -} - -// NewSigner returns a new SignerPrivateData with random D & K -func NewSigner() *SignerPrivateData { - sk := NewPrivateKey() +// NewRequestParameters returns a new random k (secret) & R (public) parameters +func NewRequestParameters() (*big.Int, *Point) { k := newRand() - return &SignerPrivateData{ - D: sk, - K: k, - } + return k, G.Mul(k) // R = kG } -// PublicData returns the SignerPublicData from the SignerPrivateData -func (signer *SignerPrivateData) PublicData() *SignerPublicData { - return &SignerPublicData{ - Q: signer.D.Public(), // Q = dG - R: G.Mul(signer.K), // R = kG - } -} - -// BlindSign performs the blind signature on the given mBlinded using -// SignerPrivateData values -func (signer *SignerPrivateData) BlindSign(mBlinded *big.Int) *big.Int { +// 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 { // TODO add pending checks // s' = dm' + k sBlind := new(big.Int).Add( - new(big.Int).Mul(signer.D.BigInt(), mBlinded), - signer.K) + new(big.Int).Mul(sk.BigInt(), mBlinded), + k) return sBlind } @@ -146,17 +120,19 @@ type UserSecretData struct { F *Point // public (in the paper is R) } -// Blind performs the blinding operation on m using SignerPublicData parameters -func Blind(m *big.Int, signer *SignerPublicData) (*big.Int, *UserSecretData) { +// Blind performs the blinding operation on m using signerR parameter +func Blind(m *big.Int, signerR *Point) (*big.Int, *UserSecretData) { u := &UserSecretData{} u.A = newRand() u.B = newRand() // (R) F = aR' + bG - aR := signer.R.Mul(u.A) + aR := signerR.Mul(u.A) bG := G.Mul(u.B) u.F = aR.Add(bG) + // TODO check that F != O (point at infinity) + rx := new(big.Int).Mod(u.F.X, N) // m' = a^-1 rx h(m) diff --git a/blindsecp256k1_test.go b/blindsecp256k1_test.go index 6091a85..6175d36 100644 --- a/blindsecp256k1_test.go +++ b/blindsecp256k1_test.go @@ -8,23 +8,25 @@ import ( ) func TestFlow(t *testing.T) { - // message to be signed - msg := new(big.Int).SetBytes([]byte("test")) + // signer: create new signer key pair + sk := NewPrivateKey() + signerPubK := sk.Public() - // create new signer - signerPrivateData := NewSigner() - signerPublicData := signerPrivateData.PublicData() + // signer: when user requests new R parameter to blind a new msg, + // create new signerR (public) with its secret k + k, signerR := NewRequestParameters() - // user blinds the msg - msgBlinded, user := Blind(msg, signerPublicData) + // user: blinds the msg using signer's R + msg := new(big.Int).SetBytes([]byte("test")) + msgBlinded, userSecretData := Blind(msg, signerR) - // signer signs the blinded message - sBlind := signerPrivateData.BlindSign(msgBlinded) + // signer: signs the blinded message using its private key & secret k + sBlind := sk.BlindSign(msgBlinded, k) - // user unblinds the blinded signature - sig := Unblind(sBlind, msg, user) + // user: unblinds the blinded signature + sig := Unblind(sBlind, msg, userSecretData) - // signature can be verified with signer PublicKey (Q) - verified := Verify(msg, sig, signerPublicData.Q) + // signature can be verified with signer PublicKey + verified := Verify(msg, sig, signerPubK) assert.True(t, verified) } diff --git a/go.mod b/go.mod index 7d51625..0c15b13 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module blindsecp256k1 +module github.com/arnaucube/go-blindsecp256k1 go 1.14 diff --git a/go.sum b/go.sum index bcc8e30..da58442 100644 --- a/go.sum +++ b/go.sum @@ -20,7 +20,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/arnaucube/go-blindsecp256k1 v0.0.0-20210110223224-c3e4afc55292 h1:IDrJ98Pv07YozWvwigwK9ygJBa6zsB+H5sHGWLJTrX8= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= @@ -30,7 +29,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/v0/blindsecp256k1v0.go b/v0/blindsecp256k1v0.go index 87dbcd3..1308f1e 100644 --- a/v0/blindsecp256k1v0.go +++ b/v0/blindsecp256k1v0.go @@ -93,46 +93,20 @@ func (pk *PublicKey) Point() *Point { return (*Point)(pk) } -// SignerPrivateData contains the secret values from the Signer -type SignerPrivateData struct { - D *PrivateKey - K *big.Int -} - -// SignerPublicData contains the public values from the Signer (generated from -// its SignerPrivateData) -type SignerPublicData struct { - // Q is the Signer Public Key - Q *PublicKey // = skG - R *Point // = kG -} - -// NewSigner returns a new SignerPrivateData with random D & K -func NewSigner() *SignerPrivateData { - sk := NewPrivateKey() +// NewRequestParameters returns a new random k (secret) & R (public) parameters +func NewRequestParameters() (*big.Int, *Point) { k := newRand() - return &SignerPrivateData{ - D: sk, - K: k, - } -} - -// PublicData returns the SignerPublicData from the SignerPrivateData -func (signer *SignerPrivateData) PublicData() *SignerPublicData { - return &SignerPublicData{ - Q: signer.D.Public(), // Q = dG - R: G.Mul(signer.K), // R = kG - } + return k, G.Mul(k) // R = kG } // BlindSign performs the blind signature on the given mBlinded using // SignerPrivateData values -func (signer *SignerPrivateData) BlindSign(mBlinded *big.Int) *big.Int { +func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) *big.Int { // TODO add pending checks // s' = d(m') + k sBlind := new(big.Int).Add( - new(big.Int).Mul(signer.D.BigInt(), mBlinded), - signer.K) + new(big.Int).Mul(sk.BigInt(), mBlinded), + k) return sBlind } @@ -147,7 +121,7 @@ type UserSecretData struct { } // Blind performs the blinding operation on m using SignerPublicData parameters -func Blind(m *big.Int, signer *SignerPublicData) (*big.Int, *UserSecretData) { +func Blind(m *big.Int, signerPubK *PublicKey, signerR *Point) (*big.Int, *UserSecretData) { u := &UserSecretData{} u.A = newRand() u.B = newRand() @@ -155,10 +129,10 @@ func Blind(m *big.Int, signer *SignerPublicData) (*big.Int, *UserSecretData) { binv := new(big.Int).ModInverse(u.B, N) // F = b^-1 R + a b^-1 Q + c G - bR := signer.R.Mul(binv) + bR := signerR.Mul(binv) abinv := new(big.Int).Mul(u.A, binv) abinv = new(big.Int).Mod(abinv, N) - abQ := signer.Q.Point().Mul(abinv) + abQ := signerPubK.Point().Mul(abinv) cG := G.Mul(u.C) u.F = bR.Add(abQ).Add(cG) // TODO check F==O diff --git a/v0/blindsecp256k1v0_test.go b/v0/blindsecp256k1v0_test.go index 5d616c6..3f758e9 100644 --- a/v0/blindsecp256k1v0_test.go +++ b/v0/blindsecp256k1v0_test.go @@ -8,23 +8,25 @@ import ( ) func TestFlow(t *testing.T) { - // message to be signed - msg := new(big.Int).SetBytes([]byte("test")) + // signer: create new signer key pair + sk := NewPrivateKey() + signerPubK := sk.Public() - // create new signer - signerPrivateData := NewSigner() - signerPublicData := signerPrivateData.PublicData() + // signer: when user requests new R parameter to blind a new msg, + // create new signerR (public) with its secret k + k, signerR := NewRequestParameters() - // user blinds the msg - msgBlinded, user := Blind(msg, signerPublicData) + // user: blinds the msg using signer's R + msg := new(big.Int).SetBytes([]byte("test")) + msgBlinded, userSecretData := Blind(msg, signerPubK, signerR) - // signer signs the blinded message - sBlind := signerPrivateData.BlindSign(msgBlinded) + // signer: signs the blinded message using its private key & secret k + sBlind := sk.BlindSign(msgBlinded, k) - // user unblinds the blinded signature - sig := Unblind(sBlind, msg, user) + // user: unblinds the blinded signature + sig := Unblind(sBlind, msg, userSecretData) // signature can be verified with signer PublicKey (Q) - verified := Verify(msg, sig, signerPublicData.Q) + verified := Verify(msg, sig, signerPubK) assert.True(t, verified) } diff --git a/wasm/blindsecp256k1-wasm.go b/wasm/blindsecp256k1-wasm.go index 8e2553c..adf482e 100644 --- a/wasm/blindsecp256k1-wasm.go +++ b/wasm/blindsecp256k1-wasm.go @@ -57,8 +57,7 @@ func blindv0(this js.Value, values []js.Value) interface{} { Y: signerRy, } - signer := &blindsecp256k1v0.SignerPublicData{signerQ, signerR} - mBlinded, user := blindsecp256k1v0.Blind(m, signer) + mBlinded, user := blindsecp256k1v0.Blind(m, signerQ, signerR) r := make(map[string]interface{}) r["mBlinded"] = mBlinded.String() @@ -108,28 +107,19 @@ func unblindv0(this js.Value, values []js.Value) interface{} { } func blind(this js.Value, values []js.Value) interface{} { mStr := values[0].String() - signerQxStr := values[1].String() - signerQyStr := values[2].String() - signerRxStr := values[3].String() - signerRyStr := values[4].String() + signerRxStr := values[1].String() + signerRyStr := values[2].String() m := stringToBigInt(mStr) - signerQx := stringToBigInt(signerQxStr) - signerQy := stringToBigInt(signerQyStr) signerRx := stringToBigInt(signerRxStr) signerRy := stringToBigInt(signerRyStr) - signerQ := &blindsecp256k1.PublicKey{ - X: signerQx, - Y: signerQy, - } signerR := &blindsecp256k1.Point{ X: signerRx, Y: signerRy, } - signer := &blindsecp256k1.SignerPublicData{signerQ, signerR} - mBlinded, user := blindsecp256k1.Blind(m, signer) + mBlinded, user := blindsecp256k1.Blind(m, signerR) r := make(map[string]interface{}) r["mBlinded"] = mBlinded.String() diff --git a/wasm/webtest/blindsecp256k1.wasm b/wasm/webtest/blindsecp256k1.wasm index fb928a8..ca0f6b8 100755 Binary files a/wasm/webtest/blindsecp256k1.wasm and b/wasm/webtest/blindsecp256k1.wasm differ diff --git a/wasm/webtest/index.js b/wasm/webtest/index.js index 50b6e72..77cd822 100644 --- a/wasm/webtest/index.js +++ b/wasm/webtest/index.js @@ -2,15 +2,15 @@ function test() { let m = "1952805748"; console.log("using: https://sci-hub.do/10.1109/ICCKE.2013.6682844"); - // Q & R would be received from the Signer - let signerQx = "26613296432153871833441195158297038913673464785502568519907582377915678491093"; - let signerQy = "81940194042971427014176158889809922552127995083760111384335138546589994227275"; + // R would be received from the Signer let signerRx = "59371873487402651110657306418818354906476102545298559461791300717696053835454"; let signerRy = "98322875246066710654579302898391677189379767946198239290895789444110962324342"; - let blindRes = blind(m, signerQx, signerQy, signerRx, signerRy); + let blindRes = blind(m, signerRx, signerRy); console.log("blind", blindRes); - // sBlind would be received from the Signer + // Q & sBlind would be received from the Signer + let signerQx = "26613296432153871833441195158297038913673464785502568519907582377915678491093"; + let signerQy = "81940194042971427014176158889809922552127995083760111384335138546589994227275"; let sBlind = "7240298625621589352655632414257224668430424461224914067754717095121139699933353374227084479180038954015287518505167995306229258561275087198611946596619855"; let unblindRes = unblind(sBlind, m, blindRes.uA, blindRes.uB, blindRes.uFx, blindRes.uFy); console.log("unblind", unblindRes);