From 5ff6cfbbf7bccc1822d14c617277da2f15caa5eb Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Thu, 29 Aug 2019 16:48:35 +0200 Subject: [PATCH 01/26] 1st draft using user entropy --- share/dkg/pedersen/dkg.go | 12 ++++++--- util/random/rand.go | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 6d7bc5aa3..4edec01d8 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,11 +10,13 @@ package dkg import ( + "crypto/rand" "errors" "fmt" + "io" - "go.dedis.ch/kyber/v3" - + "github.com/dedis/kyber/util/random" + "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" "go.dedis.ch/kyber/v3/sign/schnorr" @@ -78,6 +80,9 @@ type Config struct { // absent) when doing a resharing to avoid a downgrade attack, where a resharing // the number of deals required is less than what it is supposed to be. OldThreshold int + + // Reader to maybe include entropy from the user during random generation + Reader io.Reader } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -164,7 +169,8 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - secretCoeff := c.Suite.Scalar().Pick(c.Suite.RandomStream()) + randomStream := random.NewStream(c.Reader, rand.Reader) + secretCoeff := c.Suite.Scalar().Pick(randomStream) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true c.OldNodes = c.NewNodes diff --git a/util/random/rand.go b/util/random/rand.go index 0fcee6fed..b8711d716 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,6 +5,7 @@ package random import ( "crypto/cipher" "crypto/rand" + "io" "math/big" ) @@ -76,3 +77,58 @@ func (r *randstream) XORKeyStream(dst, src []byte) { func New() cipher.Stream { return &randstream{} } + +type mixedrandstream struct { + reader io.Reader + rand io.Reader +} + +func (r *mixedrandstream) XORKeyStream(dst, src []byte) { + + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } + + remains := l + + //get entropy from user + buf1 := make([]byte, l) + if r.reader != nil { + n1, err := r.rand.Read(buf1) + if err != nil { + panic(err) + } + remains -= n1 + } + + //get entropy ffron crypto/rand + buf2 := make([]byte, remains) + n2, err := r.rand.Read(buf2) + if err != nil { + panic(err) + } + if n2 < len(buf2) { + panic("short read on infinite random stream!?") + } + + var buf []byte + + //concat the two + if l == remains { + //no additional entropy from user + buf = buf2 + } else { + buf = append(buf2, buf1...) + } + + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] + } +} + +// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand +// package AND the user input given via Reader. +func NewStream(reader io.Reader, rand io.Reader) cipher.Stream { + return &mixedrandstream{reader: reader, rand: rand} +} From 387efc0f0e59d176dadf2c167def414d4f7cb8b2 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 13:34:19 +0200 Subject: [PATCH 02/26] impl XOR mixed rand --- go.mod | 13 ++- go.sum | 22 +++++ share/dkg/pedersen/dkg.go | 15 +++- util/random/rand.go | 168 +++++++++++++++++++------------------- 4 files changed, 127 insertions(+), 91 deletions(-) diff --git a/go.mod b/go.mod index 4e80f1976..41a8bc564 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,14 @@ module go.dedis.ch/kyber/v3 require ( - github.com/stretchr/testify v1.3.0 + github.com/stretchr/objx v0.2.0 // indirect + github.com/stretchr/testify v1.4.0 go.dedis.ch/fixbuf v1.0.3 - go.dedis.ch/protobuf v1.0.5 - golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b - golang.org/x/sys v0.0.0-20190124100055-b90733256f2e + go.dedis.ch/protobuf v1.0.6 + golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 + golang.org/x/net v0.0.0-20190909003024-a7b16738d86b // indirect + golang.org/x/sys v0.0.0-20190909082730-f460065e899a + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20190909030654-5b82db07426d // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) diff --git a/go.sum b/go.sum index 08a703534..0ad3a1541 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,37 @@ 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= +go.dedis.ch/kyber/v3 v3.0.0-pre2/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= +go.dedis.ch/protobuf v1.0.6/go.mod h1:YHYXW6dQ9p2iJ3f+2fxKnOpjGx0MvL4cwpg1RVNXaV8= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 4edec01d8..fa87ebc7f 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -83,6 +83,9 @@ type Config struct { // Reader to maybe include entropy from the user during random generation Reader io.Reader + // UserReaderOnly forces the dkg secret to be picked with the randomness comming + // from the user only allowing reproducibility + UserReaderOnly bool } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -169,7 +172,17 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - randomStream := random.NewStream(c.Reader, rand.Reader) + var randomStream cipher.Stream + // user did not provide a reader, we use entropy from crypto/rand + if c.Reader == nil { + randomStream = random.NewMixedStream(rand.Reader) + } else { // we use the reader they gave + if c.UserReaderOnly { + randomStream = random.NewMixedStream(c.Reader) + } else { + randomStream = random.NewMixedStream(c.Reader, rand.Reader) + } + } secretCoeff := c.Suite.Scalar().Pick(randomStream) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true diff --git a/util/random/rand.go b/util/random/rand.go index b8711d716..7a60cc85d 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -7,6 +7,8 @@ import ( "crypto/rand" "io" "math/big" + "golang.org/x/crypto/blake2b" + "go.dedis.ch/kyber/v3/xof/blake2xb" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -21,114 +23,108 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { if exact { if highbits != 0 { b[0] |= 1 << (highbits - 1) - } else { - b[0] |= 0x80 + } else { + b[0] |= 0x80 + } } + return b } - return b -} - -// Int chooses a uniform random big.Int less than a given modulus -func Int(mod *big.Int, rand cipher.Stream) *big.Int { - bitlen := uint(mod.BitLen()) - i := new(big.Int) - for { - i.SetBytes(Bits(bitlen, false, rand)) - if i.Sign() > 0 && i.Cmp(mod) < 0 { - return i + + // Int chooses a uniform random big.Int less than a given modulus + func Int(mod *big.Int, rand cipher.Stream) *big.Int { + bitlen := uint(mod.BitLen()) + i := new(big.Int) + for { + i.SetBytes(Bits(bitlen, false, rand)) + if i.Sign() > 0 && i.Cmp(mod) < 0 { + return i + } } } -} -// Bytes fills a slice with random bytes from rand. -func Bytes(b []byte, rand cipher.Stream) { - rand.XORKeyStream(b, b) -} + // Bytes fills a slice with random bytes from rand. + func Bytes(b []byte, rand cipher.Stream) { + rand.XORKeyStream(b, b) + } -type randstream struct { -} + type randstream struct { + } -func (r *randstream) XORKeyStream(dst, src []byte) { - // This function works only on local data, so it is - // safe against race conditions, as long as crypto/rand - // is as well. (It is.) + func (r *randstream) XORKeyStream(dst, src []byte) { + // This function works only on local data, so it is + // safe against race conditions, as long as crypto/rand + // is as well. (It is.) - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - buf := make([]byte, l) - n, err := rand.Read(buf) - if err != nil { - panic(err) - } - if n < len(buf) { - panic("short read on infinite random stream!?") - } + buf := make([]byte, l) + n, err := rand.Read(buf) + if err != nil { + panic(err) + } + if n < len(buf) { + panic("short read on infinite random stream!?") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] + } } -} -// New returns a new cipher.Stream that gets random data from Go's crypto/rand package. -// The resulting cipher.Stream can be used in multiple threads. -func New() cipher.Stream { - return &randstream{} -} + // New returns a new cipher.Stream that gets random data from Go's crypto/rand package. + // The resulting cipher.Stream can be used in multiple threads. + func New() cipher.Stream { + return &randstream{} + } -type mixedrandstream struct { - reader io.Reader - rand io.Reader -} -func (r *mixedrandstream) XORKeyStream(dst, src []byte) { + const READER_BYTES = 32; - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") + type mixedrandstream struct { + Readers []io.Reader } - remains := l + func (r *mixedrandstream) XORKeyStream(dst, src []byte) { - //get entropy from user - buf1 := make([]byte, l) - if r.reader != nil { - n1, err := r.rand.Read(buf1) - if err != nil { - panic(err) + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") } - remains -= n1 - } - //get entropy ffron crypto/rand - buf2 := make([]byte, remains) - n2, err := r.rand.Read(buf2) - if err != nil { - panic(err) - } - if n2 < len(buf2) { - panic("short read on infinite random stream!?") - } + var b bytes.Buffer + var nerr int - var buf []byte + for _, r := range r.Readers { + var buff [READER_BYTES]byte + n, err := io.ReadFull(r, buff[:]) + if err != nil { + nerr++ + } + b.Write(buff[:n]) + } - //concat the two - if l == remains { - //no additional entropy from user - buf = buf2 - } else { - buf = append(buf2, buf1...) - } + // we are ok with few sources being insecure (aka giving less than 32 bytes) + // but not all of them + if nerr == len(r.Readers) { + panic("all readers failed") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] + // create the XOF hash output + h := sha256.New() + h.Write(b.Bytes()) + seed := h.Sum(nil)[:blake2b.Size] + hash := blake2xb.New(seed) + return hash.XORKeyStream(dst, src) } -} -// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand -// package AND the user input given via Reader. -func NewStream(reader io.Reader, rand io.Reader) cipher.Stream { - return &mixedrandstream{reader: reader, rand: rand} -} + // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand + // package AND user input if given via a Reader. + func NewMixedStream(readers ...io.Reader) cipher.Stream { + if len(readers) == 0 { + readers = [1]io.Reader{rand.Reader} + } + return &mixedrandstream{readers} + } From 87dc4c2a36f4791f982d6c7117484fdfa5f7d7b1 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 14:54:46 +0200 Subject: [PATCH 03/26] fixes --- share/dkg/pedersen/dkg.go | 3 ++- util/random/rand.go | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index fa87ebc7f..89679ad14 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -14,8 +14,9 @@ import ( "errors" "fmt" "io" + "crypto/cipher" - "github.com/dedis/kyber/util/random" + "github.com/PizzaWhisperer/kyber/util/random" "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" diff --git a/util/random/rand.go b/util/random/rand.go index 7a60cc85d..7a1b685a2 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,10 +5,12 @@ package random import ( "crypto/cipher" "crypto/rand" + "crypto/sha256" "io" "math/big" "golang.org/x/crypto/blake2b" "go.dedis.ch/kyber/v3/xof/blake2xb" + "bytes" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -117,14 +119,14 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { h.Write(b.Bytes()) seed := h.Sum(nil)[:blake2b.Size] hash := blake2xb.New(seed) - return hash.XORKeyStream(dst, src) + hash.XORKeyStream(dst, src) } // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand // package AND user input if given via a Reader. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { - readers = [1]io.Reader{rand.Reader} + readers = []io.Reader{rand.Reader} } return &mixedrandstream{readers} } From 1dc8dedb24e91c60d6201c74a49837001516761d Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 14:59:48 +0200 Subject: [PATCH 04/26] identation --- util/random/rand.go | 160 ++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index 7a1b685a2..d70afc60a 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -25,108 +25,108 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { if exact { if highbits != 0 { b[0] |= 1 << (highbits - 1) - } else { - b[0] |= 0x80 - } + } else { + b[0] |= 0x80 } - return b } - - // Int chooses a uniform random big.Int less than a given modulus - func Int(mod *big.Int, rand cipher.Stream) *big.Int { - bitlen := uint(mod.BitLen()) - i := new(big.Int) - for { - i.SetBytes(Bits(bitlen, false, rand)) - if i.Sign() > 0 && i.Cmp(mod) < 0 { - return i - } + return b +} + +// Int chooses a uniform random big.Int less than a given modulus +func Int(mod *big.Int, rand cipher.Stream) *big.Int { + bitlen := uint(mod.BitLen()) + i := new(big.Int) + for { + i.SetBytes(Bits(bitlen, false, rand)) + if i.Sign() > 0 && i.Cmp(mod) < 0 { + return i } } +} - // Bytes fills a slice with random bytes from rand. - func Bytes(b []byte, rand cipher.Stream) { - rand.XORKeyStream(b, b) - } - - type randstream struct { - } +// Bytes fills a slice with random bytes from rand. +func Bytes(b []byte, rand cipher.Stream) { + rand.XORKeyStream(b, b) +} - func (r *randstream) XORKeyStream(dst, src []byte) { - // This function works only on local data, so it is - // safe against race conditions, as long as crypto/rand - // is as well. (It is.) +type randstream struct { +} - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } +func (r *randstream) XORKeyStream(dst, src []byte) { + // This function works only on local data, so it is + // safe against race conditions, as long as crypto/rand + // is as well. (It is.) - buf := make([]byte, l) - n, err := rand.Read(buf) - if err != nil { - panic(err) - } - if n < len(buf) { - panic("short read on infinite random stream!?") - } + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] - } + buf := make([]byte, l) + n, err := rand.Read(buf) + if err != nil { + panic(err) + } + if n < len(buf) { + panic("short read on infinite random stream!?") } - // New returns a new cipher.Stream that gets random data from Go's crypto/rand package. - // The resulting cipher.Stream can be used in multiple threads. - func New() cipher.Stream { - return &randstream{} + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] } +} +// New returns a new cipher.Stream that gets random data from Go's crypto/rand package. +// The resulting cipher.Stream can be used in multiple threads. +func New() cipher.Stream { + return &randstream{} +} - const READER_BYTES = 32; - type mixedrandstream struct { - Readers []io.Reader - } +const READER_BYTES = 32; - func (r *mixedrandstream) XORKeyStream(dst, src []byte) { +type mixedrandstream struct { + Readers []io.Reader +} - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } +func (r *mixedrandstream) XORKeyStream(dst, src []byte) { - var b bytes.Buffer - var nerr int + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - for _, r := range r.Readers { - var buff [READER_BYTES]byte - n, err := io.ReadFull(r, buff[:]) - if err != nil { - nerr++ - } - b.Write(buff[:n]) - } + var b bytes.Buffer + var nerr int - // we are ok with few sources being insecure (aka giving less than 32 bytes) - // but not all of them - if nerr == len(r.Readers) { - panic("all readers failed") + for _, r := range r.Readers { + var buff [READER_BYTES]byte + n, err := io.ReadFull(r, buff[:]) + if err != nil { + nerr++ } + b.Write(buff[:n]) + } - // create the XOF hash output - h := sha256.New() - h.Write(b.Bytes()) - seed := h.Sum(nil)[:blake2b.Size] - hash := blake2xb.New(seed) - hash.XORKeyStream(dst, src) + // we are ok with few sources being insecure (aka giving less than 32 bytes) + // but not all of them + if nerr == len(r.Readers) { + panic("all readers failed") } - // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand - // package AND user input if given via a Reader. - func NewMixedStream(readers ...io.Reader) cipher.Stream { - if len(readers) == 0 { - readers = []io.Reader{rand.Reader} - } - return &mixedrandstream{readers} + // create the XOF hash output + h := sha256.New() + h.Write(b.Bytes()) + seed := h.Sum(nil)[:blake2b.Size] + hash := blake2xb.New(seed) + hash.XORKeyStream(dst, src) +} + +// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand +// package AND user input if given via a Reader. +func NewMixedStream(readers ...io.Reader) cipher.Stream { + if len(readers) == 0 { + readers = []io.Reader{rand.Reader} } + return &mixedrandstream{readers} +} From 9f5eef398c38e4f5137ea0b8117f835a482aecae Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 15:16:02 +0200 Subject: [PATCH 05/26] tests passing --- util/random/rand.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index d70afc60a..ae086902f 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,10 +5,9 @@ package random import ( "crypto/cipher" "crypto/rand" - "crypto/sha256" + "crypto/sha512" "io" "math/big" - "golang.org/x/crypto/blake2b" "go.dedis.ch/kyber/v3/xof/blake2xb" "bytes" ) @@ -115,9 +114,9 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // create the XOF hash output - h := sha256.New() + h := sha512.New() h.Write(b.Bytes()) - seed := h.Sum(nil)[:blake2b.Size] + seed := h.Sum(nil) hash := blake2xb.New(seed) hash.XORKeyStream(dst, src) } From 16c054a128741e25cf5590c8a837c1f35d62edd9 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 10:07:57 +0200 Subject: [PATCH 06/26] comments --- share/dkg/pedersen/dkg.go | 15 ++++++++------- util/random/rand.go | 17 +++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 89679ad14..196549877 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,11 +10,11 @@ package dkg import ( + "crypto/cipher" "crypto/rand" "errors" "fmt" "io" - "crypto/cipher" "github.com/PizzaWhisperer/kyber/util/random" "go.dedis.ch/kyber" @@ -82,10 +82,11 @@ type Config struct { // the number of deals required is less than what it is supposed to be. OldThreshold int - // Reader to maybe include entropy from the user during random generation + // Reader holds a user-specified entropy source used to create a random stream Reader io.Reader - // UserReaderOnly forces the dkg secret to be picked with the randomness comming - // from the user only allowing reproducibility + + // UserReaderOnly forces the dkg's secretCoeff to be picked with randomness comming + // from the user only, allowing reproducibility UserReaderOnly bool } @@ -174,10 +175,10 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { } else if !isResharing && newPresent { // fresh DKG case var randomStream cipher.Stream - // user did not provide a reader, we use entropy from crypto/rand + // empty reader, use entropy from crypto/rand if c.Reader == nil { - randomStream = random.NewMixedStream(rand.Reader) - } else { // we use the reader they gave + randomStream = random.New() + } else { // use the reader they gave, alone or combined if c.UserReaderOnly { randomStream = random.NewMixedStream(c.Reader) } else { diff --git a/util/random/rand.go b/util/random/rand.go index ae086902f..1b20554c5 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -3,13 +3,14 @@ package random import ( + "bytes" "crypto/cipher" "crypto/rand" "crypto/sha512" "io" "math/big" + "go.dedis.ch/kyber/v3/xof/blake2xb" - "bytes" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -81,8 +82,8 @@ func New() cipher.Stream { return &randstream{} } - -const READER_BYTES = 32; +// READER_BYTES is how many bytes we expect from each source +const READER_BYTES = 32 type mixedrandstream struct { Readers []io.Reader @@ -107,13 +108,13 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { b.Write(buff[:n]) } - // we are ok with few sources being insecure (aka giving less than 32 bytes) - // but not all of them + // we are ok with few sources being insecure (i.e., providing less than + // READER_BYTES bytes), but not all of them if nerr == len(r.Readers) { panic("all readers failed") } - // create the XOF hash output + // create the XOF output, with hash of collected data as seed h := sha512.New() h.Write(b.Bytes()) seed := h.Sum(nil) @@ -121,8 +122,8 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { hash.XORKeyStream(dst, src) } -// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand -// package AND user input if given via a Reader. +// NewMixedStream returns a new cipher.Stream that gets random data from the specified +// readers. If no reader was given, Go's crypto/rand package is used. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { readers = []io.Reader{rand.Reader} From fc23550af7d7b5878f0b0a3c9ca7f83f5c1805a0 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 10:34:19 +0200 Subject: [PATCH 07/26] tests --- share/dkg/pedersen/dkg.go | 12 ++++---- share/dkg/pedersen/dkg_test.go | 52 +++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 196549877..f5c909ccc 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -243,12 +243,14 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { // NewDistKeyGenerator returns a dist key generator ready to create a fresh // distributed key with the regular DKG protocol. -func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int) (*DistKeyGenerator, error) { +func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int, r io.Reader, userOnly bool) (*DistKeyGenerator, error) { c := &Config{ - Suite: suite, - Longterm: longterm, - NewNodes: participants, - Threshold: t, + Suite: suite, + Longterm: longterm, + NewNodes: participants, + Threshold: t, + Reader: r, + UserReaderOnly: userOnly, } return NewDistKeyHandler(c) } diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index f4ba4d07e..bcad1ad0a 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -3,11 +3,12 @@ package dkg import ( "crypto/rand" "fmt" + "io" mathRand "math/rand" "testing" "github.com/stretchr/testify/require" - "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/group/edwards25519" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" @@ -19,7 +20,10 @@ const defaultN = 5 var defaultT = vss.MinimumT(defaultN) -func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { +var defaultReader io.Reader +var defaultUserOnly = false + +func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { partPubs = make([]kyber.Point, n) partSec = make([]kyber.Scalar, n) for i := 0; i < n; i++ { @@ -29,7 +33,7 @@ func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs [] } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, r, userOnly) if err != nil { panic(err) } @@ -39,10 +43,10 @@ func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs [] } func TestDKGNewDistKeyGenerator(t *testing.T) { - partPubs, partSec, _ := generate(defaultN, defaultT) + partPubs, partSec, _ := generate(defaultN, defaultT, defaultReader, defaultUserOnly) long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT) + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, defaultReader, defaultUserOnly) require.Nil(t, err) require.NotNil(t, dkg.dealer) require.True(t, dkg.canIssue) @@ -54,12 +58,12 @@ func TestDKGNewDistKeyGenerator(t *testing.T) { require.False(t, dkg.isResharing) sec, _ := genPair() - _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT) + _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT, defaultReader, defaultUserOnly) require.Error(t, err) } func TestDKGDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] dks, err := dkg.DistKeyShare() @@ -81,7 +85,7 @@ func TestDKGDeal(t *testing.T) { } func TestDKGProcessDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] deals, err := dkg.Deals() require.Nil(t, err) @@ -136,7 +140,7 @@ func TestDKGProcessResponse(t *testing.T) { // second peer processes it and returns a complaint // first peer process the complaint - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] idxRec := 1 rec := dkgs[idxRec] @@ -242,7 +246,7 @@ func TestDKGProcessResponse(t *testing.T) { func TestDKGResharingThreshold(t *testing.T) { n := 7 oldT := vss.MinimumT(n) - publics, _, dkgs := generate(n, oldT) + publics, _, dkgs := generate(n, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) newN := len(dkgs) + 1 @@ -407,7 +411,7 @@ func TestDKGThreshold(t *testing.T) { } for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal) + dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal, defaultReader, defaultUserOnly) if err != nil { panic(err) } @@ -504,7 +508,7 @@ func TestDKGThreshold(t *testing.T) { } func TestDistKeyShare(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) for _, dkg := range dkgs { @@ -609,7 +613,7 @@ func fullExchange(t *testing.T, dkgs []*DistKeyGenerator, checkQUAL bool) { // Test resharing of a DKG to the same set of nodes func TestDKGResharing(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT) + publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -665,7 +669,7 @@ func TestDKGResharing(t *testing.T) { // Test resharing functionality with one node less func TestDKGResharingRemoveNode(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT) + publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) newN := len(publics) - 1 @@ -728,7 +732,7 @@ func TestDKGResharingRemoveNode(t *testing.T) { func TestDKGResharingNewNodesThreshold(t *testing.T) { oldN := defaultN oldT := vss.MinimumT(oldN) - oldPubs, oldPrivs, dkgs := generate(oldN, oldT) + oldPubs, oldPrivs, dkgs := generate(oldN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -892,7 +896,7 @@ func TestDKGResharingNewNodesThreshold(t *testing.T) { // Test resharing to a different set of nodes with one common func TestDKGResharingNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1068,7 +1072,7 @@ func TestDKGResharingNewNodes(t *testing.T) { } func TestDKGResharingPartialNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1241,3 +1245,17 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.NoError(t, err) require.Equal(t, oldSecret.String(), newSecret.String()) } + +func TestDKGUserOnly(t *testing.T) { + r := string.NewReader("This is the seed to my custom reader, please use it well.") + partPubs, partSec, _ := generate(defaultN, defaultT, r, true) + + long := partSec[0] + dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + require.Nil(t, err) + require.NotNil(t, dkg1.dealer) + dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + require.Nil(t, err) + require.NotNil(t, dkg1.dealer) + require.True(t, dkg1.dealer.secret.Equal(dkg2.dealer.secret)) +} From cc77bdb5985d0145a208aca216e3c04dbe0bf409 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 13:13:44 +0200 Subject: [PATCH 08/26] testing --- go.mod | 8 +++----- go.sum | 22 +++++++++++++--------- share/dkg/pedersen/dkg_test.go | 33 +++++++++++++++++++++++++++------ util/random/rand.go | 7 +++---- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 41a8bc564..f0264eb2b 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,12 @@ module go.dedis.ch/kyber/v3 require ( - github.com/stretchr/objx v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.4.0 go.dedis.ch/fixbuf v1.0.3 go.dedis.ch/protobuf v1.0.6 golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 - golang.org/x/net v0.0.0-20190909003024-a7b16738d86b // indirect - golang.org/x/sys v0.0.0-20190909082730-f460065e899a - golang.org/x/text v0.3.2 // indirect - golang.org/x/tools v0.0.0-20190909030654-5b82db07426d // indirect + golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) diff --git a/go.sum b/go.sum index 0ad3a1541..cb21d790b 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,41 @@ 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/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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.0-pre2/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= +go.dedis.ch/protobuf v1.0.6 h1:E61p2XjYbYrTf3WeXE8M8Ui5WA3hX/NgbHHi5D0FLxI= go.dedis.ch/protobuf v1.0.6/go.mod h1:YHYXW6dQ9p2iJ3f+2fxKnOpjGx0MvL4cwpg1RVNXaV8= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 h1:mgAKeshyNqWKdENOnQsg+8dRTwZFIwFaO3HNl52sweA= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b h1:3S2h5FadpNr0zUUCVZjlKIEYF+KaX/OBplTGo89CYHI= +golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index bcad1ad0a..c6b800b06 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -4,7 +4,10 @@ import ( "crypto/rand" "fmt" "io" + "io/ioutil" + "bytes" mathRand "math/rand" + "strings" "testing" "github.com/stretchr/testify/require" @@ -31,9 +34,15 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par partPubs[i] = pub partSec[i] = sec } + //if there is a reader we need to make a copy for each dkg + var b []byte + if r != nil { + b, _ = ioutil.ReadAll(r) + } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, r, userOnly) + rcopy := bytes.NewReader(b) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, rcopy, userOnly) if err != nil { panic(err) } @@ -1246,16 +1255,28 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.Equal(t, oldSecret.String(), newSecret.String()) } +func TestDKGMixedEntropy(t *testing.T) { + r := strings.NewReader("some io.Reader stream to be read") + partPubs, partSec, _ := generate(defaultN, defaultT, r, defaultUserOnly) + + long := partSec[0] + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, defaultUserOnly) + require.Nil(t, err) + require.NotNil(t, dkg.dealer) +} + func TestDKGUserOnly(t *testing.T) { - r := string.NewReader("This is the seed to my custom reader, please use it well.") + r := strings.NewReader("some io.Reader stream to be read") partPubs, partSec, _ := generate(defaultN, defaultT, r, true) long := partSec[0] - dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + r1 := strings.NewReader("some io.Reader stream to be read") + dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r1, true) require.Nil(t, err) require.NotNil(t, dkg1.dealer) - dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + r2 := strings.NewReader("some io.Reader stream to be read") + dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r2, true) require.Nil(t, err) - require.NotNil(t, dkg1.dealer) - require.True(t, dkg1.dealer.secret.Equal(dkg2.dealer.secret)) + require.NotNil(t, dkg2.dealer) + require.True(t, dkg1.dealer.PrivatePoly().Secret().Equal(dkg2.dealer.PrivatePoly().Secret())) } diff --git a/util/random/rand.go b/util/random/rand.go index 1b20554c5..d3ed56796 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -98,10 +98,9 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { var b bytes.Buffer var nerr int - - for _, r := range r.Readers { - var buff [READER_BYTES]byte - n, err := io.ReadFull(r, buff[:]) + for _, reader := range r.Readers { + buff := make([]byte, READER_BYTES) + n, err := io.ReadFull(reader, buff) if err != nil { nerr++ } From d69c5ffb6c4907a1d26c752eb536afaf483cb9c5 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Fri, 20 Sep 2019 12:06:00 +0200 Subject: [PATCH 09/26] rand pr --- share/dkg/pedersen/dkg.go | 39 ++++-------------- share/dkg/pedersen/dkg_test.go | 73 ++++++++-------------------------- util/random/rand.go | 17 +++++--- 3 files changed, 37 insertions(+), 92 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index f5c909ccc..6d7bc5aa3 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,14 +10,11 @@ package dkg import ( - "crypto/cipher" - "crypto/rand" "errors" "fmt" - "io" - "github.com/PizzaWhisperer/kyber/util/random" - "go.dedis.ch/kyber" + "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" "go.dedis.ch/kyber/v3/sign/schnorr" @@ -81,13 +78,6 @@ type Config struct { // absent) when doing a resharing to avoid a downgrade attack, where a resharing // the number of deals required is less than what it is supposed to be. OldThreshold int - - // Reader holds a user-specified entropy source used to create a random stream - Reader io.Reader - - // UserReaderOnly forces the dkg's secretCoeff to be picked with randomness comming - // from the user only, allowing reproducibility - UserReaderOnly bool } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -174,18 +164,7 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - var randomStream cipher.Stream - // empty reader, use entropy from crypto/rand - if c.Reader == nil { - randomStream = random.New() - } else { // use the reader they gave, alone or combined - if c.UserReaderOnly { - randomStream = random.NewMixedStream(c.Reader) - } else { - randomStream = random.NewMixedStream(c.Reader, rand.Reader) - } - } - secretCoeff := c.Suite.Scalar().Pick(randomStream) + secretCoeff := c.Suite.Scalar().Pick(c.Suite.RandomStream()) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true c.OldNodes = c.NewNodes @@ -243,14 +222,12 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { // NewDistKeyGenerator returns a dist key generator ready to create a fresh // distributed key with the regular DKG protocol. -func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int, r io.Reader, userOnly bool) (*DistKeyGenerator, error) { +func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int) (*DistKeyGenerator, error) { c := &Config{ - Suite: suite, - Longterm: longterm, - NewNodes: participants, - Threshold: t, - Reader: r, - UserReaderOnly: userOnly, + Suite: suite, + Longterm: longterm, + NewNodes: participants, + Threshold: t, } return NewDistKeyHandler(c) } diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index c6b800b06..f4ba4d07e 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -3,15 +3,11 @@ package dkg import ( "crypto/rand" "fmt" - "io" - "io/ioutil" - "bytes" mathRand "math/rand" - "strings" "testing" "github.com/stretchr/testify/require" - "go.dedis.ch/kyber" + "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/group/edwards25519" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" @@ -23,10 +19,7 @@ const defaultN = 5 var defaultT = vss.MinimumT(defaultN) -var defaultReader io.Reader -var defaultUserOnly = false - -func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { +func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { partPubs = make([]kyber.Point, n) partSec = make([]kyber.Scalar, n) for i := 0; i < n; i++ { @@ -34,15 +27,9 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par partPubs[i] = pub partSec[i] = sec } - //if there is a reader we need to make a copy for each dkg - var b []byte - if r != nil { - b, _ = ioutil.ReadAll(r) - } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - rcopy := bytes.NewReader(b) - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, rcopy, userOnly) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t) if err != nil { panic(err) } @@ -52,10 +39,10 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par } func TestDKGNewDistKeyGenerator(t *testing.T) { - partPubs, partSec, _ := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + partPubs, partSec, _ := generate(defaultN, defaultT) long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, defaultReader, defaultUserOnly) + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT) require.Nil(t, err) require.NotNil(t, dkg.dealer) require.True(t, dkg.canIssue) @@ -67,12 +54,12 @@ func TestDKGNewDistKeyGenerator(t *testing.T) { require.False(t, dkg.isResharing) sec, _ := genPair() - _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT, defaultReader, defaultUserOnly) + _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT) require.Error(t, err) } func TestDKGDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] dks, err := dkg.DistKeyShare() @@ -94,7 +81,7 @@ func TestDKGDeal(t *testing.T) { } func TestDKGProcessDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] deals, err := dkg.Deals() require.Nil(t, err) @@ -149,7 +136,7 @@ func TestDKGProcessResponse(t *testing.T) { // second peer processes it and returns a complaint // first peer process the complaint - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] idxRec := 1 rec := dkgs[idxRec] @@ -255,7 +242,7 @@ func TestDKGProcessResponse(t *testing.T) { func TestDKGResharingThreshold(t *testing.T) { n := 7 oldT := vss.MinimumT(n) - publics, _, dkgs := generate(n, oldT, defaultReader, defaultUserOnly) + publics, _, dkgs := generate(n, oldT) fullExchange(t, dkgs, true) newN := len(dkgs) + 1 @@ -420,7 +407,7 @@ func TestDKGThreshold(t *testing.T) { } for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal, defaultReader, defaultUserOnly) + dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal) if err != nil { panic(err) } @@ -517,7 +504,7 @@ func TestDKGThreshold(t *testing.T) { } func TestDistKeyShare(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) fullExchange(t, dkgs, true) for _, dkg := range dkgs { @@ -622,7 +609,7 @@ func fullExchange(t *testing.T, dkgs []*DistKeyGenerator, checkQUAL bool) { // Test resharing of a DKG to the same set of nodes func TestDKGResharing(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) + publics, secrets, dkgs := generate(defaultN, oldT) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -678,7 +665,7 @@ func TestDKGResharing(t *testing.T) { // Test resharing functionality with one node less func TestDKGResharingRemoveNode(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) + publics, secrets, dkgs := generate(defaultN, oldT) fullExchange(t, dkgs, true) newN := len(publics) - 1 @@ -741,7 +728,7 @@ func TestDKGResharingRemoveNode(t *testing.T) { func TestDKGResharingNewNodesThreshold(t *testing.T) { oldN := defaultN oldT := vss.MinimumT(oldN) - oldPubs, oldPrivs, dkgs := generate(oldN, oldT, defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(oldN, oldT) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -905,7 +892,7 @@ func TestDKGResharingNewNodesThreshold(t *testing.T) { // Test resharing to a different set of nodes with one common func TestDKGResharingNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1081,7 +1068,7 @@ func TestDKGResharingNewNodes(t *testing.T) { } func TestDKGResharingPartialNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1254,29 +1241,3 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.NoError(t, err) require.Equal(t, oldSecret.String(), newSecret.String()) } - -func TestDKGMixedEntropy(t *testing.T) { - r := strings.NewReader("some io.Reader stream to be read") - partPubs, partSec, _ := generate(defaultN, defaultT, r, defaultUserOnly) - - long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, defaultUserOnly) - require.Nil(t, err) - require.NotNil(t, dkg.dealer) -} - -func TestDKGUserOnly(t *testing.T) { - r := strings.NewReader("some io.Reader stream to be read") - partPubs, partSec, _ := generate(defaultN, defaultT, r, true) - - long := partSec[0] - r1 := strings.NewReader("some io.Reader stream to be read") - dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r1, true) - require.Nil(t, err) - require.NotNil(t, dkg1.dealer) - r2 := strings.NewReader("some io.Reader stream to be read") - dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r2, true) - require.Nil(t, err) - require.NotNil(t, dkg2.dealer) - require.True(t, dkg1.dealer.PrivatePoly().Secret().Equal(dkg2.dealer.PrivatePoly().Secret())) -} diff --git a/util/random/rand.go b/util/random/rand.go index d3ed56796..8c9b99ba4 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -85,6 +85,10 @@ func New() cipher.Stream { // READER_BYTES is how many bytes we expect from each source const READER_BYTES = 32 +// MIXEDRAND_HASH is the hash used in XORKeyStream to mix all entropy sources together. +// sha512 is chosen as its digest is 64 bytes long, matching the length of blake2xb's seed. +var MIXEDRAND_HASH = sha512.New + type mixedrandstream struct { Readers []io.Reader } @@ -114,15 +118,18 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // create the XOF output, with hash of collected data as seed - h := sha512.New() + h := MIXEDRAND_HASH() h.Write(b.Bytes()) seed := h.Sum(nil) - hash := blake2xb.New(seed) - hash.XORKeyStream(dst, src) + blake2 := blake2xb.New(seed) + blake2.XORKeyStream(dst, src) } -// NewMixedStream returns a new cipher.Stream that gets random data from the specified -// readers. If no reader was given, Go's crypto/rand package is used. +// NewMixedStream returns a new cipher.Stream that gets random data from the given +// readers. If no reader was provided, Go's crypto/rand package is used. +// In order to use every source, it tries to read 32 bytes from each, and mix it +// all together into a string of valid length via hashing. This string is then +// used as a seed for blake2, which is used to perform the final XOR. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { readers = []io.Reader{rand.Reader} From 69f7d324df84515e4f82abc96d0485da7273489d Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Thu, 29 Aug 2019 16:48:35 +0200 Subject: [PATCH 10/26] 1st draft using user entropy --- share/dkg/pedersen/dkg.go | 12 ++++++--- util/random/rand.go | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 6d7bc5aa3..4edec01d8 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,11 +10,13 @@ package dkg import ( + "crypto/rand" "errors" "fmt" + "io" - "go.dedis.ch/kyber/v3" - + "github.com/dedis/kyber/util/random" + "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" "go.dedis.ch/kyber/v3/sign/schnorr" @@ -78,6 +80,9 @@ type Config struct { // absent) when doing a resharing to avoid a downgrade attack, where a resharing // the number of deals required is less than what it is supposed to be. OldThreshold int + + // Reader to maybe include entropy from the user during random generation + Reader io.Reader } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -164,7 +169,8 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - secretCoeff := c.Suite.Scalar().Pick(c.Suite.RandomStream()) + randomStream := random.NewStream(c.Reader, rand.Reader) + secretCoeff := c.Suite.Scalar().Pick(randomStream) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true c.OldNodes = c.NewNodes diff --git a/util/random/rand.go b/util/random/rand.go index 0fcee6fed..b8711d716 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,6 +5,7 @@ package random import ( "crypto/cipher" "crypto/rand" + "io" "math/big" ) @@ -76,3 +77,58 @@ func (r *randstream) XORKeyStream(dst, src []byte) { func New() cipher.Stream { return &randstream{} } + +type mixedrandstream struct { + reader io.Reader + rand io.Reader +} + +func (r *mixedrandstream) XORKeyStream(dst, src []byte) { + + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } + + remains := l + + //get entropy from user + buf1 := make([]byte, l) + if r.reader != nil { + n1, err := r.rand.Read(buf1) + if err != nil { + panic(err) + } + remains -= n1 + } + + //get entropy ffron crypto/rand + buf2 := make([]byte, remains) + n2, err := r.rand.Read(buf2) + if err != nil { + panic(err) + } + if n2 < len(buf2) { + panic("short read on infinite random stream!?") + } + + var buf []byte + + //concat the two + if l == remains { + //no additional entropy from user + buf = buf2 + } else { + buf = append(buf2, buf1...) + } + + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] + } +} + +// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand +// package AND the user input given via Reader. +func NewStream(reader io.Reader, rand io.Reader) cipher.Stream { + return &mixedrandstream{reader: reader, rand: rand} +} From b6d910d8ca85d155603adee4fe0158ca8519b315 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 13:34:19 +0200 Subject: [PATCH 11/26] impl XOR mixed rand --- go.mod | 3 +- go.sum | 27 ++++++ share/dkg/pedersen/dkg.go | 15 +++- util/random/rand.go | 168 +++++++++++++++++++------------------- 4 files changed, 125 insertions(+), 88 deletions(-) diff --git a/go.mod b/go.mod index 0a7e728dc..6957a4fea 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,8 @@ module go.dedis.ch/kyber/v3 require ( - github.com/stretchr/testify v1.3.0 + github.com/stretchr/objx v0.2.0 // indirect + github.com/stretchr/testify v1.4.0 go.dedis.ch/fixbuf v1.0.3 go.dedis.ch/protobuf v1.0.7 golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b diff --git a/go.sum b/go.sum index 72b5df637..a724d9799 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,45 @@ 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= +<<<<<<< HEAD go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7 h1:wRUEiq3u0/vBhLjcw9CmAVrol+BnDyq2M0XLukdphyI= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= +======= +go.dedis.ch/kyber/v3 v3.0.0-pre2/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= +go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= +go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= +go.dedis.ch/protobuf v1.0.6/go.mod h1:YHYXW6dQ9p2iJ3f+2fxKnOpjGx0MvL4cwpg1RVNXaV8= +>>>>>>> impl XOR mixed rand golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 4edec01d8..fa87ebc7f 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -83,6 +83,9 @@ type Config struct { // Reader to maybe include entropy from the user during random generation Reader io.Reader + // UserReaderOnly forces the dkg secret to be picked with the randomness comming + // from the user only allowing reproducibility + UserReaderOnly bool } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -169,7 +172,17 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - randomStream := random.NewStream(c.Reader, rand.Reader) + var randomStream cipher.Stream + // user did not provide a reader, we use entropy from crypto/rand + if c.Reader == nil { + randomStream = random.NewMixedStream(rand.Reader) + } else { // we use the reader they gave + if c.UserReaderOnly { + randomStream = random.NewMixedStream(c.Reader) + } else { + randomStream = random.NewMixedStream(c.Reader, rand.Reader) + } + } secretCoeff := c.Suite.Scalar().Pick(randomStream) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true diff --git a/util/random/rand.go b/util/random/rand.go index b8711d716..7a60cc85d 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -7,6 +7,8 @@ import ( "crypto/rand" "io" "math/big" + "golang.org/x/crypto/blake2b" + "go.dedis.ch/kyber/v3/xof/blake2xb" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -21,114 +23,108 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { if exact { if highbits != 0 { b[0] |= 1 << (highbits - 1) - } else { - b[0] |= 0x80 + } else { + b[0] |= 0x80 + } } + return b } - return b -} - -// Int chooses a uniform random big.Int less than a given modulus -func Int(mod *big.Int, rand cipher.Stream) *big.Int { - bitlen := uint(mod.BitLen()) - i := new(big.Int) - for { - i.SetBytes(Bits(bitlen, false, rand)) - if i.Sign() > 0 && i.Cmp(mod) < 0 { - return i + + // Int chooses a uniform random big.Int less than a given modulus + func Int(mod *big.Int, rand cipher.Stream) *big.Int { + bitlen := uint(mod.BitLen()) + i := new(big.Int) + for { + i.SetBytes(Bits(bitlen, false, rand)) + if i.Sign() > 0 && i.Cmp(mod) < 0 { + return i + } } } -} -// Bytes fills a slice with random bytes from rand. -func Bytes(b []byte, rand cipher.Stream) { - rand.XORKeyStream(b, b) -} + // Bytes fills a slice with random bytes from rand. + func Bytes(b []byte, rand cipher.Stream) { + rand.XORKeyStream(b, b) + } -type randstream struct { -} + type randstream struct { + } -func (r *randstream) XORKeyStream(dst, src []byte) { - // This function works only on local data, so it is - // safe against race conditions, as long as crypto/rand - // is as well. (It is.) + func (r *randstream) XORKeyStream(dst, src []byte) { + // This function works only on local data, so it is + // safe against race conditions, as long as crypto/rand + // is as well. (It is.) - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - buf := make([]byte, l) - n, err := rand.Read(buf) - if err != nil { - panic(err) - } - if n < len(buf) { - panic("short read on infinite random stream!?") - } + buf := make([]byte, l) + n, err := rand.Read(buf) + if err != nil { + panic(err) + } + if n < len(buf) { + panic("short read on infinite random stream!?") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] + } } -} -// New returns a new cipher.Stream that gets random data from Go's crypto/rand package. -// The resulting cipher.Stream can be used in multiple threads. -func New() cipher.Stream { - return &randstream{} -} + // New returns a new cipher.Stream that gets random data from Go's crypto/rand package. + // The resulting cipher.Stream can be used in multiple threads. + func New() cipher.Stream { + return &randstream{} + } -type mixedrandstream struct { - reader io.Reader - rand io.Reader -} -func (r *mixedrandstream) XORKeyStream(dst, src []byte) { + const READER_BYTES = 32; - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") + type mixedrandstream struct { + Readers []io.Reader } - remains := l + func (r *mixedrandstream) XORKeyStream(dst, src []byte) { - //get entropy from user - buf1 := make([]byte, l) - if r.reader != nil { - n1, err := r.rand.Read(buf1) - if err != nil { - panic(err) + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") } - remains -= n1 - } - //get entropy ffron crypto/rand - buf2 := make([]byte, remains) - n2, err := r.rand.Read(buf2) - if err != nil { - panic(err) - } - if n2 < len(buf2) { - panic("short read on infinite random stream!?") - } + var b bytes.Buffer + var nerr int - var buf []byte + for _, r := range r.Readers { + var buff [READER_BYTES]byte + n, err := io.ReadFull(r, buff[:]) + if err != nil { + nerr++ + } + b.Write(buff[:n]) + } - //concat the two - if l == remains { - //no additional entropy from user - buf = buf2 - } else { - buf = append(buf2, buf1...) - } + // we are ok with few sources being insecure (aka giving less than 32 bytes) + // but not all of them + if nerr == len(r.Readers) { + panic("all readers failed") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] + // create the XOF hash output + h := sha256.New() + h.Write(b.Bytes()) + seed := h.Sum(nil)[:blake2b.Size] + hash := blake2xb.New(seed) + return hash.XORKeyStream(dst, src) } -} -// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand -// package AND the user input given via Reader. -func NewStream(reader io.Reader, rand io.Reader) cipher.Stream { - return &mixedrandstream{reader: reader, rand: rand} -} + // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand + // package AND user input if given via a Reader. + func NewMixedStream(readers ...io.Reader) cipher.Stream { + if len(readers) == 0 { + readers = [1]io.Reader{rand.Reader} + } + return &mixedrandstream{readers} + } From 1105c09fd58c1e1a2ba3aa18ae7c5fc610dfb0f6 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 14:54:46 +0200 Subject: [PATCH 12/26] fixes --- share/dkg/pedersen/dkg.go | 3 ++- util/random/rand.go | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index fa87ebc7f..89679ad14 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -14,8 +14,9 @@ import ( "errors" "fmt" "io" + "crypto/cipher" - "github.com/dedis/kyber/util/random" + "github.com/PizzaWhisperer/kyber/util/random" "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" diff --git a/util/random/rand.go b/util/random/rand.go index 7a60cc85d..7a1b685a2 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,10 +5,12 @@ package random import ( "crypto/cipher" "crypto/rand" + "crypto/sha256" "io" "math/big" "golang.org/x/crypto/blake2b" "go.dedis.ch/kyber/v3/xof/blake2xb" + "bytes" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -117,14 +119,14 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { h.Write(b.Bytes()) seed := h.Sum(nil)[:blake2b.Size] hash := blake2xb.New(seed) - return hash.XORKeyStream(dst, src) + hash.XORKeyStream(dst, src) } // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand // package AND user input if given via a Reader. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { - readers = [1]io.Reader{rand.Reader} + readers = []io.Reader{rand.Reader} } return &mixedrandstream{readers} } From 70f75c56cbede454368efed76679e9ddef5ef4b2 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 14:59:48 +0200 Subject: [PATCH 13/26] identation --- util/random/rand.go | 160 ++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index 7a1b685a2..d70afc60a 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -25,108 +25,108 @@ func Bits(bitlen uint, exact bool, rand cipher.Stream) []byte { if exact { if highbits != 0 { b[0] |= 1 << (highbits - 1) - } else { - b[0] |= 0x80 - } + } else { + b[0] |= 0x80 } - return b } - - // Int chooses a uniform random big.Int less than a given modulus - func Int(mod *big.Int, rand cipher.Stream) *big.Int { - bitlen := uint(mod.BitLen()) - i := new(big.Int) - for { - i.SetBytes(Bits(bitlen, false, rand)) - if i.Sign() > 0 && i.Cmp(mod) < 0 { - return i - } + return b +} + +// Int chooses a uniform random big.Int less than a given modulus +func Int(mod *big.Int, rand cipher.Stream) *big.Int { + bitlen := uint(mod.BitLen()) + i := new(big.Int) + for { + i.SetBytes(Bits(bitlen, false, rand)) + if i.Sign() > 0 && i.Cmp(mod) < 0 { + return i } } +} - // Bytes fills a slice with random bytes from rand. - func Bytes(b []byte, rand cipher.Stream) { - rand.XORKeyStream(b, b) - } - - type randstream struct { - } +// Bytes fills a slice with random bytes from rand. +func Bytes(b []byte, rand cipher.Stream) { + rand.XORKeyStream(b, b) +} - func (r *randstream) XORKeyStream(dst, src []byte) { - // This function works only on local data, so it is - // safe against race conditions, as long as crypto/rand - // is as well. (It is.) +type randstream struct { +} - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } +func (r *randstream) XORKeyStream(dst, src []byte) { + // This function works only on local data, so it is + // safe against race conditions, as long as crypto/rand + // is as well. (It is.) - buf := make([]byte, l) - n, err := rand.Read(buf) - if err != nil { - panic(err) - } - if n < len(buf) { - panic("short read on infinite random stream!?") - } + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] - } + buf := make([]byte, l) + n, err := rand.Read(buf) + if err != nil { + panic(err) + } + if n < len(buf) { + panic("short read on infinite random stream!?") } - // New returns a new cipher.Stream that gets random data from Go's crypto/rand package. - // The resulting cipher.Stream can be used in multiple threads. - func New() cipher.Stream { - return &randstream{} + for i := 0; i < l; i++ { + dst[i] = src[i] ^ buf[i] } +} +// New returns a new cipher.Stream that gets random data from Go's crypto/rand package. +// The resulting cipher.Stream can be used in multiple threads. +func New() cipher.Stream { + return &randstream{} +} - const READER_BYTES = 32; - type mixedrandstream struct { - Readers []io.Reader - } +const READER_BYTES = 32; - func (r *mixedrandstream) XORKeyStream(dst, src []byte) { +type mixedrandstream struct { + Readers []io.Reader +} - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } +func (r *mixedrandstream) XORKeyStream(dst, src []byte) { - var b bytes.Buffer - var nerr int + l := len(dst) + if len(src) != l { + panic("XORKeyStream: mismatched buffer lengths") + } - for _, r := range r.Readers { - var buff [READER_BYTES]byte - n, err := io.ReadFull(r, buff[:]) - if err != nil { - nerr++ - } - b.Write(buff[:n]) - } + var b bytes.Buffer + var nerr int - // we are ok with few sources being insecure (aka giving less than 32 bytes) - // but not all of them - if nerr == len(r.Readers) { - panic("all readers failed") + for _, r := range r.Readers { + var buff [READER_BYTES]byte + n, err := io.ReadFull(r, buff[:]) + if err != nil { + nerr++ } + b.Write(buff[:n]) + } - // create the XOF hash output - h := sha256.New() - h.Write(b.Bytes()) - seed := h.Sum(nil)[:blake2b.Size] - hash := blake2xb.New(seed) - hash.XORKeyStream(dst, src) + // we are ok with few sources being insecure (aka giving less than 32 bytes) + // but not all of them + if nerr == len(r.Readers) { + panic("all readers failed") } - // NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand - // package AND user input if given via a Reader. - func NewMixedStream(readers ...io.Reader) cipher.Stream { - if len(readers) == 0 { - readers = []io.Reader{rand.Reader} - } - return &mixedrandstream{readers} + // create the XOF hash output + h := sha256.New() + h.Write(b.Bytes()) + seed := h.Sum(nil)[:blake2b.Size] + hash := blake2xb.New(seed) + hash.XORKeyStream(dst, src) +} + +// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand +// package AND user input if given via a Reader. +func NewMixedStream(readers ...io.Reader) cipher.Stream { + if len(readers) == 0 { + readers = []io.Reader{rand.Reader} } + return &mixedrandstream{readers} +} From 4ea8711ea0bb41c16c2a41c356b99351771554f0 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 9 Sep 2019 15:16:02 +0200 Subject: [PATCH 14/26] tests passing --- util/random/rand.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index d70afc60a..ae086902f 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -5,10 +5,9 @@ package random import ( "crypto/cipher" "crypto/rand" - "crypto/sha256" + "crypto/sha512" "io" "math/big" - "golang.org/x/crypto/blake2b" "go.dedis.ch/kyber/v3/xof/blake2xb" "bytes" ) @@ -115,9 +114,9 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // create the XOF hash output - h := sha256.New() + h := sha512.New() h.Write(b.Bytes()) - seed := h.Sum(nil)[:blake2b.Size] + seed := h.Sum(nil) hash := blake2xb.New(seed) hash.XORKeyStream(dst, src) } From 1f07ba3409e7bf0287ac5a7f22cc7d5caec26ca4 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 10:07:57 +0200 Subject: [PATCH 15/26] comments --- share/dkg/pedersen/dkg.go | 15 ++++++++------- util/random/rand.go | 17 +++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 89679ad14..196549877 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,11 +10,11 @@ package dkg import ( + "crypto/cipher" "crypto/rand" "errors" "fmt" "io" - "crypto/cipher" "github.com/PizzaWhisperer/kyber/util/random" "go.dedis.ch/kyber" @@ -82,10 +82,11 @@ type Config struct { // the number of deals required is less than what it is supposed to be. OldThreshold int - // Reader to maybe include entropy from the user during random generation + // Reader holds a user-specified entropy source used to create a random stream Reader io.Reader - // UserReaderOnly forces the dkg secret to be picked with the randomness comming - // from the user only allowing reproducibility + + // UserReaderOnly forces the dkg's secretCoeff to be picked with randomness comming + // from the user only, allowing reproducibility UserReaderOnly bool } @@ -174,10 +175,10 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { } else if !isResharing && newPresent { // fresh DKG case var randomStream cipher.Stream - // user did not provide a reader, we use entropy from crypto/rand + // empty reader, use entropy from crypto/rand if c.Reader == nil { - randomStream = random.NewMixedStream(rand.Reader) - } else { // we use the reader they gave + randomStream = random.New() + } else { // use the reader they gave, alone or combined if c.UserReaderOnly { randomStream = random.NewMixedStream(c.Reader) } else { diff --git a/util/random/rand.go b/util/random/rand.go index ae086902f..1b20554c5 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -3,13 +3,14 @@ package random import ( + "bytes" "crypto/cipher" "crypto/rand" "crypto/sha512" "io" "math/big" + "go.dedis.ch/kyber/v3/xof/blake2xb" - "bytes" ) // Bits chooses a uniform random BigInt with a given maximum BitLen. @@ -81,8 +82,8 @@ func New() cipher.Stream { return &randstream{} } - -const READER_BYTES = 32; +// READER_BYTES is how many bytes we expect from each source +const READER_BYTES = 32 type mixedrandstream struct { Readers []io.Reader @@ -107,13 +108,13 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { b.Write(buff[:n]) } - // we are ok with few sources being insecure (aka giving less than 32 bytes) - // but not all of them + // we are ok with few sources being insecure (i.e., providing less than + // READER_BYTES bytes), but not all of them if nerr == len(r.Readers) { panic("all readers failed") } - // create the XOF hash output + // create the XOF output, with hash of collected data as seed h := sha512.New() h.Write(b.Bytes()) seed := h.Sum(nil) @@ -121,8 +122,8 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { hash.XORKeyStream(dst, src) } -// NewStream returns a new cipher.Stream that gets random data from Go's crypto/rand -// package AND user input if given via a Reader. +// NewMixedStream returns a new cipher.Stream that gets random data from the specified +// readers. If no reader was given, Go's crypto/rand package is used. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { readers = []io.Reader{rand.Reader} From e18640622e242b21d5bae4e9b39549e4ec80d7d4 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 10:34:19 +0200 Subject: [PATCH 16/26] tests --- share/dkg/pedersen/dkg.go | 12 ++++---- share/dkg/pedersen/dkg_test.go | 52 +++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index 196549877..f5c909ccc 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -243,12 +243,14 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { // NewDistKeyGenerator returns a dist key generator ready to create a fresh // distributed key with the regular DKG protocol. -func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int) (*DistKeyGenerator, error) { +func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int, r io.Reader, userOnly bool) (*DistKeyGenerator, error) { c := &Config{ - Suite: suite, - Longterm: longterm, - NewNodes: participants, - Threshold: t, + Suite: suite, + Longterm: longterm, + NewNodes: participants, + Threshold: t, + Reader: r, + UserReaderOnly: userOnly, } return NewDistKeyHandler(c) } diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index f4ba4d07e..bcad1ad0a 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -3,11 +3,12 @@ package dkg import ( "crypto/rand" "fmt" + "io" mathRand "math/rand" "testing" "github.com/stretchr/testify/require" - "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber" "go.dedis.ch/kyber/v3/group/edwards25519" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" @@ -19,7 +20,10 @@ const defaultN = 5 var defaultT = vss.MinimumT(defaultN) -func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { +var defaultReader io.Reader +var defaultUserOnly = false + +func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { partPubs = make([]kyber.Point, n) partSec = make([]kyber.Scalar, n) for i := 0; i < n; i++ { @@ -29,7 +33,7 @@ func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs [] } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, r, userOnly) if err != nil { panic(err) } @@ -39,10 +43,10 @@ func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs [] } func TestDKGNewDistKeyGenerator(t *testing.T) { - partPubs, partSec, _ := generate(defaultN, defaultT) + partPubs, partSec, _ := generate(defaultN, defaultT, defaultReader, defaultUserOnly) long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT) + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, defaultReader, defaultUserOnly) require.Nil(t, err) require.NotNil(t, dkg.dealer) require.True(t, dkg.canIssue) @@ -54,12 +58,12 @@ func TestDKGNewDistKeyGenerator(t *testing.T) { require.False(t, dkg.isResharing) sec, _ := genPair() - _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT) + _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT, defaultReader, defaultUserOnly) require.Error(t, err) } func TestDKGDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] dks, err := dkg.DistKeyShare() @@ -81,7 +85,7 @@ func TestDKGDeal(t *testing.T) { } func TestDKGProcessDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] deals, err := dkg.Deals() require.Nil(t, err) @@ -136,7 +140,7 @@ func TestDKGProcessResponse(t *testing.T) { // second peer processes it and returns a complaint // first peer process the complaint - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) dkg := dkgs[0] idxRec := 1 rec := dkgs[idxRec] @@ -242,7 +246,7 @@ func TestDKGProcessResponse(t *testing.T) { func TestDKGResharingThreshold(t *testing.T) { n := 7 oldT := vss.MinimumT(n) - publics, _, dkgs := generate(n, oldT) + publics, _, dkgs := generate(n, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) newN := len(dkgs) + 1 @@ -407,7 +411,7 @@ func TestDKGThreshold(t *testing.T) { } for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal) + dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal, defaultReader, defaultUserOnly) if err != nil { panic(err) } @@ -504,7 +508,7 @@ func TestDKGThreshold(t *testing.T) { } func TestDistKeyShare(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT) + _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) for _, dkg := range dkgs { @@ -609,7 +613,7 @@ func fullExchange(t *testing.T, dkgs []*DistKeyGenerator, checkQUAL bool) { // Test resharing of a DKG to the same set of nodes func TestDKGResharing(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT) + publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -665,7 +669,7 @@ func TestDKGResharing(t *testing.T) { // Test resharing functionality with one node less func TestDKGResharingRemoveNode(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT) + publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) newN := len(publics) - 1 @@ -728,7 +732,7 @@ func TestDKGResharingRemoveNode(t *testing.T) { func TestDKGResharingNewNodesThreshold(t *testing.T) { oldN := defaultN oldT := vss.MinimumT(oldN) - oldPubs, oldPrivs, dkgs := generate(oldN, oldT) + oldPubs, oldPrivs, dkgs := generate(oldN, oldT, defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -892,7 +896,7 @@ func TestDKGResharingNewNodesThreshold(t *testing.T) { // Test resharing to a different set of nodes with one common func TestDKGResharingNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1068,7 +1072,7 @@ func TestDKGResharingNewNodes(t *testing.T) { } func TestDKGResharingPartialNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1241,3 +1245,17 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.NoError(t, err) require.Equal(t, oldSecret.String(), newSecret.String()) } + +func TestDKGUserOnly(t *testing.T) { + r := string.NewReader("This is the seed to my custom reader, please use it well.") + partPubs, partSec, _ := generate(defaultN, defaultT, r, true) + + long := partSec[0] + dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + require.Nil(t, err) + require.NotNil(t, dkg1.dealer) + dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + require.Nil(t, err) + require.NotNil(t, dkg1.dealer) + require.True(t, dkg1.dealer.secret.Equal(dkg2.dealer.secret)) +} From dc1dee967b0a3080c0d34272433ae7f918e7a637 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 10 Sep 2019 13:13:44 +0200 Subject: [PATCH 17/26] testing --- go.mod | 10 +++++++++- go.sum | 22 +++++++++++++--------- share/dkg/pedersen/dkg_test.go | 33 +++++++++++++++++++++++++++------ util/random/rand.go | 7 +++---- 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 6957a4fea..c63632d4e 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,18 @@ module go.dedis.ch/kyber/v3 require ( - github.com/stretchr/objx v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.4.0 go.dedis.ch/fixbuf v1.0.3 +<<<<<<< HEAD go.dedis.ch/protobuf v1.0.7 golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b golang.org/x/sys v0.0.0-20190124100055-b90733256f2e +======= + go.dedis.ch/protobuf v1.0.6 + golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 + golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect +>>>>>>> testing ) diff --git a/go.sum b/go.sum index a724d9799..cc48ead32 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,18 @@ 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/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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= @@ -20,26 +26,24 @@ go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI go.dedis.ch/kyber/v3 v3.0.0-pre2/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= +go.dedis.ch/protobuf v1.0.6 h1:E61p2XjYbYrTf3WeXE8M8Ui5WA3hX/NgbHHi5D0FLxI= go.dedis.ch/protobuf v1.0.6/go.mod h1:YHYXW6dQ9p2iJ3f+2fxKnOpjGx0MvL4cwpg1RVNXaV8= >>>>>>> impl XOR mixed rand golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 h1:mgAKeshyNqWKdENOnQsg+8dRTwZFIwFaO3HNl52sweA= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b h1:3S2h5FadpNr0zUUCVZjlKIEYF+KaX/OBplTGo89CYHI= +golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index bcad1ad0a..c6b800b06 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -4,7 +4,10 @@ import ( "crypto/rand" "fmt" "io" + "io/ioutil" + "bytes" mathRand "math/rand" + "strings" "testing" "github.com/stretchr/testify/require" @@ -31,9 +34,15 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par partPubs[i] = pub partSec[i] = sec } + //if there is a reader we need to make a copy for each dkg + var b []byte + if r != nil { + b, _ = ioutil.ReadAll(r) + } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, r, userOnly) + rcopy := bytes.NewReader(b) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, rcopy, userOnly) if err != nil { panic(err) } @@ -1246,16 +1255,28 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.Equal(t, oldSecret.String(), newSecret.String()) } +func TestDKGMixedEntropy(t *testing.T) { + r := strings.NewReader("some io.Reader stream to be read") + partPubs, partSec, _ := generate(defaultN, defaultT, r, defaultUserOnly) + + long := partSec[0] + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, defaultUserOnly) + require.Nil(t, err) + require.NotNil(t, dkg.dealer) +} + func TestDKGUserOnly(t *testing.T) { - r := string.NewReader("This is the seed to my custom reader, please use it well.") + r := strings.NewReader("some io.Reader stream to be read") partPubs, partSec, _ := generate(defaultN, defaultT, r, true) long := partSec[0] - dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + r1 := strings.NewReader("some io.Reader stream to be read") + dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r1, true) require.Nil(t, err) require.NotNil(t, dkg1.dealer) - dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, true) + r2 := strings.NewReader("some io.Reader stream to be read") + dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r2, true) require.Nil(t, err) - require.NotNil(t, dkg1.dealer) - require.True(t, dkg1.dealer.secret.Equal(dkg2.dealer.secret)) + require.NotNil(t, dkg2.dealer) + require.True(t, dkg1.dealer.PrivatePoly().Secret().Equal(dkg2.dealer.PrivatePoly().Secret())) } diff --git a/util/random/rand.go b/util/random/rand.go index 1b20554c5..d3ed56796 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -98,10 +98,9 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { var b bytes.Buffer var nerr int - - for _, r := range r.Readers { - var buff [READER_BYTES]byte - n, err := io.ReadFull(r, buff[:]) + for _, reader := range r.Readers { + buff := make([]byte, READER_BYTES) + n, err := io.ReadFull(reader, buff) if err != nil { nerr++ } From a2c813866552331657f1cb391b9639539f4238b8 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Fri, 20 Sep 2019 12:06:00 +0200 Subject: [PATCH 18/26] rand pr --- share/dkg/pedersen/dkg.go | 39 ++++-------------- share/dkg/pedersen/dkg_test.go | 73 ++++++++-------------------------- util/random/rand.go | 17 +++++--- 3 files changed, 37 insertions(+), 92 deletions(-) diff --git a/share/dkg/pedersen/dkg.go b/share/dkg/pedersen/dkg.go index f5c909ccc..6d7bc5aa3 100644 --- a/share/dkg/pedersen/dkg.go +++ b/share/dkg/pedersen/dkg.go @@ -10,14 +10,11 @@ package dkg import ( - "crypto/cipher" - "crypto/rand" "errors" "fmt" - "io" - "github.com/PizzaWhisperer/kyber/util/random" - "go.dedis.ch/kyber" + "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" "go.dedis.ch/kyber/v3/sign/schnorr" @@ -81,13 +78,6 @@ type Config struct { // absent) when doing a resharing to avoid a downgrade attack, where a resharing // the number of deals required is less than what it is supposed to be. OldThreshold int - - // Reader holds a user-specified entropy source used to create a random stream - Reader io.Reader - - // UserReaderOnly forces the dkg's secretCoeff to be picked with randomness comming - // from the user only, allowing reproducibility - UserReaderOnly bool } // DistKeyGenerator is the struct that runs the DKG protocol. @@ -174,18 +164,7 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { canIssue = true } else if !isResharing && newPresent { // fresh DKG case - var randomStream cipher.Stream - // empty reader, use entropy from crypto/rand - if c.Reader == nil { - randomStream = random.New() - } else { // use the reader they gave, alone or combined - if c.UserReaderOnly { - randomStream = random.NewMixedStream(c.Reader) - } else { - randomStream = random.NewMixedStream(c.Reader, rand.Reader) - } - } - secretCoeff := c.Suite.Scalar().Pick(randomStream) + secretCoeff := c.Suite.Scalar().Pick(c.Suite.RandomStream()) dealer, err = vss.NewDealer(c.Suite, c.Longterm, secretCoeff, c.NewNodes, newThreshold) canIssue = true c.OldNodes = c.NewNodes @@ -243,14 +222,12 @@ func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { // NewDistKeyGenerator returns a dist key generator ready to create a fresh // distributed key with the regular DKG protocol. -func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int, r io.Reader, userOnly bool) (*DistKeyGenerator, error) { +func NewDistKeyGenerator(suite Suite, longterm kyber.Scalar, participants []kyber.Point, t int) (*DistKeyGenerator, error) { c := &Config{ - Suite: suite, - Longterm: longterm, - NewNodes: participants, - Threshold: t, - Reader: r, - UserReaderOnly: userOnly, + Suite: suite, + Longterm: longterm, + NewNodes: participants, + Threshold: t, } return NewDistKeyHandler(c) } diff --git a/share/dkg/pedersen/dkg_test.go b/share/dkg/pedersen/dkg_test.go index c6b800b06..f4ba4d07e 100644 --- a/share/dkg/pedersen/dkg_test.go +++ b/share/dkg/pedersen/dkg_test.go @@ -3,15 +3,11 @@ package dkg import ( "crypto/rand" "fmt" - "io" - "io/ioutil" - "bytes" mathRand "math/rand" - "strings" "testing" "github.com/stretchr/testify/require" - "go.dedis.ch/kyber" + "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/group/edwards25519" "go.dedis.ch/kyber/v3/share" vss "go.dedis.ch/kyber/v3/share/vss/pedersen" @@ -23,10 +19,7 @@ const defaultN = 5 var defaultT = vss.MinimumT(defaultN) -var defaultReader io.Reader -var defaultUserOnly = false - -func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { +func generate(n, t int) (partPubs []kyber.Point, partSec []kyber.Scalar, dkgs []*DistKeyGenerator) { partPubs = make([]kyber.Point, n) partSec = make([]kyber.Scalar, n) for i := 0; i < n; i++ { @@ -34,15 +27,9 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par partPubs[i] = pub partSec[i] = sec } - //if there is a reader we need to make a copy for each dkg - var b []byte - if r != nil { - b, _ = ioutil.ReadAll(r) - } dkgs = make([]*DistKeyGenerator, n) for i := 0; i < n; i++ { - rcopy := bytes.NewReader(b) - dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t, rcopy, userOnly) + dkg, err := NewDistKeyGenerator(suite, partSec[i], partPubs, t) if err != nil { panic(err) } @@ -52,10 +39,10 @@ func generate(n, t int, r io.Reader, userOnly bool) (partPubs []kyber.Point, par } func TestDKGNewDistKeyGenerator(t *testing.T) { - partPubs, partSec, _ := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + partPubs, partSec, _ := generate(defaultN, defaultT) long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, defaultReader, defaultUserOnly) + dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT) require.Nil(t, err) require.NotNil(t, dkg.dealer) require.True(t, dkg.canIssue) @@ -67,12 +54,12 @@ func TestDKGNewDistKeyGenerator(t *testing.T) { require.False(t, dkg.isResharing) sec, _ := genPair() - _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT, defaultReader, defaultUserOnly) + _, err = NewDistKeyGenerator(suite, sec, partPubs, defaultT) require.Error(t, err) } func TestDKGDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] dks, err := dkg.DistKeyShare() @@ -94,7 +81,7 @@ func TestDKGDeal(t *testing.T) { } func TestDKGProcessDeal(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] deals, err := dkg.Deals() require.Nil(t, err) @@ -149,7 +136,7 @@ func TestDKGProcessResponse(t *testing.T) { // second peer processes it and returns a complaint // first peer process the complaint - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) dkg := dkgs[0] idxRec := 1 rec := dkgs[idxRec] @@ -255,7 +242,7 @@ func TestDKGProcessResponse(t *testing.T) { func TestDKGResharingThreshold(t *testing.T) { n := 7 oldT := vss.MinimumT(n) - publics, _, dkgs := generate(n, oldT, defaultReader, defaultUserOnly) + publics, _, dkgs := generate(n, oldT) fullExchange(t, dkgs, true) newN := len(dkgs) + 1 @@ -420,7 +407,7 @@ func TestDKGThreshold(t *testing.T) { } for i := 0; i < n; i++ { - dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal, defaultReader, defaultUserOnly) + dkg, err := NewDistKeyGenerator(suite, privates[i], publics, newTotal) if err != nil { panic(err) } @@ -517,7 +504,7 @@ func TestDKGThreshold(t *testing.T) { } func TestDistKeyShare(t *testing.T) { - _, _, dkgs := generate(defaultN, defaultT, defaultReader, defaultUserOnly) + _, _, dkgs := generate(defaultN, defaultT) fullExchange(t, dkgs, true) for _, dkg := range dkgs { @@ -622,7 +609,7 @@ func fullExchange(t *testing.T, dkgs []*DistKeyGenerator, checkQUAL bool) { // Test resharing of a DKG to the same set of nodes func TestDKGResharing(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) + publics, secrets, dkgs := generate(defaultN, oldT) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -678,7 +665,7 @@ func TestDKGResharing(t *testing.T) { // Test resharing functionality with one node less func TestDKGResharingRemoveNode(t *testing.T) { oldT := vss.MinimumT(defaultN) - publics, secrets, dkgs := generate(defaultN, oldT, defaultReader, defaultUserOnly) + publics, secrets, dkgs := generate(defaultN, oldT) fullExchange(t, dkgs, true) newN := len(publics) - 1 @@ -741,7 +728,7 @@ func TestDKGResharingRemoveNode(t *testing.T) { func TestDKGResharingNewNodesThreshold(t *testing.T) { oldN := defaultN oldT := vss.MinimumT(oldN) - oldPubs, oldPrivs, dkgs := generate(oldN, oldT, defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(oldN, oldT) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -905,7 +892,7 @@ func TestDKGResharingNewNodesThreshold(t *testing.T) { // Test resharing to a different set of nodes with one common func TestDKGResharingNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1081,7 +1068,7 @@ func TestDKGResharingNewNodes(t *testing.T) { } func TestDKGResharingPartialNewNodes(t *testing.T) { - oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN), defaultReader, defaultUserOnly) + oldPubs, oldPrivs, dkgs := generate(defaultN, vss.MinimumT(defaultN)) fullExchange(t, dkgs, true) shares := make([]*DistKeyShare, len(dkgs)) @@ -1254,29 +1241,3 @@ func TestDKGResharingPartialNewNodes(t *testing.T) { require.NoError(t, err) require.Equal(t, oldSecret.String(), newSecret.String()) } - -func TestDKGMixedEntropy(t *testing.T) { - r := strings.NewReader("some io.Reader stream to be read") - partPubs, partSec, _ := generate(defaultN, defaultT, r, defaultUserOnly) - - long := partSec[0] - dkg, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r, defaultUserOnly) - require.Nil(t, err) - require.NotNil(t, dkg.dealer) -} - -func TestDKGUserOnly(t *testing.T) { - r := strings.NewReader("some io.Reader stream to be read") - partPubs, partSec, _ := generate(defaultN, defaultT, r, true) - - long := partSec[0] - r1 := strings.NewReader("some io.Reader stream to be read") - dkg1, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r1, true) - require.Nil(t, err) - require.NotNil(t, dkg1.dealer) - r2 := strings.NewReader("some io.Reader stream to be read") - dkg2, err := NewDistKeyGenerator(suite, long, partPubs, defaultT, r2, true) - require.Nil(t, err) - require.NotNil(t, dkg2.dealer) - require.True(t, dkg1.dealer.PrivatePoly().Secret().Equal(dkg2.dealer.PrivatePoly().Secret())) -} diff --git a/util/random/rand.go b/util/random/rand.go index d3ed56796..8c9b99ba4 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -85,6 +85,10 @@ func New() cipher.Stream { // READER_BYTES is how many bytes we expect from each source const READER_BYTES = 32 +// MIXEDRAND_HASH is the hash used in XORKeyStream to mix all entropy sources together. +// sha512 is chosen as its digest is 64 bytes long, matching the length of blake2xb's seed. +var MIXEDRAND_HASH = sha512.New + type mixedrandstream struct { Readers []io.Reader } @@ -114,15 +118,18 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // create the XOF output, with hash of collected data as seed - h := sha512.New() + h := MIXEDRAND_HASH() h.Write(b.Bytes()) seed := h.Sum(nil) - hash := blake2xb.New(seed) - hash.XORKeyStream(dst, src) + blake2 := blake2xb.New(seed) + blake2.XORKeyStream(dst, src) } -// NewMixedStream returns a new cipher.Stream that gets random data from the specified -// readers. If no reader was given, Go's crypto/rand package is used. +// NewMixedStream returns a new cipher.Stream that gets random data from the given +// readers. If no reader was provided, Go's crypto/rand package is used. +// In order to use every source, it tries to read 32 bytes from each, and mix it +// all together into a string of valid length via hashing. This string is then +// used as a seed for blake2, which is used to perform the final XOR. func NewMixedStream(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { readers = []io.Reader{rand.Reader} From 9211a29dccdf7c3eeca2a86086990cffab8aabf7 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Fri, 20 Sep 2019 12:15:07 +0200 Subject: [PATCH 19/26] comment --- util/random/rand.go | 1 + 1 file changed, 1 insertion(+) diff --git a/util/random/rand.go b/util/random/rand.go index 8c9b99ba4..5e08e5719 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -100,6 +100,7 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { panic("XORKeyStream: mismatched buffer lengths") } +// try to read 32 bytes from all readers and write them in a buffer var b bytes.Buffer var nerr int for _, reader := range r.Readers { From febcc25bdc6379c75c43c58a5e83991af14024f3 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Fri, 20 Sep 2019 12:21:26 +0200 Subject: [PATCH 20/26] modules --- go.mod | 8 -------- go.sum | 25 +------------------------ 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/go.mod b/go.mod index c63632d4e..fc361410f 100644 --- a/go.mod +++ b/go.mod @@ -2,17 +2,9 @@ module go.dedis.ch/kyber/v3 require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.4.0 go.dedis.ch/fixbuf v1.0.3 -<<<<<<< HEAD go.dedis.ch/protobuf v1.0.7 golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b golang.org/x/sys v0.0.0-20190124100055-b90733256f2e -======= - go.dedis.ch/protobuf v1.0.6 - golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 - golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ->>>>>>> testing ) diff --git a/go.sum b/go.sum index cc48ead32..cfb0c50fb 100644 --- a/go.sum +++ b/go.sum @@ -2,11 +2,6 @@ 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/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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -16,34 +11,16 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= -<<<<<<< HEAD go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7 h1:wRUEiq3u0/vBhLjcw9CmAVrol+BnDyq2M0XLukdphyI= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= -======= -go.dedis.ch/kyber/v3 v3.0.0-pre2/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= -go.dedis.ch/protobuf v1.0.5 h1:EbF1czEKICxf5KY8Tm7wMF28hcOQbB6yk4IybIFWTYE= -go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= -go.dedis.ch/protobuf v1.0.6 h1:E61p2XjYbYrTf3WeXE8M8Ui5WA3hX/NgbHHi5D0FLxI= -go.dedis.ch/protobuf v1.0.6/go.mod h1:YHYXW6dQ9p2iJ3f+2fxKnOpjGx0MvL4cwpg1RVNXaV8= ->>>>>>> impl XOR mixed rand golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 h1:mgAKeshyNqWKdENOnQsg+8dRTwZFIwFaO3HNl52sweA= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b h1:3S2h5FadpNr0zUUCVZjlKIEYF+KaX/OBplTGo89CYHI= -golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From d8e994ea1ef349bb27a0e691c79a14c6491d58cb Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 7 Oct 2019 18:40:26 +0200 Subject: [PATCH 21/26] tests --- util/random/rand.go | 2 +- util/random/rand_test.go | 73 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 util/random/rand_test.go diff --git a/util/random/rand.go b/util/random/rand.go index 5e08e5719..2b37de73e 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -100,7 +100,7 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { panic("XORKeyStream: mismatched buffer lengths") } -// try to read 32 bytes from all readers and write them in a buffer + // try to read 32 bytes from all readers and write them in a buffer var b bytes.Buffer var nerr int for _, reader := range r.Readers { diff --git a/util/random/rand_test.go b/util/random/rand_test.go new file mode 100644 index 000000000..99fa7b1aa --- /dev/null +++ b/util/random/rand_test.go @@ -0,0 +1,73 @@ +package random + +import ( + "bytes" + "crypto/rand" + "strings" + "testing" +) + +const size = 32 + +func TestMixedEntropy(t *testing.T) { + r := strings.NewReader("some io.Reader stream to be used for testing") + cipher := NewMixedStream(r, rand.Reader) + + src := make([]byte, size) + copy(src, []byte("source buffer")) + dst := make([]byte, size+1) + dst[len(dst)-1] = 0xff + + cipher.XORKeyStream(dst[:len(dst)-1], src) + if len(src) > 0 && bytes.Equal(src, dst[0:len(src)]) { + t.Fatal("src and dst should not be equal") + } + if dst[len(dst)-1] != 0xff { + t.Fatal("last byte of dst chagned") + } +} + +func TestEmptyReader(t *testing.T) { + //expecting a panic + defer func() { + if r := recover(); r == nil { + t.Fatal("code did not panicked but should have") + } + }() + + r := strings.NewReader("too small io.Reader") + cipher := NewMixedStream(r) + src := make([]byte, size) + copy(src, []byte("hello")) + dst := make([]byte, size) + cipher.XORKeyStream(dst, src) +} + +func TestCryptoOnly(t *testing.T) { + cipher := NewMixedStream() + src := make([]byte, size) + copy(src, []byte("hello")) + dst1 := make([]byte, size) + cipher.XORKeyStream(dst1, src) + dst2 := make([]byte, size) + cipher.XORKeyStream(dst2, src) + if bytes.Equal(dst1, dst2) { + t.Fatal("dst1 and dst2 should not be equal") + } +} + +func TestUserOnly(t *testing.T) { + r1 := strings.NewReader("some io.Reader stream to be used for testing") + cipher1 := NewMixedStream(r1) + src := make([]byte, size) + copy(src, []byte("hello")) + dst1 := make([]byte, size) + cipher1.XORKeyStream(dst1, src) + r2 := strings.NewReader("some io.Reader stream to be used for testing") + cipher2 := NewMixedStream(r2) + dst2 := make([]byte, size) + cipher2.XORKeyStream(dst2, src) + if !bytes.Equal(dst1, dst2) { + t.Fatal("dst1/dst2 should be equal") + } +} From 96e27debc0e707fef6451a16097c142f85b4a13d Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Mon, 7 Oct 2019 18:50:27 +0200 Subject: [PATCH 22/26] tests again --- util/random/rand_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/util/random/rand_test.go b/util/random/rand_test.go index 99fa7b1aa..eddc43dda 100644 --- a/util/random/rand_test.go +++ b/util/random/rand_test.go @@ -57,17 +57,30 @@ func TestCryptoOnly(t *testing.T) { } func TestUserOnly(t *testing.T) { - r1 := strings.NewReader("some io.Reader stream to be used for testing") - cipher1 := NewMixedStream(r1) + seed := "some io.Reader stream to be used for testing" + cipher1 := NewMixedStream(strings.NewReader(seed)) src := make([]byte, size) copy(src, []byte("hello")) dst1 := make([]byte, size) cipher1.XORKeyStream(dst1, src) - r2 := strings.NewReader("some io.Reader stream to be used for testing") - cipher2 := NewMixedStream(r2) + cipher2 := NewMixedStream(strings.NewReader(seed)) dst2 := make([]byte, size) cipher2.XORKeyStream(dst2, src) if !bytes.Equal(dst1, dst2) { t.Fatal("dst1/dst2 should be equal") } } + +func TestIncorrectSize(t *testing.T) { + //expecting a panic + defer func() { + if r := recover(); r == nil { + t.Fatal("code did not panicked but should have") + } + }() + cipher := NewMixedStream() + src := make([]byte, size) + copy(src, []byte("hello")) + dst := make([]byte, size+1) + cipher.XORKeyStream(dst, src) +} From ea71c29a7d26c9afbe3c8dc091ddac521253f1fd Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 8 Oct 2019 12:42:51 +0200 Subject: [PATCH 23/26] modifs according to reviews --- util/random/rand.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index 2b37de73e..13871b8bc 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -85,9 +85,9 @@ func New() cipher.Stream { // READER_BYTES is how many bytes we expect from each source const READER_BYTES = 32 -// MIXEDRAND_HASH is the hash used in XORKeyStream to mix all entropy sources together. +// MixedrandHash is the hash used in XORKeyStream to mix all entropy sources together. // sha512 is chosen as its digest is 64 bytes long, matching the length of blake2xb's seed. -var MIXEDRAND_HASH = sha512.New +var MixedrandHash = sha512.New type mixedrandstream struct { Readers []io.Reader @@ -103,8 +103,8 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { // try to read 32 bytes from all readers and write them in a buffer var b bytes.Buffer var nerr int + buff := make([]byte, READER_BYTES) for _, reader := range r.Readers { - buff := make([]byte, READER_BYTES) n, err := io.ReadFull(reader, buff) if err != nil { nerr++ @@ -119,7 +119,7 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // create the XOF output, with hash of collected data as seed - h := MIXEDRAND_HASH() + h := MixedrandHash() h.Write(b.Bytes()) seed := h.Sum(nil) blake2 := blake2xb.New(seed) From 93efc4f605eccd9d74cb6de04a9f67b0bb5e0ab3 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Tue, 8 Oct 2019 15:49:47 +0200 Subject: [PATCH 24/26] merge New and NewRandMixed --- util/random/rand.go | 16 ++++++---------- util/random/rand_test.go | 12 ++++++------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index 13871b8bc..9b9b15e06 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -76,12 +76,6 @@ func (r *randstream) XORKeyStream(dst, src []byte) { } } -// New returns a new cipher.Stream that gets random data from Go's crypto/rand package. -// The resulting cipher.Stream can be used in multiple threads. -func New() cipher.Stream { - return &randstream{} -} - // READER_BYTES is how many bytes we expect from each source const READER_BYTES = 32 @@ -126,14 +120,16 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { blake2.XORKeyStream(dst, src) } -// NewMixedStream returns a new cipher.Stream that gets random data from the given +// New returns a new cipher.Stream that gets random data from the given // readers. If no reader was provided, Go's crypto/rand package is used. // In order to use every source, it tries to read 32 bytes from each, and mix it // all together into a string of valid length via hashing. This string is then // used as a seed for blake2, which is used to perform the final XOR. -func NewMixedStream(readers ...io.Reader) cipher.Stream { +// The resulting cipher.Stream can be used in multiple threads. +func New(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { - readers = []io.Reader{rand.Reader} + return &randstream{} + } else { + return &mixedrandstream{readers} } - return &mixedrandstream{readers} } diff --git a/util/random/rand_test.go b/util/random/rand_test.go index eddc43dda..274457f88 100644 --- a/util/random/rand_test.go +++ b/util/random/rand_test.go @@ -11,7 +11,7 @@ const size = 32 func TestMixedEntropy(t *testing.T) { r := strings.NewReader("some io.Reader stream to be used for testing") - cipher := NewMixedStream(r, rand.Reader) + cipher := New(r, rand.Reader) src := make([]byte, size) copy(src, []byte("source buffer")) @@ -36,7 +36,7 @@ func TestEmptyReader(t *testing.T) { }() r := strings.NewReader("too small io.Reader") - cipher := NewMixedStream(r) + cipher := New(r) src := make([]byte, size) copy(src, []byte("hello")) dst := make([]byte, size) @@ -44,7 +44,7 @@ func TestEmptyReader(t *testing.T) { } func TestCryptoOnly(t *testing.T) { - cipher := NewMixedStream() + cipher := New() src := make([]byte, size) copy(src, []byte("hello")) dst1 := make([]byte, size) @@ -58,12 +58,12 @@ func TestCryptoOnly(t *testing.T) { func TestUserOnly(t *testing.T) { seed := "some io.Reader stream to be used for testing" - cipher1 := NewMixedStream(strings.NewReader(seed)) + cipher1 := New(strings.NewReader(seed)) src := make([]byte, size) copy(src, []byte("hello")) dst1 := make([]byte, size) cipher1.XORKeyStream(dst1, src) - cipher2 := NewMixedStream(strings.NewReader(seed)) + cipher2 := New(strings.NewReader(seed)) dst2 := make([]byte, size) cipher2.XORKeyStream(dst2, src) if !bytes.Equal(dst1, dst2) { @@ -78,7 +78,7 @@ func TestIncorrectSize(t *testing.T) { t.Fatal("code did not panicked but should have") } }() - cipher := NewMixedStream() + cipher := New() src := make([]byte, size) copy(src, []byte("hello")) dst := make([]byte, size+1) From 7678124b478f7ed5ce5230ad732431e8ac638769 Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Wed, 9 Oct 2019 22:11:19 +0200 Subject: [PATCH 25/26] revert mod files and small fixes --- go.mod | 3 +-- go.sum | 8 ------ util/random/rand.go | 53 +++++++++------------------------------- util/random/rand_test.go | 2 +- 4 files changed, 14 insertions(+), 52 deletions(-) diff --git a/go.mod b/go.mod index fc361410f..0a7e728dc 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,7 @@ module go.dedis.ch/kyber/v3 require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.3.0 go.dedis.ch/fixbuf v1.0.3 go.dedis.ch/protobuf v1.0.7 golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b diff --git a/go.sum b/go.sum index cfb0c50fb..72b5df637 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,10 @@ 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/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/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/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= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -20,7 +16,3 @@ 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= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/util/random/rand.go b/util/random/rand.go index 9b9b15e06..3cc4f383f 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -49,55 +49,28 @@ func Bytes(b []byte, rand cipher.Stream) { rand.XORKeyStream(b, b) } -type randstream struct { -} - -func (r *randstream) XORKeyStream(dst, src []byte) { - // This function works only on local data, so it is - // safe against race conditions, as long as crypto/rand - // is as well. (It is.) - - l := len(dst) - if len(src) != l { - panic("XORKeyStream: mismatched buffer lengths") - } - - buf := make([]byte, l) - n, err := rand.Read(buf) - if err != nil { - panic(err) - } - if n < len(buf) { - panic("short read on infinite random stream!?") - } - - for i := 0; i < l; i++ { - dst[i] = src[i] ^ buf[i] - } -} - -// READER_BYTES is how many bytes we expect from each source -const READER_BYTES = 32 - // MixedrandHash is the hash used in XORKeyStream to mix all entropy sources together. // sha512 is chosen as its digest is 64 bytes long, matching the length of blake2xb's seed. var MixedrandHash = sha512.New -type mixedrandstream struct { +type randstream struct { Readers []io.Reader } -func (r *mixedrandstream) XORKeyStream(dst, src []byte) { +func (r *randstream) XORKeyStream(dst, src []byte) { l := len(dst) if len(src) != l { panic("XORKeyStream: mismatched buffer lengths") } - // try to read 32 bytes from all readers and write them in a buffer + // readerBytes is how many bytes we expect from each source + readerBytes := 32 + + // try to read readerBytes bytes from all readers and write them in a buffer var b bytes.Buffer var nerr int - buff := make([]byte, READER_BYTES) + buff := make([]byte, readerBytes) for _, reader := range r.Readers { n, err := io.ReadFull(reader, buff) if err != nil { @@ -107,7 +80,7 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { } // we are ok with few sources being insecure (i.e., providing less than - // READER_BYTES bytes), but not all of them + // readerBytes bytes), but not all of them if nerr == len(r.Readers) { panic("all readers failed") } @@ -122,14 +95,12 @@ func (r *mixedrandstream) XORKeyStream(dst, src []byte) { // New returns a new cipher.Stream that gets random data from the given // readers. If no reader was provided, Go's crypto/rand package is used. -// In order to use every source, it tries to read 32 bytes from each, and mix it -// all together into a string of valid length via hashing. This string is then -// used as a seed for blake2, which is used to perform the final XOR. +// Otherwise, for each source, 32 bytes are read. They are concatenated and +// then hashed, and the resulting hash is used as a seed to a PRNG. // The resulting cipher.Stream can be used in multiple threads. func New(readers ...io.Reader) cipher.Stream { if len(readers) == 0 { - return &randstream{} - } else { - return &mixedrandstream{readers} + readers = []io.Reader{rand.Reader} } + return &randstream{readers} } diff --git a/util/random/rand_test.go b/util/random/rand_test.go index 274457f88..42b50ac03 100644 --- a/util/random/rand_test.go +++ b/util/random/rand_test.go @@ -78,7 +78,7 @@ func TestIncorrectSize(t *testing.T) { t.Fatal("code did not panicked but should have") } }() - cipher := New() + cipher := New(rand.Reader) src := make([]byte, size) copy(src, []byte("hello")) dst := make([]byte, size+1) From a4f6282c78ac32274505aed295213d053a60449c Mon Sep 17 00:00:00 2001 From: PizzaWhisperer Date: Wed, 9 Oct 2019 22:24:00 +0200 Subject: [PATCH 26/26] moving and changing hash --- util/random/rand.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/util/random/rand.go b/util/random/rand.go index 3cc4f383f..b7e9a7e7c 100644 --- a/util/random/rand.go +++ b/util/random/rand.go @@ -6,7 +6,7 @@ import ( "bytes" "crypto/cipher" "crypto/rand" - "crypto/sha512" + "crypto/sha256" "io" "math/big" @@ -49,10 +49,6 @@ func Bytes(b []byte, rand cipher.Stream) { rand.XORKeyStream(b, b) } -// MixedrandHash is the hash used in XORKeyStream to mix all entropy sources together. -// sha512 is chosen as its digest is 64 bytes long, matching the length of blake2xb's seed. -var MixedrandHash = sha512.New - type randstream struct { Readers []io.Reader } @@ -86,7 +82,7 @@ func (r *randstream) XORKeyStream(dst, src []byte) { } // create the XOF output, with hash of collected data as seed - h := MixedrandHash() + h := sha256.New() h.Write(b.Bytes()) seed := h.Sum(nil) blake2 := blake2xb.New(seed)