Skip to content

Commit

Permalink
Bls12381 (#505)
Browse files Browse the repository at this point in the history
* Added circl and kilic implementation of bls12381 + benchmarks
* Added deserialization tests compressed vectors +more comments
* Fix IBE in the drand merge (#514)
* Add ByteOrder() function + constant from int.go
* Update circl_bls12381 and edwards25519 scalars
* Add Order() to the scalar interface
* Adapt IBE to make it general
* Fix dkg bug (#515)
* BugFix: use array index instead of node index
* Fix endianess bool
* Add tests for endianess
* Fixed deserialization tests + circl issue
* Removed groupchecker iface
* Added back circl deserialization test (cloudflare/circl#499)
* Since Go 1.21 go mod tidy require the go directive to match the highest of our dependencies

---------

Co-authored-by: Kilian <79536516+K1li4nL@users.noreply.github.com>
Co-authored-by: Yolan Romailler <anomalroil@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 13, 2024
1 parent 4485f5d commit ae87c6b
Show file tree
Hide file tree
Showing 66 changed files with 1,947 additions and 555 deletions.
13 changes: 3 additions & 10 deletions encrypt/ibe/ibe.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package ibe

/*
import (
"bytes"
"crypto/rand"
Expand All @@ -10,7 +8,6 @@ import (
"fmt"

"go.dedis.ch/kyber/v4"
"go.dedis.ch/kyber/v4/group/mod"
"go.dedis.ch/kyber/v4/pairing"
"go.dedis.ch/kyber/v4/util/random"
)
Expand Down Expand Up @@ -243,12 +240,9 @@ func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) {
// we hash it a first time: buffer = hash("IBE-H3" || sigma || msg)
buffer := h.Sum(nil)

hashable, ok := s.G1().Scalar().(*mod.Int)
if !ok {
return nil, fmt.Errorf("unable to instantiate scalar as a mod.Int")
}
hashable := s.G1().Scalar()
canonicalBitLen := hashable.MarshalSize() * 8
actualBitLen := hashable.M.BitLen()
actualBitLen := hashable.GroupOrder().BitLen()
toMask := canonicalBitLen - actualBitLen

for i := uint16(1); i < 65535; i++ {
Expand All @@ -263,7 +257,7 @@ func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) {
// We then apply masking to our resulting bytes at the bit level
// but we assume that toMask is a few bits, at most 8.
// For instance when using BLS12-381 toMask == 1.
if hashable.BO == mod.BigEndian {
if hashable.ByteOrder() == kyber.BigEndian {
hashed[0] = hashed[0] >> toMask
} else {
hashed[len(hashed)-1] = hashed[len(hashed)-1] >> toMask
Expand Down Expand Up @@ -399,4 +393,3 @@ func DecryptCPAonG1(s pairing.Suite, private kyber.Point, c *CiphertextCPA) ([]b
}
return xor(c.C, hGidT), nil
}
*/
11 changes: 4 additions & 7 deletions encrypt/ibe/ibe_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package ibe

/*
import (
"encoding/hex"
"strings"
Expand All @@ -10,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"go.dedis.ch/kyber/v4"
"go.dedis.ch/kyber/v4/pairing"
bls "go.dedis.ch/kyber/v4/pairing/circl_bls12381"
circl "go.dedis.ch/kyber/v4/pairing/bls12381/circl"
"go.dedis.ch/kyber/v4/util/random"
)

Expand All @@ -23,7 +21,7 @@ func newSetting(i uint) (
panic("invalid test")
}
if i == 1 {
suite := bls.NewSuiteBLS12381()
suite := circl.NewSuiteBLS12381()
P := suite.G1().Point().Base()
s := suite.G1().Scalar().Pick(random.New())
Ppub := suite.G1().Point().Mul(s, P)
Expand All @@ -35,7 +33,7 @@ func newSetting(i uint) (
return suite, Ppub, ID, sQid, EncryptCCAonG1, DecryptCCAonG1
}
// i == 2
suite := bls.NewSuiteBLS12381()
suite := circl.NewSuiteBLS12381()
P := suite.G2().Point().Base()
s := suite.G2().Scalar().Pick(random.New())
Ppub := suite.G2().Point().Mul(s, P)
Expand Down Expand Up @@ -246,7 +244,7 @@ func TestBackwardsInteropWithTypescript(t *testing.T) {
}

func TestCPAEncryptOnG1(t *testing.T) {
suite := bls.NewSuiteBLS12381()
suite := circl.NewSuiteBLS12381()
P := suite.G1().Point().Pick(random.New())
s := suite.G1().Scalar().Pick(random.New())
Ppub := suite.G1().Point().Mul(s, P)
Expand All @@ -261,4 +259,3 @@ func TestCPAEncryptOnG1(t *testing.T) {
require.NoError(t, err)
require.Equal(t, msg, msg2)
}
*/
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
module go.dedis.ch/kyber/v4

go 1.20
go 1.21

require (
github.com/cloudflare/circl v1.3.7
github.com/cloudflare/circl v1.3.9
github.com/consensys/gnark-crypto v0.12.1
github.com/jonboulle/clockwork v0.4.0
github.com/kilic/bls12-381 v0.1.0
github.com/stretchr/testify v1.9.0
go.dedis.ch/fixbuf v1.0.3
go.dedis.ch/protobuf v1.0.11
golang.org/x/crypto v0.21.0
golang.org/x/sys v0.18.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand All @@ -21,6 +23,5 @@ require (
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
Expand All @@ -13,10 +13,14 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
Expand All @@ -41,10 +45,12 @@ golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
Expand Down
39 changes: 28 additions & 11 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ package kyber

import (
"crypto/cipher"
"math/big"
)

// ByteOrder denotes the endianness of the operation.
type ByteOrder bool

const (
// LittleEndian endianness
LittleEndian ByteOrder = true
// BigEndian endianness
BigEndian ByteOrder = false
)

// Scalar represents a scalar value by which
Expand Down Expand Up @@ -56,6 +67,12 @@ type Scalar interface {
// The endianess of the byte-slice is determined by the
// implementation.
SetBytes([]byte) Scalar

// ByteOrder return the byte representation type (big or little endian)
ByteOrder() ByteOrder

// GroupOrder returns the order of the underlying group
GroupOrder() *big.Int
}

// Point represents an element of a public-key cryptographic Group.
Expand Down Expand Up @@ -112,17 +129,6 @@ type Point interface {
Mul(s Scalar, p Point) Point
}

// SubGroupElement allows to verify if a Point is in the correct group or not.
// For curves which don't have a prime order, we need to only consider the
// points lying in the subgroup of prime order. That check returns true if the
// point is correct or not. If the curve forms already a prime order// group,
// then this method should be implemented as a nop returning true, to be able to
// use the Schnorr signature scheme for example.
type SubGroupElement interface {
Point
IsInCorrectGroup() bool
}

// AllowsVarTime allows callers to determine if a given kyber.Scalar
// or kyber.Point supports opting-in to variable time operations. If
// an object implements AllowsVarTime, then the caller can use
Expand Down Expand Up @@ -174,3 +180,14 @@ type Group interface {
PointLen() int // Max length of point in bytes
Point() Point // Create new point
}

// SubGroupElement allows to verify if a Point is in the correct group or not.
// For curves which don't have a prime order, we need to only consider the
// points lying in the subgroup of prime order. That check returns true if the
// point is correct or not. If the curve forms already a prime order// group,
// then this method should be implemented as a nop returning true, to be able to
// use the Schnorr signature scheme for example.
type SubGroupElement interface {
Point
IsInCorrectGroup() bool
}
15 changes: 13 additions & 2 deletions group/edwards25519/scalar.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
// The scalars are GF(2^252 + 27742317777372353535851937790883648493).

var marshalScalarID = [8]byte{'e', 'd', '.', 's', 'c', 'a', 'l', 'a'}
var defaultEndianess = kyber.LittleEndian

type scalar struct {
v [32]byte
Expand Down Expand Up @@ -60,7 +61,7 @@ func (s *scalar) SetInt64(v int64) kyber.Scalar {
}

func (s *scalar) toInt() *mod.Int {
return mod.NewIntBytes(s.v[:], primeOrder, mod.LittleEndian)
return mod.NewIntBytes(s.v[:], primeOrder, defaultEndianess)
}

// Set to the additive identity (0)
Expand Down Expand Up @@ -140,7 +141,17 @@ func (s *scalar) Pick(rand cipher.Stream) kyber.Scalar {

// SetBytes s to b, interpreted as a little endian integer.
func (s *scalar) SetBytes(b []byte) kyber.Scalar {
return s.setInt(mod.NewIntBytes(b, primeOrder, mod.LittleEndian))
return s.setInt(mod.NewIntBytes(b, primeOrder, defaultEndianess))
}

// ByteOrder return the byte representation type (big or little endian)
func (s *scalar) ByteOrder() kyber.ByteOrder {
return defaultEndianess
}

// GroupOrder returns the order of the underlying group
func (s *scalar) GroupOrder() *big.Int {
return big.NewInt(0).SetBytes(primeOrder.Bytes())
}

// String returns the string representation of this scalar (fixed length of 32 bytes, little endian).
Expand Down
42 changes: 21 additions & 21 deletions group/mod/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ var one = big.NewInt(1)
var two = big.NewInt(2)
var marshalScalarID = [8]byte{'m', 'o', 'd', '.', 'i', 'n', 't', ' '}

// ByteOrder denotes the endianness of the operation.
type ByteOrder bool

const (
// LittleEndian endianness
LittleEndian ByteOrder = true
// BigEndian endianness
BigEndian ByteOrder = false
)

// Int is a generic implementation of finite field arithmetic
// on integer finite fields with a given constant modulus,
// built using Go's built-in big.Int package.
Expand All @@ -47,9 +37,9 @@ const (
// For efficiency the modulus field M is a pointer,
// whose target is assumed never to change.
type Int struct {
V big.Int // Integer value from 0 through M-1
M *big.Int // Modulus for finite field arithmetic
BO ByteOrder // Endianness which will be used on input and output
V big.Int // Integer value from 0 through M-1
M *big.Int // Modulus for finite field arithmetic
BO kyber.ByteOrder // Endianness which will be used on input and output
}

// NewInt creaters a new Int with a given big.Int and a big.Int modulus.
Expand All @@ -64,7 +54,7 @@ func NewInt64(v int64, M *big.Int) *Int {

// NewIntBytes creates a new Int with a given slice of bytes and a big.Int
// modulus.
func NewIntBytes(a []byte, m *big.Int, byteOrder ByteOrder) *Int {
func NewIntBytes(a []byte, m *big.Int, byteOrder kyber.ByteOrder) *Int {
return new(Int).InitBytes(a, m, byteOrder)
}

Expand All @@ -78,21 +68,21 @@ func NewIntString(n, d string, base int, m *big.Int) *Int {
// Note that the value is copied; the modulus is not.
func (i *Int) Init(V *big.Int, m *big.Int) *Int {
i.M = m
i.BO = BigEndian
i.BO = kyber.BigEndian
i.V.Set(V).Mod(&i.V, m)
return i
}

// Init64 creates an Int with an int64 value and big.Int modulus.
func (i *Int) Init64(v int64, m *big.Int) *Int {
i.M = m
i.BO = BigEndian
i.BO = kyber.BigEndian
i.V.SetInt64(v).Mod(&i.V, m)
return i
}

// InitBytes init the Int to a number represented in a big-endian byte string.
func (i *Int) InitBytes(a []byte, m *big.Int, byteOrder ByteOrder) *Int {
func (i *Int) InitBytes(a []byte, m *big.Int, byteOrder kyber.ByteOrder) *Int {
i.M = m
i.BO = byteOrder
i.SetBytes(a)
Expand All @@ -103,7 +93,7 @@ func (i *Int) InitBytes(a []byte, m *big.Int, byteOrder ByteOrder) *Int {
// specified with a pair of strings in a given base.
func (i *Int) InitString(n, d string, base int, m *big.Int) *Int {
i.M = m
i.BO = BigEndian
i.BO = kyber.BigEndian
if _, succ := i.SetString(n, d, base); !succ {
panic("InitString: invalid fraction representation")
}
Expand Down Expand Up @@ -302,6 +292,16 @@ func (i *Int) Pick(rand cipher.Stream) kyber.Scalar {
return i
}

// ByteOrder return the byte representation type (big or little endian)
func (i *Int) ByteOrder() kyber.ByteOrder {
return i.BO
}

// GroupOrder returns the order of the underlying group
func (i *Int) GroupOrder() *big.Int {
return big.NewInt(0).Set(i.M)
}

// MarshalSize returns the length in bytes of encoded integers with modulus M.
// The length of encoded Ints depends only on the size of the modulus,
// and not on the the value of the encoded integer,
Expand All @@ -317,7 +317,7 @@ func (i *Int) MarshalBinary() ([]byte, error) {
b := i.V.Bytes() // may be shorter than l
offset := l - len(b)

if i.BO == LittleEndian {
if i.BO == kyber.LittleEndian {
return i.LittleEndian(l, l), nil
}

Expand All @@ -342,7 +342,7 @@ func (i *Int) UnmarshalBinary(buf []byte) error {
return errors.New("UnmarshalBinary: wrong size buffer")
}
// Still needed here because of the comparison with the modulo
if i.BO == LittleEndian {
if i.BO == kyber.LittleEndian {
buf = reverse(nil, buf)
}
i.V.SetBytes(buf)
Expand Down Expand Up @@ -384,7 +384,7 @@ func (i *Int) BigEndian(min, max int) []byte {
// Endianness depends on the endianess set in i.
func (i *Int) SetBytes(a []byte) kyber.Scalar {
var buff = a
if i.BO == LittleEndian {
if i.BO == kyber.LittleEndian {
buff = reverse(nil, a)
}
i.V.SetBytes(buff).Mod(&i.V, i.M)
Expand Down
Loading

0 comments on commit ae87c6b

Please sign in to comment.