Skip to content

Commit

Permalink
Merge pull request #4 from corestario/1-eth2-compatibility
Browse files Browse the repository at this point in the history
1 eth2 compatibility
  • Loading branch information
zavgorodnii authored Oct 5, 2020
2 parents 159b9e4 + c6ac2f8 commit c266752
Show file tree
Hide file tree
Showing 10 changed files with 1,002 additions and 25 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module github.com/corestario/kyber

require (
github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391
github.com/stretchr/testify v1.3.0
go.dedis.ch/fixbuf v1.0.3
go.dedis.ch/protobuf v1.0.11
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339
)

go 1.12
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ github.com/corestario/kyber v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDT
github.com/corestario/kyber v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg=
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/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 h1:51kHw7l/dUDdOdW06AlUGT5jnpj6nqQSILebcsikSjA=
github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand All @@ -22,3 +25,5 @@ golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339 h1:zSqWKgm/o7HAnlAzBQ+aetp9fpuyytsXnKA8eiLHYQM=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
316 changes: 316 additions & 0 deletions pairing/bls12381/bls_groups_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
package bls12381

import (
"bytes"
"crypto/cipher"
"testing"

"github.com/corestario/kyber"
"github.com/corestario/kyber/util/random"
"github.com/stretchr/testify/require"
)

// Code extracted from kyber/utils/test
// TODO: expose API in forked drand/kyber
// Apply a generic set of validation tests to a cryptographic Group,
// using a given source of [pseudo-]randomness.
//
// Returns a log of the pseudorandom Points produced in the test,
// for comparison across alternative implementations
// that are supposed to be equivalent.
func testGroup(t *testing.T, g kyber.Group, rand cipher.Stream) []kyber.Point {
t.Logf("\nTesting group '%s': %d-byte Point, %d-byte Scalar\n",
g.String(), g.PointLen(), g.ScalarLen())

points := make([]kyber.Point, 0)
ptmp := g.Point()
stmp := g.Scalar()
pzero := g.Point().Null()
szero := g.Scalar().Zero()
sone := g.Scalar().One()

// Do a simple Diffie-Hellman test
s1 := g.Scalar().Pick(rand)
s2 := g.Scalar().Pick(rand)
if s1.Equal(szero) {
t.Fatalf("first secret is scalar zero %v", s1)
}
if s2.Equal(szero) {
t.Fatalf("second secret is scalar zero %v", s2)
}
if s1.Equal(s2) {
t.Fatalf("not getting unique secrets: picked %s twice", s1)
}

gen := g.Point().Base()
points = append(points, gen)

// Sanity-check relationship between addition and multiplication
p1 := g.Point().Add(gen, gen)
p2 := g.Point().Mul(stmp.SetInt64(2), nil)
if !p1.Equal(p2) {
t.Fatalf("multiply by two doesn't work: %v == %v (+) %[2]v != %[2]v (x) 2 == %v", p1, gen, p2)
}
p1.Add(p1, p1)
p2.Mul(stmp.SetInt64(4), nil)
if !p1.Equal(p2) {
t.Fatalf("multiply by four doesn't work: %v (+) %[1]v != %v (x) 4 == %v",
g.Point().Add(gen, gen), gen, p2)
}
points = append(points, p1)

// Find out if this curve has a prime order:
// if the curve does not offer a method IsPrimeOrder,
// then assume that it is.
type canCheckPrimeOrder interface {
IsPrimeOrder() bool
}
primeOrder := true
if gpo, ok := g.(canCheckPrimeOrder); ok {
primeOrder = gpo.IsPrimeOrder()
}

// Verify additive and multiplicative identities of the generator.
ptmp.Mul(stmp.SetInt64(-1), nil).Add(ptmp, gen)
if !ptmp.Equal(pzero) {
t.Fatalf("generator additive identity doesn't work: (scalar -1 %v) %v (x) -1 (+) %v = %v != %v the group point identity",
stmp.SetInt64(-1), ptmp.Mul(stmp.SetInt64(-1), nil), gen, ptmp.Mul(stmp.SetInt64(-1), nil).Add(ptmp, gen), pzero)
}
// secret.Inv works only in prime-order groups
if primeOrder {
ptmp.Mul(stmp.SetInt64(2), nil).Mul(stmp.Inv(stmp), ptmp)
if !ptmp.Equal(gen) {
t.Fatalf("generator multiplicative identity doesn't work:\n%v (x) %v = %v\n%[3]v (x) %v = %v",
ptmp.Base().String(), stmp.SetInt64(2).String(),
ptmp.Mul(stmp.SetInt64(2), nil).String(),
stmp.Inv(stmp).String(),
ptmp.Mul(stmp.SetInt64(2), nil).Mul(stmp.Inv(stmp), ptmp).String())
}
}

p1.Mul(s1, gen)
p2.Mul(s2, gen)
if p1.Equal(p2) {
t.Fatalf("encryption isn't producing unique points: %v (x) %v == %v (x) %[2]v == %[4]v", s1, gen, s2, p1)
}
points = append(points, p1)

dh1 := g.Point().Mul(s2, p1)
dh2 := g.Point().Mul(s1, p2)
if !dh1.Equal(dh2) {
t.Fatalf("Diffie-Hellman didn't work: %v == %v (x) %v != %v (x) %v == %v", dh1, s2, p1, s1, p2, dh2)
}
points = append(points, dh1)

// Test secret inverse to get from dh1 back to p1
if primeOrder {
ptmp.Mul(g.Scalar().Inv(s2), dh1)
if !ptmp.Equal(p1) {
t.Fatalf("Scalar inverse didn't work: %v != (-)%v (x) %v == %v", p1, s2, dh1, ptmp)
}
}

// Zero and One identity secrets
if !ptmp.Mul(szero, dh1).Equal(pzero) {
t.Fatalf("Encryption with secret=0 didn't work: %v (x) %v == %v != %v", szero, dh1, ptmp, pzero)
}
if !ptmp.Mul(sone, dh1).Equal(dh1) {
t.Fatalf("Encryption with secret=1 didn't work: %v (x) %v == %v != %[2]v", sone, dh1, ptmp)
}

// Additive homomorphic identities
ptmp.Add(p1, p2)
stmp.Add(s1, s2)
pt2 := g.Point().Mul(stmp, gen)
if !pt2.Equal(ptmp) {
t.Fatalf("Additive homomorphism doesn't work: %v + %v == %v, %[3]v (x) %v == %v != %v == %v (+) %v",
s1, s2, stmp, gen, pt2, ptmp, p1, p2)
}
ptmp.Sub(p1, p2)
stmp.Sub(s1, s2)
pt2.Mul(stmp, gen)
if !pt2.Equal(ptmp) {
t.Fatalf("Additive homomorphism doesn't work: %v - %v == %v, %[3]v (x) %v == %v != %v == %v (-) %v",
s1, s2, stmp, gen, pt2, ptmp, p1, p2)
}
st2 := g.Scalar().Neg(s2)
st2.Add(s1, st2)
if !stmp.Equal(st2) {
t.Fatalf("Scalar.Neg doesn't work: -%v == %v, %[2]v + %v == %v != %v",
s2, g.Scalar().Neg(s2), s1, st2, stmp)
}
pt2.Neg(p2).Add(pt2, p1)
if !pt2.Equal(ptmp) {
t.Fatalf("Point.Neg doesn't work: (-)%v == %v, %[2]v (+) %v == %v != %v",
p2, g.Point().Neg(p2), p1, pt2, ptmp)
}

// Multiplicative homomorphic identities
stmp.Mul(s1, s2)
if !ptmp.Mul(stmp, gen).Equal(dh1) {
t.Fatalf("Multiplicative homomorphism doesn't work: %v * %v == %v, %[2]v (x) %v == %v != %v",
s1, s2, stmp, gen, ptmp, dh1)
}
if primeOrder {
st2.Inv(s2)
st2.Mul(st2, stmp)
if !st2.Equal(s1) {
t.Fatalf("Scalar division doesn't work: %v^-1 * %v == %v * %[2]v == %[4]v != %v",
s2, stmp, g.Scalar().Inv(s2), st2, s1)
}
st2.Div(stmp, s2)
if !st2.Equal(s1) {
t.Fatalf("Scalar division doesn't work: %v / %v == %v != %v",
stmp, s2, st2, s1)
}
}

// Test randomly picked points
last := gen
for i := 0; i < 5; i++ {
rgen := g.Point().Pick(rand)
if rgen.Equal(last) {
t.Fatalf("Pick() not producing unique points: got %v twice", rgen)
}
last = rgen

ptmp.Mul(stmp.SetInt64(-1), rgen).Add(ptmp, rgen)
if !ptmp.Equal(pzero) {
t.Fatalf("random generator fails additive identity: %v (x) %v == %v, %v (+) %[3]v == %[5]v != %v",
g.Scalar().SetInt64(-1), rgen, g.Point().Mul(g.Scalar().SetInt64(-1), rgen),
rgen, g.Point().Mul(g.Scalar().SetInt64(-1), rgen), pzero)
}
if primeOrder {
ptmp.Mul(stmp.SetInt64(2), rgen).Mul(stmp.Inv(stmp), ptmp)
if !ptmp.Equal(rgen) {
t.Fatalf("random generator fails multiplicative identity: %v (x) (2 (x) %v) == %v != %[2]v",
stmp, rgen, ptmp)
}
}
points = append(points, rgen)
}

// Test encoding and decoding
buf := new(bytes.Buffer)
for i := 0; i < 5; i++ {
buf.Reset()
s := g.Scalar().Pick(rand)
if _, err := s.MarshalTo(buf); err != nil {
t.Fatalf("encoding of secret fails: " + err.Error())
}
if _, err := stmp.UnmarshalFrom(buf); err != nil {
t.Fatalf("decoding of secret fails: " + err.Error())
}
if !stmp.Equal(s) {
t.Fatalf("decoding produces different secret than encoded")
}

buf.Reset()
p := g.Point().Pick(rand)
if _, err := p.MarshalTo(buf); err != nil {
t.Fatalf("encoding of point fails: " + err.Error())
}
if _, err := ptmp.UnmarshalFrom(buf); err != nil {
t.Fatalf("decoding of point fails: " + err.Error())
}

if !ptmp.Equal(p) {
t.Fatalf("decoding produces different point than encoded")
}
}

// Test that we can marshal/ unmarshal null point
pzero = g.Point().Null()
b, _ := pzero.MarshalBinary()
repzero := g.Point()
err := repzero.UnmarshalBinary(b)
if err != nil {
t.Fatalf("Could not unmarshall binary %v: %v", b, err)
}

return points
}

// GroupTest applies a generic set of validation tests to a cryptographic Group.
func GroupTest(t *testing.T, g kyber.Group) {
testGroup(t, g, random.New())
}

func TestKyberG1(t *testing.T) {
GroupTest(t, NewGroupG1())
}

func TestKyberG2(t *testing.T) {
GroupTest(t, NewGroupG2())
}

func TestKyberGT(t *testing.T) {
GroupTest(t, NewGroupGT())
}

func TestKyberPairingG2(t *testing.T) {
s := NewBLS12381Suite().(*Suite)
a := s.G1().Scalar().Pick(s.RandomStream())
b := s.G2().Scalar().Pick(s.RandomStream())
aG := s.G1().Point().Mul(a, nil)
bH := s.G2().Point().Mul(b, nil)
ab := s.G1().Scalar().Mul(a, b)
abG := s.G1().Point().Mul(ab, nil)
// e(aG, bG) = e(G,H)^(ab)
p1 := s.Pair(aG, bH)
// e((ab)G,H) = e(G,H)^(ab)
p2 := s.Pair(abG, s.G2().Point().Base())
require.True(t, p1.Equal(p2))
require.True(t, s.ValidatePairing(aG, bH, abG.Clone(), s.G2().Point().Base()))

pRandom := s.Pair(aG, s.G2().Point().Pick(s.RandomStream()))
require.False(t, p1.Equal(pRandom))
pRandom = s.Pair(s.G1().Point().Pick(s.RandomStream()), bH)
require.False(t, p1.Equal(pRandom))
}

func BenchmarkPairingSeparate(bb *testing.B) {
s := NewBLS12381Suite().(*Suite)
a := s.G1().Scalar().Pick(s.RandomStream())
b := s.G2().Scalar().Pick(s.RandomStream())
aG := s.G1().Point().Mul(a, nil)
bH := s.G2().Point().Mul(b, nil)
ab := s.G1().Scalar().Mul(a, b)
abG := s.G1().Point().Mul(ab, nil)
bb.ResetTimer()
for i := 0; i < bb.N; i++ {

// e(aG, bG) = e(G,H)^(ab)
p1 := s.Pair(aG, bH)
// e((ab)G,H) = e(G,H)^(ab)
p2 := s.Pair(abG, s.G2().Point().Base())
if !p1.Equal(p2) {
panic("aie")
}
}
}

func BenchmarkPairingInv(bb *testing.B) {
s := NewBLS12381Suite().(*Suite)
a := s.G1().Scalar().Pick(s.RandomStream())
b := s.G2().Scalar().Pick(s.RandomStream())
aG := s.G1().Point().Mul(a, nil)
bH := s.G2().Point().Mul(b, nil)
ab := s.G1().Scalar().Mul(a, b)
abG := s.G1().Point().Mul(ab, nil)
bb.ResetTimer()
for i := 0; i < bb.N; i++ {
if !s.ValidatePairing(aG, bH, abG.Clone(), s.G2().Point().Base()) {
panic("aie")
}
}
}

func TestIsValidGroup(t *testing.T) {
suite := NewBLS12381Suite()
p1 := suite.G1().Point().Pick(random.New())
p2 := suite.G1().Point().Pick(random.New())

require.True(t, p1.(GroupChecker).IsInCorrectGroup())
require.True(t, p2.(GroupChecker).IsInCorrectGroup())
}
Loading

0 comments on commit c266752

Please sign in to comment.