Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the group-specific scalar type when hashing in BDN #553

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions sign/bdn/bdn.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,20 @@ import (
"crypto/cipher"
"errors"
"fmt"
"math/big"
"slices"

"go.dedis.ch/kyber/v4"
"go.dedis.ch/kyber/v4/group/mod"
"go.dedis.ch/kyber/v4/pairing"
"go.dedis.ch/kyber/v4/sign"
"go.dedis.ch/kyber/v4/sign/bls"
"golang.org/x/crypto/blake2s"
)

// modulus128 can be provided to the big integer implementation to create numbers
// over 128 bits
var modulus128 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1))

// For the choice of H, we're mostly worried about the second preimage attack. In
// other words, find m' where H(m) == H(m')
// We also use the entire roster so that the coefficient will vary for the same
// public key used in different roster
func hashPointToR(pubs []kyber.Point) ([]kyber.Scalar, error) {
func hashPointToR(group kyber.Group, pubs []kyber.Point) ([]kyber.Scalar, error) {
h, err := blake2s.NewXOF(blake2s.OutputLengthUnknown, nil)
if err != nil {
return nil, err
Expand All @@ -55,7 +50,13 @@ func hashPointToR(pubs []kyber.Point) ([]kyber.Scalar, error) {

coefs := make([]kyber.Scalar, len(pubs))
for i := range coefs {
coefs[i] = mod.NewIntBytes(out[i*16:(i+1)*16], modulus128, kyber.LittleEndian)
scalar := group.Scalar()
bytes := out[i*16 : (i+1)*16]
if scalar.ByteOrder() != kyber.LittleEndian {
slices.Reverse(bytes)
}
scalar.SetBytes(bytes)
coefs[i] = scalar
}

return coefs, nil
Expand Down
22 changes: 8 additions & 14 deletions sign/bdn/bdn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ func TestBDN_HashPointToR_BN256(t *testing.T) {
p2 := suite.Point().Mul(two, suite.Point().Base())
p3 := suite.Point().Mul(three, suite.Point().Base())

coefs, err := hashPointToR([]kyber.Point{p1, p2, p3})
coefs, err := hashPointToR(suite, []kyber.Point{p1, p2, p3})

require.NoError(t, err)
require.Equal(t, "35b5b395f58aba3b192fb7e1e5f2abd3", coefs[0].String())
require.Equal(t, "14dcc79d46b09b93075266e47cd4b19e", coefs[1].String())
require.Equal(t, "933f6013eb3f654f9489d6d45ad04eaf", coefs[2].String())
require.Equal(t, 16, coefs[0].MarshalSize())

mask, _ := NewMask([]kyber.Point{p1, p2, p3}, nil)
mask, _ := NewMask(suite, []kyber.Point{p1, p2, p3}, nil)
mask.SetBit(0, true)
mask.SetBit(1, true)
mask.SetBit(2, true)
Expand All @@ -48,15 +47,14 @@ 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)
require.NoError(t, err)
sig2, err := Sign(suite, private2, msg)
require.NoError(t, err)

mask, _ := NewMask([]kyber.Point{public1, public2}, nil)
mask, _ := NewMask(suite, []kyber.Point{public1, public2}, nil)
mask.SetBit(0, true)
mask.SetBit(1, true)

Expand Down Expand Up @@ -85,7 +83,6 @@ func TestBDN_AggregateSignatures(t *testing.T) {

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())
Expand All @@ -94,7 +91,7 @@ func TestBDN_SubsetSignature(t *testing.T) {
sig2, err := Sign(suite, private2, msg)
require.NoError(t, err)

mask, _ := NewMask([]kyber.Point{public1, public3, public2}, nil)
mask, _ := NewMask(suite, []kyber.Point{public1, public3, public2}, nil)
mask.SetBit(0, true)
mask.SetBit(2, true)

Expand All @@ -113,7 +110,6 @@ func TestBDN_SubsetSignature(t *testing.T) {

func TestBDN_RogueAttack(t *testing.T) {
msg := []byte("Hello Boneh-Lynn-Shacham")
suite := bn256.NewSuite()
scheme := bls.NewSchemeOnG1(suite)
// honest
_, public1 := scheme.NewKeyPair(random.New())
Expand All @@ -133,7 +129,7 @@ func TestBDN_RogueAttack(t *testing.T) {
require.NoError(t, scheme.Verify(agg, msg, sig))

// New scheme that should detect
mask, _ := NewMask(pubs, nil)
mask, _ := NewMask(suite, pubs, nil)
mask.SetBit(0, true)
mask.SetBit(1, true)
agg, err = AggregatePublicKeys(suite, mask)
Expand All @@ -142,7 +138,6 @@ func TestBDN_RogueAttack(t *testing.T) {
}

func Benchmark_BDN_AggregateSigs(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")
Expand All @@ -151,7 +146,7 @@ func Benchmark_BDN_AggregateSigs(b *testing.B) {
sig2, err := Sign(suite, private2, msg)
require.Nil(b, err)

mask, _ := NewMask([]kyber.Point{public1, public2}, nil)
mask, _ := NewMask(suite, []kyber.Point{public1, public2}, nil)
mask.SetBit(0, true)
mask.SetBit(1, false)

Expand All @@ -172,7 +167,7 @@ func Benchmark_BDN_BLS12381_AggregateVerify(b *testing.B) {
privKeys[i], pubKeys[i] = schemeOnG2.NewKeyPair(rng)
}

mask, err := NewMask(pubKeys, nil)
mask, err := NewMask(suite.G1(), pubKeys, nil)
require.NoError(b, err)
for i := range pubKeys {
require.NoError(b, mask.SetBit(i, true))
Expand Down Expand Up @@ -210,7 +205,6 @@ func unmarshalHex[T encoding.BinaryUnmarshaler](t *testing.T, into T, s string)
// This tests exists to make sure we don't accidentally make breaking changes to signature
// aggregation by using checking against known aggregated signatures and keys.
func TestBDNFixtures(t *testing.T) {
suite := bn256.NewSuite()
schemeOnG1 := NewSchemeOnG1(suite)

public1 := unmarshalHex(t, suite.G2().Point(), "1a30714035c7a161e286e54c191b8c68345bd8239c74925a26290e8e1ae97ed6657958a17dca12c943fadceb11b824402389ff427179e0f10194da3c1b771c6083797d2b5915ea78123cbdb99ea6389d6d6b67dcb512a2b552c373094ee5693524e3ebb4a176f7efa7285c25c80081d8cb598745978f1a63b886c09a316b1493")
Expand Down Expand Up @@ -243,7 +237,7 @@ func TestBDNFixtures(t *testing.T) {
require.Nil(t, err)
require.Equal(t, sig3Exp, sig3)

mask, _ := NewMask([]kyber.Point{public1, public2, public3}, nil)
mask, _ := NewMask(suite, []kyber.Point{public1, public2, public3}, nil)
mask.SetBit(0, true)
mask.SetBit(1, false)
mask.SetBit(2, true)
Expand Down
4 changes: 2 additions & 2 deletions sign/bdn/mask.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Mask struct {
// The returned Mask will contain pre-computed terms and coefficients for all provided public
// keys, so it should be re-used for optimal performance (e.g., by creating a "base" mask and
// cloning it whenever aggregating signatures and/or public keys).
func NewMask(publics []kyber.Point, myKey kyber.Point) (*Mask, error) {
func NewMask(group kyber.Group, publics []kyber.Point, myKey kyber.Point) (*Mask, error) {
m := &Mask{
publics: publics,
}
Expand All @@ -49,7 +49,7 @@ func NewMask(publics []kyber.Point, myKey kyber.Point) (*Mask, error) {
}

var err error
m.publicCoefs, err = hashPointToR(publics)
m.publicCoefs, err = hashPointToR(group, publics)
if err != nil {
return nil, fmt.Errorf("failed to hash public keys: %w", err)
}
Expand Down
12 changes: 6 additions & 6 deletions sign/bdn/mask_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func init() {
}

func TestMask_CreateMask(t *testing.T) {
mask, err := NewMask(publics, nil)
mask, err := NewMask(suite, publics, nil)
require.NoError(t, err)

require.Equal(t, len(publics), len(mask.Publics()))
Expand All @@ -32,19 +32,19 @@ func TestMask_CreateMask(t *testing.T) {
require.Equal(t, n/8+1, mask.Len())
require.Equal(t, uint8(0), mask.Mask()[0])

mask, err = NewMask(publics, publics[2])
mask, err = NewMask(suite, publics, publics[2])
require.NoError(t, err)

require.Equal(t, len(publics), len(mask.Publics()))
require.Equal(t, 1, mask.CountEnabled())
require.Equal(t, uint8(0x4), mask.Mask()[0])

_, err = NewMask(publics, suite.G1().Point())
_, err = NewMask(suite, publics, suite.G1().Point())
require.Error(t, err)
}

func TestMask_SetBit(t *testing.T) {
mask, err := NewMask(publics, publics[2])
mask, err := NewMask(suite, publics, publics[2])
require.NoError(t, err)

// Make sure the mask is initially as we'd expect.
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestMask_SetBit(t *testing.T) {
}

func TestMask_SetAndMerge(t *testing.T) {
mask, err := NewMask(publics, publics[2])
mask, err := NewMask(suite, publics, publics[2])
require.NoError(t, err)

err = mask.SetMask([]byte{})
Expand All @@ -129,7 +129,7 @@ func TestMask_SetAndMerge(t *testing.T) {
}

func TestMask_PositionalQueries(t *testing.T) {
mask, err := NewMask(publics, publics[2])
mask, err := NewMask(suite, publics, publics[2])
require.NoError(t, err)

for i := 0; i < 10000; i++ {
Expand Down
Loading