diff --git a/Makefile b/Makefile index f5b2c46aa..720452255 100644 --- a/Makefile +++ b/Makefile @@ -24,4 +24,4 @@ coverage: tidy # target to run all the possible checks; it's a good habit to run it before # pushing code check: lint vet test - echo "check done" + echo "check done" \ No newline at end of file diff --git a/sign/bls/bls_test.go b/sign/bls/bls_test.go index 2588df1eb..4a95ef39f 100644 --- a/sign/bls/bls_test.go +++ b/sign/bls/bls_test.go @@ -1,129 +1,282 @@ package bls -/*func TestBLSBatchVerify(t *testing.T) {*/ -//msg1 := []byte("Hello Boneh-Lynn-Shacham") -//msg2 := []byte("Hello Dedis & Boneh-Lynn-Shacham") -//suite := bn256.NewSuite() -//private1, public1 := NewKeyPair(suite, random.New()) -//private2, public2 := NewKeyPair(suite, random.New()) -//sig1, err := Sign(suite, private1, msg1) -//require.Nil(t, err) -//sig2, err := Sign(suite, private2, msg2) -//require.Nil(t, err) -//aggregatedSig, err := AggregateSignatures(suite, sig1, sig2) -//require.Nil(t, err) - -//err = BatchVerify(suite, []kyber.Point{public1, public2}, [][]byte{msg1, msg2}, aggregatedSig) -//require.Nil(t, err) -//} -//func TestBLSFailBatchVerify(t *testing.T) { -//msg1 := []byte("Hello Boneh-Lynn-Shacham") -//msg2 := []byte("Hello Dedis & Boneh-Lynn-Shacham") -//suite := bn256.NewSuite() -//private1, public1 := NewKeyPair(suite, random.New()) -//private2, public2 := NewKeyPair(suite, random.New()) -//sig1, err := Sign(suite, private1, msg1) -//require.Nil(t, err) -//sig2, err := Sign(suite, private2, msg2) -//require.Nil(t, err) - -//t.Run("fails with a bad signature", func(t *testing.T) { -//aggregatedSig, err := AggregateSignatures(suite, sig1, sig2) -//require.Nil(t, err) -//msg2[0] ^= 0x01 -//if BatchVerify(suite, []kyber.Point{public1, public2}, [][]byte{msg1, msg2}, aggregatedSig) == nil { -//t.Fatal("bls: verification succeeded unexpectedly") -//} -//}) - -//t.Run("fails with a duplicate msg", func(t *testing.T) { -//private3, public3 := NewKeyPair(suite, random.New()) -//sig3, err := Sign(suite, private3, msg1) -//require.Nil(t, err) -//aggregatedSig, err := AggregateSignatures(suite, sig1, sig2, sig3) -//require.Nil(t, err) - -//if BatchVerify(suite, []kyber.Point{public1, public2, public3}, [][]byte{msg1, msg2, msg1}, aggregatedSig) == nil { -//t.Fatal("bls: verification succeeded unexpectedly") -//} -//}) - -//} - -//func BenchmarkBLSKeyCreation(b *testing.B) { -//suite := bn256.NewSuite() -//b.ResetTimer() -//for i := 0; i < b.N; i++ { -//NewKeyPair(suite, random.New()) -//} -//} - -//func BenchmarkBLSSign(b *testing.B) { -//suite := bn256.NewSuite() -//private, _ := NewKeyPair(suite, random.New()) -//msg := []byte("Hello many times Boneh-Lynn-Shacham") -//b.ResetTimer() -//for i := 0; i < b.N; i++ { -//Sign(suite, private, msg) -//} -//} - -//func BenchmarkBLSAggregateSigs(b *testing.B) { -//suite := bn256.NewSuite() -//private1, _ := NewKeyPair(suite, random.New()) -//private2, _ := NewKeyPair(suite, random.New()) -//msg := []byte("Hello many times Boneh-Lynn-Shacham") -//sig1, err := Sign(suite, private1, msg) -//require.Nil(b, err) -//sig2, err := Sign(suite, private2, msg) -//require.Nil(b, err) - -//b.ResetTimer() -//for i := 0; i < b.N; i++ { -//AggregateSignatures(suite, sig1, sig2) -//} -//} - -//func BenchmarkBLSVerifyAggregate(b *testing.B) { -//suite := bn256.NewSuite() -//private1, public1 := NewKeyPair(suite, random.New()) -//private2, public2 := NewKeyPair(suite, random.New()) -//msg := []byte("Hello many times Boneh-Lynn-Shacham") -//sig1, err := Sign(suite, private1, msg) -//require.Nil(b, err) -//sig2, err := Sign(suite, private2, msg) -//require.Nil(b, err) -//sig, err := AggregateSignatures(suite, sig1, sig2) -//key := AggregatePublicKeys(suite, public1, public2) -//b.ResetTimer() -//for i := 0; i < b.N; i++ { -//Verify(suite, key, msg, sig) -//} -//} - -//func BenchmarkBLSVerifyBatchVerify(b *testing.B) { -//suite := bn256.NewSuite() - -//numSigs := 100 -//privates := make([]kyber.Scalar, numSigs) -//publics := make([]kyber.Point, numSigs) -//msgs := make([][]byte, numSigs) -//sigs := make([][]byte, numSigs) -//for i := 0; i < numSigs; i++ { -//private, public := NewKeyPair(suite, random.New()) -//privates[i] = private -//publics[i] = public -//msg := make([]byte, 64, 64) -//rand.Read(msg) -//msgs[i] = msg -//sig, err := Sign(suite, private, msg) -//require.Nil(b, err) -//sigs[i] = sig -//} - -//b.ResetTimer() -//for i := 0; i < b.N; i++ { -//aggregateSig, _ := AggregateSignatures(suite, sigs...) -//BatchVerify(suite, publics, msgs, aggregateSig) -//} -//} +import ( + "crypto/rand" + "testing" + + "github.com/stretchr/testify/require" + "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber/v3/pairing/bn256" + "go.dedis.ch/kyber/v3/util/random" + "go.dedis.ch/kyber/v3/xof/blake2xb" +) + +func TestBLS(t *testing.T) { + suite := bn256.NewSuite() + msg := []byte("Hello Boneh-Lynn-Shacham") + BLSRoutine(t, msg, suite) +} + +func FuzzBLS(f *testing.F) { + suite := bn256.NewSuite() + f.Fuzz(func(t *testing.T, msg []byte) { + if len(msg) < 1 || len(msg) > 1000 { + t.Skip("msg must have byte length between 1 and 1000") + } + BLSRoutine(t, msg, suite) + }) +} + +func BLSRoutine(t *testing.T, msg []byte, suite *bn256.Suite) { + scheme := NewSchemeOnG1(suite) + private, public := scheme.NewKeyPair(blake2xb.New(msg)) + sig, err := scheme.Sign(private, msg) + require.Nil(t, err) + err = scheme.Verify(public, msg, sig) + require.Nil(t, err) +} + +func TestBLSFailSig(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private, public := scheme.NewKeyPair(random.New()) + sig, err := scheme.Sign(private, msg) + require.Nil(t, err) + sig[0] ^= 0x01 + if scheme.Verify(public, msg, sig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } +} + +func TestBLSFailKey(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private, _ := scheme.NewKeyPair(random.New()) + sig, err := scheme.Sign(private, msg) + require.Nil(t, err) + _, public := scheme.NewKeyPair(random.New()) + if scheme.Verify(public, msg, sig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } +} + +func TestBLSAggregateSignatures(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg) + require.Nil(t, err) + sig2, err := scheme.Sign(private2, msg) + require.Nil(t, err) + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2) + require.Nil(t, err) + + aggregatedKey := scheme.AggregatePublicKeys(public1, public2) + + err = scheme.Verify(aggregatedKey, msg, aggregatedSig) + require.Nil(t, err) +} + +func TestBLSFailAggregatedSig(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg) + require.Nil(t, err) + sig2, err := scheme.Sign(private2, msg) + require.Nil(t, err) + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2) + require.Nil(t, err) + aggregatedKey := scheme.AggregatePublicKeys(public1, public2) + + aggregatedSig[0] ^= 0x01 + if scheme.Verify(aggregatedKey, msg, aggregatedSig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } +} +func TestBLSFailAggregatedKey(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + _, public3 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg) + require.Nil(t, err) + sig2, err := scheme.Sign(private2, msg) + require.Nil(t, err) + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2) + require.Nil(t, err) + badAggregatedKey := scheme.AggregatePublicKeys(public1, public2, public3) + + if scheme.Verify(badAggregatedKey, msg, aggregatedSig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } +} +func TestBLSBatchVerify(t *testing.T) { + msg1 := []byte("Hello Boneh-Lynn-Shacham") + msg2 := []byte("Hello Dedis & Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg1) + require.Nil(t, err) + sig2, err := scheme.Sign(private2, msg2) + require.Nil(t, err) + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2) + require.Nil(t, err) + + err = BatchVerify(suite, []kyber.Point{public1, public2}, [][]byte{msg1, msg2}, aggregatedSig) + require.Nil(t, err) +} +func TestBLSFailBatchVerify(t *testing.T) { + msg1 := []byte("Hello Boneh-Lynn-Shacham") + msg2 := []byte("Hello Dedis & Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg1) + require.Nil(t, err) + sig2, err := scheme.Sign(private2, msg2) + require.Nil(t, err) + + t.Run("fails with a bad signature", func(t *testing.T) { + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2) + require.Nil(t, err) + msg2[0] ^= 0x01 + if BatchVerify(suite, []kyber.Point{public1, public2}, [][]byte{msg1, msg2}, aggregatedSig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } + }) + + t.Run("fails with a duplicate msg", func(t *testing.T) { + private3, public3 := scheme.NewKeyPair(random.New()) + sig3, err := scheme.Sign(private3, msg1) + require.Nil(t, err) + aggregatedSig, err := scheme.AggregateSignatures(sig1, sig2, sig3) + require.Nil(t, err) + + if BatchVerify(suite, []kyber.Point{public1, public2, public3}, [][]byte{msg1, msg2, msg1}, aggregatedSig) == nil { + t.Fatal("bls: verification succeeded unexpectedly") + } + }) + +} + +func BenchmarkBLSKeyCreation(b *testing.B) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + b.ResetTimer() + for i := 0; i < b.N; i++ { + scheme.NewKeyPair(random.New()) + } +} + +func BenchmarkBLSSign(b *testing.B) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private, _ := scheme.NewKeyPair(random.New()) + msg := []byte("Hello many times Boneh-Lynn-Shacham") + b.ResetTimer() + for i := 0; i < b.N; i++ { + scheme.Sign(private, msg) + } +} + +func BenchmarkBLSAggregateSigs(b *testing.B) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, _ := scheme.NewKeyPair(random.New()) + private2, _ := scheme.NewKeyPair(random.New()) + msg := []byte("Hello many times Boneh-Lynn-Shacham") + sig1, err := scheme.Sign(private1, msg) + require.Nil(b, err) + sig2, err := scheme.Sign(private2, msg) + require.Nil(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + scheme.AggregateSignatures(sig1, sig2) + } +} + +func BenchmarkBLSVerifyAggregate(b *testing.B) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + msg := []byte("Hello many times Boneh-Lynn-Shacham") + sig1, err := scheme.Sign(private1, msg) + require.Nil(b, err) + sig2, err := scheme.Sign(private2, msg) + require.Nil(b, err) + sig, err := scheme.AggregateSignatures(sig1, sig2) + key := scheme.AggregatePublicKeys(public1, public2) + b.ResetTimer() + for i := 0; i < b.N; i++ { + scheme.Verify(key, msg, sig) + } +} + +func BenchmarkBLSVerifyBatchVerify(b *testing.B) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + + numSigs := 100 + privates := make([]kyber.Scalar, numSigs) + publics := make([]kyber.Point, numSigs) + msgs := make([][]byte, numSigs) + sigs := make([][]byte, numSigs) + for i := 0; i < numSigs; i++ { + private, public := scheme.NewKeyPair(random.New()) + privates[i] = private + publics[i] = public + msg := make([]byte, 64, 64) + rand.Read(msg) + msgs[i] = msg + sig, err := scheme.Sign(private, msg) + require.Nil(b, err) + sigs[i] = sig + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + aggregateSig, _ := scheme.AggregateSignatures(sigs...) + BatchVerify(suite, publics, msgs, aggregateSig) + } +} + +func TestBinaryMarshalAfterAggregation_issue400(t *testing.T) { + suite := bn256.NewSuite() + scheme := NewSchemeOnG1(suite) + + _, public1 := scheme.NewKeyPair(random.New()) + _, public2 := scheme.NewKeyPair(random.New()) + + workingKey := scheme.AggregatePublicKeys(public1, public2, public1) + + workingBits, err := workingKey.MarshalBinary() + require.Nil(t, err) + + workingPoint := suite.G2().Point() + err = workingPoint.UnmarshalBinary(workingBits) + require.Nil(t, err) + + // this was failing before the fix + aggregatedKey := scheme.AggregatePublicKeys(public1, public1, public2) + + bits, err := aggregatedKey.MarshalBinary() + require.Nil(t, err) + + point := suite.G2().Point() + err = point.UnmarshalBinary(bits) + require.Nil(t, err) +} diff --git a/sign/cosi/cosi_test.go b/sign/cosi/cosi_test.go index 437e11e98..6cabc4e43 100644 --- a/sign/cosi/cosi_test.go +++ b/sign/cosi/cosi_test.go @@ -28,24 +28,50 @@ func (m *cosiSuite) RandomStream() cipher.Stream { return m.r } var testSuite = &cosiSuite{edwards25519.NewBlakeSHA256Ed25519(), blake2xb.New(nil)} func TestCoSi(t *testing.T) { - testCoSi(t, 2, 0) - testCoSi(t, 5, 0) - testCoSi(t, 5, 2) - testCoSi(t, 5, 4) -} - -func testCoSi(t *testing.T, n, f int) { message := []byte("Hello World Cosi") // Generate key pairs var kps []*key.Pair + for i := 0; i < 5; i++ { + kp := key.NewKeyPair(testSuite) + kps = append(kps, kp) + } + + testCoSi(t, 2, 0, message, kps) + testCoSi(t, 5, 0, message, kps) + testCoSi(t, 5, 2, message, kps) + testCoSi(t, 5, 4, message, kps) +} + +func FuzzCoSi(f *testing.F) { + // Generate key pairs + var kps []*key.Pair + for i := 0; i < 100; i++ { + kp := key.NewKeyPair(testSuite) + kps = append(kps, kp) + } + + f.Fuzz(func(t *testing.T, n, f int, msg []byte) { + if (len(msg) < 1) || (len(msg) > 1000) { + t.Skip("msg must have byte length between 1 and 1000") + } + if n < 1 || n > 100 { + t.Skip("n must be between 1 and 100") + } + if f < 0 || f >= n { + t.Skip("f must be between 0 and n-1") + } + + testCoSi(t, n, f, msg, kps) + }) +} + +func testCoSi(t *testing.T, n, f int, message []byte, kps []*key.Pair) { var privates []kyber.Scalar var publics []kyber.Point for i := 0; i < n; i++ { - kp := key.NewKeyPair(testSuite) - kps = append(kps, kp) - privates = append(privates, kp.Private) - publics = append(publics, kp.Public) + privates = append(privates, kps[i].Private) + publics = append(publics, kps[i].Public) } // Init masks diff --git a/sign/schnorr/schnorr_test.go b/sign/schnorr/schnorr_test.go index e669c2ce1..f1a5cead8 100644 --- a/sign/schnorr/schnorr_test.go +++ b/sign/schnorr/schnorr_test.go @@ -7,6 +7,7 @@ import ( "testing/quick" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.dedis.ch/kyber/v3/group/edwards25519" "go.dedis.ch/kyber/v3/sign/eddsa" "go.dedis.ch/kyber/v3/util/key" @@ -125,3 +126,19 @@ func TestSchnorrMalleability(t *testing.T) { err = Verify(suite, kp.Public, msg, s) assert.Error(t, err, "schnorr signature malleable") } + +func FuzzSchnorr(f *testing.F) { + suite := edwards25519.NewBlakeSHA256Ed25519() + kp := key.NewKeyPair(suite) + + f.Fuzz(func(t *testing.T, msg []byte) { + if (len(msg) < 1) || (len(msg) > 1000) { + t.Skip("msg must have byte length between 1 and 1000") + } + s, err := Sign(suite, kp.Private, msg) + require.NoError(t, err, "Couldn't sign msg: %s: %v", msg, err) + + err = Verify(suite, kp.Public, msg, s) + require.NoError(t, err, "Couldn't verify signature: \n%+v\nfor msg:'%s'. Error:\n%v", s, msg, err) + }) +} diff --git a/sign/tbls/tbls_test.go b/sign/tbls/tbls_test.go index 2256ca9b6..78d03cd79 100644 --- a/sign/tbls/tbls_test.go +++ b/sign/tbls/tbls_test.go @@ -3,10 +3,54 @@ package tbls import ( "testing" + "github.com/stretchr/testify/require" "go.dedis.ch/kyber/v3/pairing/bn256" + "go.dedis.ch/kyber/v3/share" "go.dedis.ch/kyber/v3/sign/test" + "go.dedis.ch/kyber/v3/xof/blake2xb" ) +func TestTBLS(test *testing.T) { + TBLSRoutine(test, []byte("Hello threshold Boneh-Lynn-Shacham"), 10) +} + +func FuzzTBLS(f *testing.F) { + f.Fuzz(func(t *testing.T, msg []byte, n int) { + if (n < 1) || (n > 100) { + t.Skip("n must be between 1 and 100") + } + if (len(msg) < 1) || (len(msg) > 1000) { + t.Skip("msg must have byte length between 1 and 1000") + } + TBLSRoutine(t, msg, n) + }) +} + +func TBLSRoutine(test *testing.T, msg []byte, n int) { + // Use a deterministic seed for the random stream + stream := blake2xb.New(msg) + suite := bn256.NewSuiteRand(stream) + scheme := NewThresholdSchemeOnG1(suite) + th := n/2 + 1 + + secret := suite.G1().Scalar().Pick(stream) + priPoly := share.NewPriPoly(suite.G2(), th, secret, stream) + pubPoly := priPoly.Commit(suite.G2().Point().Base()) + sigShares := make([][]byte, 0) + + for _, x := range priPoly.Shares(n) { + sig, err := scheme.Sign(x, msg) + require.Nil(test, err) + sigShares = append(sigShares, sig) + } + + sig, err := scheme.Recover(pubPoly, msg, sigShares, th, n) + require.Nil(test, err) + + err = scheme.VerifyRecovered(pubPoly.Commit(), msg, sig) + require.Nil(test, err) +} + func TestBN256(t *testing.T) { suite := bn256.NewSuite() scheme := NewThresholdSchemeOnG1(suite)