From a0bb178ac8cb6a2cb365b40947c1ce3d95407e57 Mon Sep 17 00:00:00 2001 From: Matej Pavlovic Date: Tue, 30 Jan 2024 13:38:53 +0100 Subject: [PATCH 1/7] Add support for signatures on G2 to bdn --- sign/bdn/bdn.go | 61 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/sign/bdn/bdn.go b/sign/bdn/bdn.go index e6d2bb3ec..5fa7cf3eb 100644 --- a/sign/bdn/bdn.go +++ b/sign/bdn/bdn.go @@ -67,29 +67,68 @@ func hashPointToR(pubs []kyber.Point) ([]kyber.Scalar, error) { return coefs, nil } +type Scheme struct { + blsScheme sign.AggregatableScheme + sigGroup kyber.Group + keyGroup kyber.Group + pairing func(signature, public, hashedPoint kyber.Point) bool +} + +// NewSchemeOnG1 returns a sign.Scheme that uses G1 for its signature space and G2 +// for its public keys +func NewSchemeOnG1(suite pairing.Suite) *Scheme { + sigGroup := suite.G1() + keyGroup := suite.G2() + pairing := func(public, hashedMsg, sigPoint kyber.Point) bool { + return suite.ValidatePairing(hashedMsg, public, sigPoint, keyGroup.Point().Base()) + } + return &Scheme{ + blsScheme: bls.NewSchemeOnG1(suite), + sigGroup: sigGroup, + keyGroup: keyGroup, + pairing: pairing, + } +} + +// NewSchemeOnG2 returns a sign.Scheme that uses G2 for its signature space and +// G1 for its public key +func NewSchemeOnG2(suite pairing.Suite) *Scheme { + sigGroup := suite.G2() + keyGroup := suite.G1() + pairing := func(public, hashedMsg, sigPoint kyber.Point) bool { + return suite.ValidatePairing(public, hashedMsg, keyGroup.Point().Base(), sigPoint) + } + return &Scheme{ + blsScheme: bls.NewSchemeOnG2(suite), + sigGroup: sigGroup, + keyGroup: keyGroup, + pairing: pairing, + } +} + // NewKeyPair creates a new BLS signing key pair. The private key x is a scalar // and the public key X is a point on curve G2. -func NewKeyPair(suite pairing.Suite, random cipher.Stream) (kyber.Scalar, kyber.Point) { - return bls.NewSchemeOnG1(suite).NewKeyPair(random) +func NewKeyPair(scheme *Scheme, random cipher.Stream) (kyber.Scalar, kyber.Point) { + return scheme.blsScheme.NewKeyPair(random) } // Sign creates a BLS signature S = x * H(m) on a message m using the private // key x. The signature S is a point on curve G1. -func Sign(suite pairing.Suite, x kyber.Scalar, msg []byte) ([]byte, error) { - return bls.NewSchemeOnG1(suite).Sign(x, msg) +func Sign(scheme *Scheme, x kyber.Scalar, msg []byte) ([]byte, error) { + return scheme.blsScheme.Sign(x, msg) } // Verify checks the given BLS signature S on the message m using the public // key X by verifying that the equality e(H(m), X) == e(H(m), x*B2) == // e(x*H(m), B2) == e(S, B2) holds where e is the pairing operation and B2 is // the base point from curve G2. -func Verify(suite pairing.Suite, x kyber.Point, msg, sig []byte) error { - return bls.NewSchemeOnG1(suite).Verify(x, msg, sig) +func Verify(scheme *Scheme, x kyber.Point, msg, sig []byte) error { + return scheme.blsScheme.Verify(x, msg, sig) } // AggregateSignatures aggregates the signatures using a coefficient for each // one of them where c = H(pk) and H: G2 -> R with R = {1, ..., 2^128} -func AggregateSignatures(suite pairing.Suite, sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { +func AggregateSignatures(scheme *Scheme, sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { if len(sigs) != mask.CountEnabled() { return nil, errors.New("length of signatures and public keys must match") } @@ -99,7 +138,7 @@ func AggregateSignatures(suite pairing.Suite, sigs [][]byte, mask *sign.Mask) (k return nil, err } - agg := suite.G1().Point() + agg := scheme.sigGroup.Point() for i, buf := range sigs { peerIndex := mask.IndexOfNthEnabled(i) if peerIndex < 0 { @@ -108,7 +147,7 @@ func AggregateSignatures(suite pairing.Suite, sigs [][]byte, mask *sign.Mask) (k return nil, errors.New("couldn't find the index") } - sig := suite.G1().Point() + sig := scheme.sigGroup.Point() err = sig.UnmarshalBinary(buf) if err != nil { return nil, err @@ -126,13 +165,13 @@ func AggregateSignatures(suite pairing.Suite, sigs [][]byte, mask *sign.Mask) (k // AggregatePublicKeys aggregates a set of public keys (similarly to // AggregateSignatures for signatures) using the hash function // H: G2 -> R with R = {1, ..., 2^128}. -func AggregatePublicKeys(suite pairing.Suite, mask *sign.Mask) (kyber.Point, error) { +func AggregatePublicKeys(scheme *Scheme, mask *sign.Mask) (kyber.Point, error) { coefs, err := hashPointToR(mask.Publics()) if err != nil { return nil, err } - agg := suite.G2().Point() + agg := scheme.keyGroup.Point() for i := 0; i < mask.CountEnabled(); i++ { peerIndex := mask.IndexOfNthEnabled(i) if peerIndex < 0 { From f25e0f6496e15d7d18c3c8b003d39c94c1a68773 Mon Sep 17 00:00:00 2001 From: Matej Pavlovic Date: Tue, 30 Jan 2024 16:49:15 +0100 Subject: [PATCH 2/7] Adapt bdn_test.go to new BDN interface --- sign/bdn/bdn_test.go | 55 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/sign/bdn/bdn_test.go b/sign/bdn/bdn_test.go index e30bb853e..7f34d2eb6 100644 --- a/sign/bdn/bdn_test.go +++ b/sign/bdn/bdn_test.go @@ -13,6 +13,7 @@ import ( ) var suite = bn256.NewSuiteBn256() +var schemeOnG1 = NewSchemeOnG1(suite) var two = suite.Scalar().Add(suite.Scalar().One(), suite.Scalar().One()) var three = suite.Scalar().Add(two, suite.Scalar().One()) @@ -35,7 +36,7 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { mask.SetBit(1, true) mask.SetBit(2, true) - agg, err := AggregatePublicKeys(suite, mask) + agg, err := AggregatePublicKeys(schemeOnG1, mask) require.NoError(t, err) buf, err := agg.MarshalBinary() @@ -47,62 +48,62 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { func TestBDN_AggregateSignatures(t *testing.T) { msg := []byte("Hello Boneh-Lynn-Shacham") suite := bn256.NewSuite() - private1, public1 := NewKeyPair(suite, random.New()) - private2, public2 := NewKeyPair(suite, random.New()) - sig1, err := Sign(suite, private1, msg) + private1, public1 := NewKeyPair(schemeOnG1, random.New()) + private2, public2 := NewKeyPair(schemeOnG1, random.New()) + sig1, err := Sign(schemeOnG1, private1, msg) require.NoError(t, err) - sig2, err := Sign(suite, private2, msg) + sig2, err := Sign(schemeOnG1, private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) mask.SetBit(0, true) mask.SetBit(1, true) - _, err = AggregateSignatures(suite, [][]byte{sig1}, mask) + _, err = AggregateSignatures(schemeOnG1, [][]byte{sig1}, mask) require.Error(t, err) - aggregatedSig, err := AggregateSignatures(suite, [][]byte{sig1, sig2}, mask) + aggregatedSig, err := AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := AggregatePublicKeys(suite, mask) + aggregatedKey, err := AggregatePublicKeys(schemeOnG1, mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = Verify(suite, aggregatedKey, msg, sig) + err = Verify(schemeOnG1, aggregatedKey, msg, sig) require.NoError(t, err) mask.SetBit(1, false) - aggregatedKey, err = AggregatePublicKeys(suite, mask) + aggregatedKey, err = AggregatePublicKeys(schemeOnG1, mask) - err = Verify(suite, aggregatedKey, msg, sig) + err = Verify(schemeOnG1, aggregatedKey, msg, sig) require.Error(t, err) } func TestBDN_SubsetSignature(t *testing.T) { msg := []byte("Hello Boneh-Lynn-Shacham") suite := bn256.NewSuite() - private1, public1 := NewKeyPair(suite, random.New()) - private2, public2 := NewKeyPair(suite, random.New()) - _, public3 := NewKeyPair(suite, random.New()) - sig1, err := Sign(suite, private1, msg) + private1, public1 := NewKeyPair(schemeOnG1, random.New()) + private2, public2 := NewKeyPair(schemeOnG1, random.New()) + _, public3 := NewKeyPair(schemeOnG1, random.New()) + sig1, err := Sign(schemeOnG1, private1, msg) require.NoError(t, err) - sig2, err := Sign(suite, private2, msg) + sig2, err := Sign(schemeOnG1, private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public3, public2}, nil) mask.SetBit(0, true) mask.SetBit(2, true) - aggregatedSig, err := AggregateSignatures(suite, [][]byte{sig1, sig2}, mask) + aggregatedSig, err := AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := AggregatePublicKeys(suite, mask) + aggregatedKey, err := AggregatePublicKeys(schemeOnG1, mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = Verify(suite, aggregatedKey, msg, sig) + err = Verify(schemeOnG1, aggregatedKey, msg, sig) require.NoError(t, err) } @@ -120,7 +121,7 @@ func TestBDN_RogueAttack(t *testing.T) { pubs := []kyber.Point{public1, rogue} - sig, err := Sign(suite, private2, msg) + sig, err := Sign(schemeOnG1, private2, msg) require.NoError(t, err) // Old scheme not resistant to the attack @@ -131,19 +132,19 @@ func TestBDN_RogueAttack(t *testing.T) { mask, _ := sign.NewMask(suite, pubs, nil) mask.SetBit(0, true) mask.SetBit(1, true) - agg, err = AggregatePublicKeys(suite, mask) + agg, err = AggregatePublicKeys(schemeOnG1, mask) require.NoError(t, err) - require.Error(t, Verify(suite, agg, msg, sig)) + require.Error(t, Verify(schemeOnG1, agg, msg, sig)) } func Benchmark_BDN_AggregateSigs(b *testing.B) { suite := bn256.NewSuite() - private1, public1 := NewKeyPair(suite, random.New()) - private2, public2 := NewKeyPair(suite, random.New()) + private1, public1 := NewKeyPair(schemeOnG1, random.New()) + private2, public2 := NewKeyPair(schemeOnG1, random.New()) msg := []byte("Hello many times Boneh-Lynn-Shacham") - sig1, err := Sign(suite, private1, msg) + sig1, err := Sign(schemeOnG1, private1, msg) require.Nil(b, err) - sig2, err := Sign(suite, private2, msg) + sig2, err := Sign(schemeOnG1, private2, msg) require.Nil(b, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) @@ -152,6 +153,6 @@ func Benchmark_BDN_AggregateSigs(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - AggregateSignatures(suite, [][]byte{sig1, sig2}, mask) + AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) } } From f556b3a7e7bc2414f6b8025d13ad7281f0145dbb Mon Sep 17 00:00:00 2001 From: Matej Pavlovic Date: Wed, 7 Feb 2024 22:46:41 +0100 Subject: [PATCH 3/7] Make API functions methods of the Scheme type --- sign/bdn/bdn.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sign/bdn/bdn.go b/sign/bdn/bdn.go index 5fa7cf3eb..dab05e472 100644 --- a/sign/bdn/bdn.go +++ b/sign/bdn/bdn.go @@ -108,13 +108,13 @@ func NewSchemeOnG2(suite pairing.Suite) *Scheme { // NewKeyPair creates a new BLS signing key pair. The private key x is a scalar // and the public key X is a point on curve G2. -func NewKeyPair(scheme *Scheme, random cipher.Stream) (kyber.Scalar, kyber.Point) { +func (scheme *Scheme) NewKeyPair(random cipher.Stream) (kyber.Scalar, kyber.Point) { return scheme.blsScheme.NewKeyPair(random) } // Sign creates a BLS signature S = x * H(m) on a message m using the private // key x. The signature S is a point on curve G1. -func Sign(scheme *Scheme, x kyber.Scalar, msg []byte) ([]byte, error) { +func (scheme *Scheme) Sign(x kyber.Scalar, msg []byte) ([]byte, error) { return scheme.blsScheme.Sign(x, msg) } @@ -122,13 +122,13 @@ func Sign(scheme *Scheme, x kyber.Scalar, msg []byte) ([]byte, error) { // key X by verifying that the equality e(H(m), X) == e(H(m), x*B2) == // e(x*H(m), B2) == e(S, B2) holds where e is the pairing operation and B2 is // the base point from curve G2. -func Verify(scheme *Scheme, x kyber.Point, msg, sig []byte) error { +func (scheme *Scheme) Verify(x kyber.Point, msg, sig []byte) error { return scheme.blsScheme.Verify(x, msg, sig) } // AggregateSignatures aggregates the signatures using a coefficient for each // one of them where c = H(pk) and H: G2 -> R with R = {1, ..., 2^128} -func AggregateSignatures(scheme *Scheme, sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { +func (scheme *Scheme) AggregateSignatures(sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { if len(sigs) != mask.CountEnabled() { return nil, errors.New("length of signatures and public keys must match") } @@ -165,7 +165,7 @@ func AggregateSignatures(scheme *Scheme, sigs [][]byte, mask *sign.Mask) (kyber. // AggregatePublicKeys aggregates a set of public keys (similarly to // AggregateSignatures for signatures) using the hash function // H: G2 -> R with R = {1, ..., 2^128}. -func AggregatePublicKeys(scheme *Scheme, mask *sign.Mask) (kyber.Point, error) { +func (scheme *Scheme) AggregatePublicKeys(mask *sign.Mask) (kyber.Point, error) { coefs, err := hashPointToR(mask.Publics()) if err != nil { return nil, err From 3fbec7c75ea59ddfcf4b3277c5e15e01a60e5f65 Mon Sep 17 00:00:00 2001 From: Matej Pavlovic Date: Wed, 7 Feb 2024 22:51:55 +0100 Subject: [PATCH 4/7] Generalize G1- and G2-related comments --- sign/bdn/bdn.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sign/bdn/bdn.go b/sign/bdn/bdn.go index dab05e472..d7a59c639 100644 --- a/sign/bdn/bdn.go +++ b/sign/bdn/bdn.go @@ -107,13 +107,13 @@ func NewSchemeOnG2(suite pairing.Suite) *Scheme { } // NewKeyPair creates a new BLS signing key pair. The private key x is a scalar -// and the public key X is a point on curve G2. +// and the public key X is a point on the scheme's key group. func (scheme *Scheme) NewKeyPair(random cipher.Stream) (kyber.Scalar, kyber.Point) { return scheme.blsScheme.NewKeyPair(random) } // Sign creates a BLS signature S = x * H(m) on a message m using the private -// key x. The signature S is a point on curve G1. +// key x. The signature S is a point on the scheme's signature group. func (scheme *Scheme) Sign(x kyber.Scalar, msg []byte) ([]byte, error) { return scheme.blsScheme.Sign(x, msg) } @@ -121,13 +121,13 @@ func (scheme *Scheme) Sign(x kyber.Scalar, msg []byte) ([]byte, error) { // Verify checks the given BLS signature S on the message m using the public // key X by verifying that the equality e(H(m), X) == e(H(m), x*B2) == // e(x*H(m), B2) == e(S, B2) holds where e is the pairing operation and B2 is -// the base point from curve G2. +// the base point from the scheme's key group. func (scheme *Scheme) Verify(x kyber.Point, msg, sig []byte) error { return scheme.blsScheme.Verify(x, msg, sig) } // AggregateSignatures aggregates the signatures using a coefficient for each -// one of them where c = H(pk) and H: G2 -> R with R = {1, ..., 2^128} +// one of them where c = H(pk) and H: keyGroup -> R with R = {1, ..., 2^128} func (scheme *Scheme) AggregateSignatures(sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { if len(sigs) != mask.CountEnabled() { return nil, errors.New("length of signatures and public keys must match") @@ -164,7 +164,7 @@ func (scheme *Scheme) AggregateSignatures(sigs [][]byte, mask *sign.Mask) (kyber // AggregatePublicKeys aggregates a set of public keys (similarly to // AggregateSignatures for signatures) using the hash function -// H: G2 -> R with R = {1, ..., 2^128}. +// H: keyGroup -> R with R = {1, ..., 2^128}. func (scheme *Scheme) AggregatePublicKeys(mask *sign.Mask) (kyber.Point, error) { coefs, err := hashPointToR(mask.Publics()) if err != nil { From 9005b29e0b7af783ab42fad5a58ed30199ff6e2d Mon Sep 17 00:00:00 2001 From: Yolan Romailler Date: Wed, 21 Feb 2024 12:34:29 +0100 Subject: [PATCH 5/7] Fixing bdn tests --- sign/bdn/bdn_test.go | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/sign/bdn/bdn_test.go b/sign/bdn/bdn_test.go index 7f34d2eb6..c64c08cff 100644 --- a/sign/bdn/bdn_test.go +++ b/sign/bdn/bdn_test.go @@ -36,7 +36,7 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { mask.SetBit(1, true) mask.SetBit(2, true) - agg, err := AggregatePublicKeys(schemeOnG1, mask) + agg, err := schemeOnG1.AggregatePublicKeys(mask) require.NoError(t, err) buf, err := agg.MarshalBinary() @@ -48,62 +48,62 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { func TestBDN_AggregateSignatures(t *testing.T) { msg := []byte("Hello Boneh-Lynn-Shacham") suite := bn256.NewSuite() - private1, public1 := NewKeyPair(schemeOnG1, random.New()) - private2, public2 := NewKeyPair(schemeOnG1, random.New()) - sig1, err := Sign(schemeOnG1, private1, msg) + private1, public1 := schemeOnG1.NewKeyPair(random.New()) + private2, public2 := schemeOnG1.NewKeyPair(random.New()) + sig1, err := schemeOnG1.Sign(private1, msg) require.NoError(t, err) - sig2, err := Sign(schemeOnG1, private2, msg) + sig2, err := schemeOnG1.Sign(private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) mask.SetBit(0, true) mask.SetBit(1, true) - _, err = AggregateSignatures(schemeOnG1, [][]byte{sig1}, mask) + _, err = schemeOnG1.AggregateSignatures([][]byte{sig1}, mask) require.Error(t, err) - aggregatedSig, err := AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) + aggregatedSig, err := schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := AggregatePublicKeys(schemeOnG1, mask) + aggregatedKey, err := schemeOnG1.AggregatePublicKeys(mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = Verify(schemeOnG1, aggregatedKey, msg, sig) + err = schemeOnG1.Verify(aggregatedKey, msg, sig) require.NoError(t, err) mask.SetBit(1, false) - aggregatedKey, err = AggregatePublicKeys(schemeOnG1, mask) + aggregatedKey, err = schemeOnG1.AggregatePublicKeys(mask) - err = Verify(schemeOnG1, aggregatedKey, msg, sig) + err = schemeOnG1.Verify(aggregatedKey, msg, sig) require.Error(t, err) } func TestBDN_SubsetSignature(t *testing.T) { msg := []byte("Hello Boneh-Lynn-Shacham") suite := bn256.NewSuite() - private1, public1 := NewKeyPair(schemeOnG1, random.New()) - private2, public2 := NewKeyPair(schemeOnG1, random.New()) - _, public3 := NewKeyPair(schemeOnG1, random.New()) - sig1, err := Sign(schemeOnG1, private1, msg) + private1, public1 := schemeOnG1.NewKeyPair(random.New()) + private2, public2 := schemeOnG1.NewKeyPair(random.New()) + _, public3 := schemeOnG1.NewKeyPair(random.New()) + sig1, err := schemeOnG1.Sign(private1, msg) require.NoError(t, err) - sig2, err := Sign(schemeOnG1, private2, msg) + sig2, err := schemeOnG1.Sign(private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public3, public2}, nil) mask.SetBit(0, true) mask.SetBit(2, true) - aggregatedSig, err := AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) + aggregatedSig, err := schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := AggregatePublicKeys(schemeOnG1, mask) + aggregatedKey, err := schemeOnG1.AggregatePublicKeys(mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = Verify(schemeOnG1, aggregatedKey, msg, sig) + err = schemeOnG1.Verify(aggregatedKey, msg, sig) require.NoError(t, err) } @@ -121,7 +121,7 @@ func TestBDN_RogueAttack(t *testing.T) { pubs := []kyber.Point{public1, rogue} - sig, err := Sign(schemeOnG1, private2, msg) + sig, err := schemeOnG1.Sign(private2, msg) require.NoError(t, err) // Old scheme not resistant to the attack @@ -132,19 +132,19 @@ func TestBDN_RogueAttack(t *testing.T) { mask, _ := sign.NewMask(suite, pubs, nil) mask.SetBit(0, true) mask.SetBit(1, true) - agg, err = AggregatePublicKeys(schemeOnG1, mask) + agg, err = schemeOnG1.AggregatePublicKeys(mask) require.NoError(t, err) - require.Error(t, Verify(schemeOnG1, agg, msg, sig)) + require.Error(t, schemeOnG1.Verify(agg, msg, sig)) } func Benchmark_BDN_AggregateSigs(b *testing.B) { suite := bn256.NewSuite() - private1, public1 := NewKeyPair(schemeOnG1, random.New()) - private2, public2 := NewKeyPair(schemeOnG1, random.New()) + private1, public1 := schemeOnG1.NewKeyPair(random.New()) + private2, public2 := schemeOnG1.NewKeyPair(random.New()) msg := []byte("Hello many times Boneh-Lynn-Shacham") - sig1, err := Sign(schemeOnG1, private1, msg) + sig1, err := schemeOnG1.Sign(private1, msg) require.Nil(b, err) - sig2, err := Sign(schemeOnG1, private2, msg) + sig2, err := schemeOnG1.Sign(private2, msg) require.Nil(b, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) @@ -153,6 +153,6 @@ func Benchmark_BDN_AggregateSigs(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - AggregateSignatures(schemeOnG1, [][]byte{sig1, sig2}, mask) + schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) } } From c19eb6d48822e39e0d421044a91f552a7dca4b9c Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 6 Mar 2024 18:13:36 +0100 Subject: [PATCH 6/7] Make the BDN test suite generic over suite and scheme Signed-off-by: Jakub Sztandera --- go.mod | 2 +- go.sum | 2 + sign/bdn/bdn_test.go | 95 ++++++++++++++++++++++++++++---------------- 3 files changed, 63 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 68b66fd9b..22102505b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/drand/kyber go 1.18 require ( - github.com/drand/kyber-bls12381 v0.2.5 + github.com/drand/kyber-bls12381 v0.3.1 github.com/jonboulle/clockwork v0.3.0 github.com/stretchr/testify v1.8.2 go.dedis.ch/fixbuf v1.0.3 diff --git a/go.sum b/go.sum index 523cbc9a5..5e763fc46 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ 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= github.com/drand/kyber-bls12381 v0.2.5 h1:4ugiCmXQsvgAuylSk929rK49WGFxCxT/7ArH2vw6Tlg= github.com/drand/kyber-bls12381 v0.2.5/go.mod h1:8fm2tmRaAdYRGMTh5tjF7qrGHywC+rmM5hrUFL+9fCI= +github.com/drand/kyber-bls12381 v0.3.1 h1:KWb8l/zYTP5yrvKTgvhOrk2eNPscbMiUOIeWBnmUxGo= +github.com/drand/kyber-bls12381 v0.3.1/go.mod h1:H4y9bLPu7KZA/1efDg+jtJ7emKx+ro3PU7/jWUVt140= github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg= github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= diff --git a/sign/bdn/bdn_test.go b/sign/bdn/bdn_test.go index c64c08cff..12ac6e59d 100644 --- a/sign/bdn/bdn_test.go +++ b/sign/bdn/bdn_test.go @@ -5,20 +5,21 @@ import ( "testing" "github.com/drand/kyber" + bls12381 "github.com/drand/kyber-bls12381" + "github.com/drand/kyber/pairing" "github.com/drand/kyber/pairing/bn256" "github.com/drand/kyber/sign" - "github.com/drand/kyber/sign/bls" "github.com/drand/kyber/util/random" "github.com/stretchr/testify/require" ) -var suite = bn256.NewSuiteBn256() -var schemeOnG1 = NewSchemeOnG1(suite) -var two = suite.Scalar().Add(suite.Scalar().One(), suite.Scalar().One()) -var three = suite.Scalar().Add(two, suite.Scalar().One()) - // Reference test for other languages func TestBDN_HashPointToR_BN256(t *testing.T) { + suite := bn256.NewSuiteBn256() + schemeOnG1 := NewSchemeOnG1(suite) + two := suite.Scalar().Add(suite.Scalar().One(), suite.Scalar().One()) + three := suite.Scalar().Add(two, suite.Scalar().One()) + p1 := suite.Point().Base() p2 := suite.Point().Mul(two, suite.Point().Base()) p3 := suite.Point().Mul(three, suite.Point().Base()) @@ -45,72 +46,95 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { require.Equal(t, ref, fmt.Sprintf("%x", buf)) } -func TestBDN_AggregateSignatures(t *testing.T) { +type schemeMaker func() *Scheme + +var testsOnSchemes = []struct { + name string + test func(t *testing.T, suite pairing.Suite, scheme *Scheme) +}{ + {"aggregateSignatures", aggregateSignatures}, + {"subsetSignature", subsetSignature}, + {"rogueAttack", rogueAttack}, +} + +func TestBDN(t *testing.T) { + run := func(name string, suite pairing.Suite, schemeGen func(pairing.Suite) *Scheme) { + for _, ts := range testsOnSchemes { + t.Run(name+"/"+ts.name, func(t *testing.T) { + ts.test(t, suite, schemeGen(suite)) + }) + } + } + + run("bn256/G1", bn256.NewSuite(), NewSchemeOnG1) + //run("bn256/G2", bn256.NewSuite(), NewSchemeOnG2) // G2 does not support hash to point https://github.com/dedis/kyber/pull/428 + run("bls12/G1", bls12381.NewBLS12381Suite(), NewSchemeOnG1) + run("bls12/G2", bls12381.NewBLS12381Suite(), NewSchemeOnG2) + +} + +func aggregateSignatures(t *testing.T, suite pairing.Suite, scheme *Scheme) { msg := []byte("Hello Boneh-Lynn-Shacham") - suite := bn256.NewSuite() - private1, public1 := schemeOnG1.NewKeyPair(random.New()) - private2, public2 := schemeOnG1.NewKeyPair(random.New()) - sig1, err := schemeOnG1.Sign(private1, msg) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg) require.NoError(t, err) - sig2, err := schemeOnG1.Sign(private2, msg) + sig2, err := scheme.Sign(private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) mask.SetBit(0, true) mask.SetBit(1, true) - _, err = schemeOnG1.AggregateSignatures([][]byte{sig1}, mask) + _, err = scheme.AggregateSignatures([][]byte{sig1}, mask) require.Error(t, err) - aggregatedSig, err := schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) + aggregatedSig, err := scheme.AggregateSignatures([][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := schemeOnG1.AggregatePublicKeys(mask) + aggregatedKey, err := scheme.AggregatePublicKeys(mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = schemeOnG1.Verify(aggregatedKey, msg, sig) + err = scheme.Verify(aggregatedKey, msg, sig) require.NoError(t, err) mask.SetBit(1, false) - aggregatedKey, err = schemeOnG1.AggregatePublicKeys(mask) + aggregatedKey, err = scheme.AggregatePublicKeys(mask) - err = schemeOnG1.Verify(aggregatedKey, msg, sig) + err = scheme.Verify(aggregatedKey, msg, sig) require.Error(t, err) } -func TestBDN_SubsetSignature(t *testing.T) { +func subsetSignature(t *testing.T, suite pairing.Suite, scheme *Scheme) { msg := []byte("Hello Boneh-Lynn-Shacham") - suite := bn256.NewSuite() - private1, public1 := schemeOnG1.NewKeyPair(random.New()) - private2, public2 := schemeOnG1.NewKeyPair(random.New()) - _, public3 := schemeOnG1.NewKeyPair(random.New()) - sig1, err := schemeOnG1.Sign(private1, msg) + private1, public1 := scheme.NewKeyPair(random.New()) + private2, public2 := scheme.NewKeyPair(random.New()) + _, public3 := scheme.NewKeyPair(random.New()) + sig1, err := scheme.Sign(private1, msg) require.NoError(t, err) - sig2, err := schemeOnG1.Sign(private2, msg) + sig2, err := scheme.Sign(private2, msg) require.NoError(t, err) mask, _ := sign.NewMask(suite, []kyber.Point{public1, public3, public2}, nil) mask.SetBit(0, true) mask.SetBit(2, true) - aggregatedSig, err := schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) + aggregatedSig, err := scheme.AggregateSignatures([][]byte{sig1, sig2}, mask) require.NoError(t, err) - aggregatedKey, err := schemeOnG1.AggregatePublicKeys(mask) + aggregatedKey, err := scheme.AggregatePublicKeys(mask) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) - err = schemeOnG1.Verify(aggregatedKey, msg, sig) + err = scheme.Verify(aggregatedKey, msg, sig) require.NoError(t, err) } -func TestBDN_RogueAttack(t *testing.T) { +func rogueAttack(t *testing.T, suite pairing.Suite, scheme *Scheme) { msg := []byte("Hello Boneh-Lynn-Shacham") - suite := bn256.NewSuite() - scheme := bls.NewSchemeOnG1(suite) // honest _, public1 := scheme.NewKeyPair(random.New()) // attacker @@ -121,24 +145,25 @@ func TestBDN_RogueAttack(t *testing.T) { pubs := []kyber.Point{public1, rogue} - sig, err := schemeOnG1.Sign(private2, msg) + sig, err := scheme.Sign(private2, msg) require.NoError(t, err) // Old scheme not resistant to the attack - agg := scheme.AggregatePublicKeys(pubs...) + agg := scheme.blsScheme.AggregatePublicKeys(pubs...) require.NoError(t, scheme.Verify(agg, msg, sig)) // New scheme that should detect mask, _ := sign.NewMask(suite, pubs, nil) mask.SetBit(0, true) mask.SetBit(1, true) - agg, err = schemeOnG1.AggregatePublicKeys(mask) + agg, err = scheme.AggregatePublicKeys(mask) require.NoError(t, err) - require.Error(t, schemeOnG1.Verify(agg, msg, sig)) + require.Error(t, scheme.Verify(agg, msg, sig)) } func Benchmark_BDN_AggregateSigs(b *testing.B) { suite := bn256.NewSuite() + schemeOnG1 := NewSchemeOnG1(suite) private1, public1 := schemeOnG1.NewKeyPair(random.New()) private2, public2 := schemeOnG1.NewKeyPair(random.New()) msg := []byte("Hello many times Boneh-Lynn-Shacham") From 3f089190ab9f0ed7685296bfee532b4e89ef7847 Mon Sep 17 00:00:00 2001 From: Yolan Romailler Date: Fri, 8 Mar 2024 23:43:14 +0100 Subject: [PATCH 7/7] Keeping public APIs from v1 --- sign/bdn/bdn.go | 40 ++++++++++++++++++++++++++++++++++++++++ sign/bdn/bdn_test.go | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/sign/bdn/bdn.go b/sign/bdn/bdn.go index d7a59c639..4b1ab1b9c 100644 --- a/sign/bdn/bdn.go +++ b/sign/bdn/bdn.go @@ -188,3 +188,43 @@ func (scheme *Scheme) AggregatePublicKeys(mask *sign.Mask) (kyber.Point, error) return agg, nil } + +// v1 API Deprecated ---------------------------------- + +// NewKeyPair creates a new BLS signing key pair. The private key x is a scalar +// and the public key X is a point on curve G2. +// Deprecated: use the new scheme methods instead. +func NewKeyPair(suite pairing.Suite, random cipher.Stream) (kyber.Scalar, kyber.Point) { + return NewSchemeOnG1(suite).NewKeyPair(random) +} + +// Sign creates a BLS signature S = x * H(m) on a message m using the private +// key x. The signature S is a point on curve G1. +// Deprecated: use the new scheme methods instead. +func Sign(suite pairing.Suite, x kyber.Scalar, msg []byte) ([]byte, error) { + return NewSchemeOnG1(suite).Sign(x, msg) +} + +// Verify checks the given BLS signature S on the message m using the public +// key X by verifying that the equality e(H(m), X) == e(H(m), x*B2) == +// e(x*H(m), B2) == e(S, B2) holds where e is the pairing operation and B2 is +// the base point from curve G2. +// Deprecated: use the new scheme methods instead. +func Verify(suite pairing.Suite, x kyber.Point, msg, sig []byte) error { + return NewSchemeOnG1(suite).Verify(x, msg, sig) +} + +// AggregateSignatures aggregates the signatures using a coefficient for each +// one of them where c = H(pk) and H: G2 -> R with R = {1, ..., 2^128} +// Deprecated: use the new scheme methods instead. +func AggregateSignatures(suite pairing.Suite, sigs [][]byte, mask *sign.Mask) (kyber.Point, error) { + return NewSchemeOnG1(suite).AggregateSignatures(sigs, mask) +} + +// AggregatePublicKeys aggregates a set of public keys (similarly to +// AggregateSignatures for signatures) using the hash function +// H: G2 -> R with R = {1, ..., 2^128}. +// Deprecated: use the new scheme methods instead. +func AggregatePublicKeys(suite pairing.Suite, mask *sign.Mask) (kyber.Point, error) { + return NewSchemeOnG1(suite).AggregatePublicKeys(mask) +} diff --git a/sign/bdn/bdn_test.go b/sign/bdn/bdn_test.go index 12ac6e59d..db80d4706 100644 --- a/sign/bdn/bdn_test.go +++ b/sign/bdn/bdn_test.go @@ -46,8 +46,6 @@ func TestBDN_HashPointToR_BN256(t *testing.T) { require.Equal(t, ref, fmt.Sprintf("%x", buf)) } -type schemeMaker func() *Scheme - var testsOnSchemes = []struct { name string test func(t *testing.T, suite pairing.Suite, scheme *Scheme) @@ -93,6 +91,7 @@ func aggregateSignatures(t *testing.T, suite pairing.Suite, scheme *Scheme) { require.NoError(t, err) aggregatedKey, err := scheme.AggregatePublicKeys(mask) + require.NoError(t, err) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) @@ -102,6 +101,7 @@ func aggregateSignatures(t *testing.T, suite pairing.Suite, scheme *Scheme) { mask.SetBit(1, false) aggregatedKey, err = scheme.AggregatePublicKeys(mask) + require.NoError(t, err) err = scheme.Verify(aggregatedKey, msg, sig) require.Error(t, err) @@ -125,6 +125,7 @@ func subsetSignature(t *testing.T, suite pairing.Suite, scheme *Scheme) { require.NoError(t, err) aggregatedKey, err := scheme.AggregatePublicKeys(mask) + require.NoError(t, err) sig, err := aggregatedSig.MarshalBinary() require.NoError(t, err) @@ -181,3 +182,40 @@ func Benchmark_BDN_AggregateSigs(b *testing.B) { schemeOnG1.AggregateSignatures([][]byte{sig1, sig2}, mask) } } + +func TestBDNDeprecatedAPIs(t *testing.T) { + msg := []byte("Hello Boneh-Lynn-Shacham") + suite := bn256.NewSuite() + private1, public1 := NewKeyPair(suite, random.New()) + private2, public2 := NewKeyPair(suite, random.New()) + sig1, err := Sign(suite, private1, msg) + require.NoError(t, err) + sig2, err := Sign(suite, private2, msg) + require.NoError(t, err) + + mask, _ := sign.NewMask(suite, []kyber.Point{public1, public2}, nil) + mask.SetBit(0, true) + mask.SetBit(1, true) + + _, err = AggregateSignatures(suite, [][]byte{sig1}, mask) + require.Error(t, err) + + aggregatedSig, err := AggregateSignatures(suite, [][]byte{sig1, sig2}, mask) + require.NoError(t, err) + + aggregatedKey, err := AggregatePublicKeys(suite, mask) + require.NoError(t, err) + + sig, err := aggregatedSig.MarshalBinary() + require.NoError(t, err) + + err = Verify(suite, aggregatedKey, msg, sig) + require.NoError(t, err) + + mask.SetBit(1, false) + aggregatedKey, err = AggregatePublicKeys(suite, mask) + require.NoError(t, err) + + err = Verify(suite, aggregatedKey, msg, sig) + require.Error(t, err) +}