From 7f74eab48a8c5064870b24cf43395781e035fb46 Mon Sep 17 00:00:00 2001 From: Patrick McClurg Date: Wed, 3 Aug 2022 17:21:02 +0200 Subject: [PATCH 1/5] Consume IBE hash function from the suite Consume IBE hash function from the suite rather than manually using blake2s XOF --- encrypt/ibe/ibe.go | 59 ++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/encrypt/ibe/ibe.go b/encrypt/ibe/ibe.go index 22ff22e2f..dbfbdb550 100644 --- a/encrypt/ibe/ibe.go +++ b/encrypt/ibe/ibe.go @@ -1,12 +1,10 @@ package ibe import ( + "bytes" "crypto/rand" "errors" "fmt" - - "golang.org/x/crypto/blake2s" - "github.com/drand/kyber" "github.com/drand/kyber/pairing" ) @@ -71,14 +69,14 @@ func Encrypt(s pairing.Suite, master kyber.Point, ID, msg []byte) (*Ciphertext, // 5. Compute V = sigma XOR H2(rGid) rGid := Gid.Mul(r, Gid) // even in Gt, it's additive notation - hrGid, err := gtToHash(rGid, len(msg), H2Tag()) + hrGid, err := gtToHash(s, rGid, len(msg), H2Tag()) if err != nil { return nil, err } V := xor(sigma, hrGid) // 6. Compute M XOR H(sigma) - hsigma, err := h4(sigma, len(msg)) + hsigma, err := h4(s, sigma, len(msg)) if err != nil { return nil, err } @@ -94,7 +92,7 @@ func Encrypt(s pairing.Suite, master kyber.Point, ID, msg []byte) (*Ciphertext, func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error) { // 1. Compute sigma = V XOR H2(e(rP,private)) gidt := s.Pair(c.U, private) - hgidt, err := gtToHash(gidt, len(c.W), H2Tag()) + hgidt, err := gtToHash(s, gidt, len(c.W), H2Tag()) if err != nil { return nil, err } @@ -104,7 +102,7 @@ func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error sigma := xor(hgidt, c.V) // 2. Compute M = W XOR H4(sigma) - hsigma, err := h4(sigma, len(c.W)) + hsigma, err := h4(s, sigma, len(c.W)) if err != nil { return nil, err } @@ -124,14 +122,11 @@ func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error } -const maxSize = 1 << 10 - // hash sigma and msg to get r func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) { - h3, err := blake2s.NewXOF(maxSize, nil) - if err != nil { - panic(err) - } + h3 := s.Hash() + h3.Reset() + if _, err := h3.Write(H3Tag()); err != nil { return nil, fmt.Errorf("err hashing h3 tag: %v", err) } @@ -143,38 +138,46 @@ func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) { if !ok { panic("scalar can't be created from hash") } - return hashable.Hash(s, h3) + + h3Reader := bytes.NewReader(h3.Sum(make([]byte, h3.Size()))) + + return hashable.Hash(s, h3Reader) } -func h4(sigma []byte, length int) ([]byte, error) { - h4, err := blake2s.NewXOF(maxSize, nil) - if err != nil { - panic(err) - } +func h4(s pairing.Suite, sigma []byte, length int) ([]byte, error) { + h4 := s.Hash() + h4.Reset() + if _, err := h4.Write(H4Tag()); err != nil { return nil, fmt.Errorf("err writing h4tag: %v", err) } if _, err := h4.Write(sigma); err != nil { return nil, fmt.Errorf("err writing sigma to h4: %v", err) } + + h4Reader := bytes.NewReader(h4.Sum(make([]byte, h4.Size()))) h4sigma := make([]byte, length) - if _, err := h4.Read(h4sigma); err != nil { + + if _, err := h4Reader.Read(h4sigma); err != nil { return nil, fmt.Errorf("err reading from h4: %v", err) } return h4sigma, nil } -func gtToHash(gt kyber.Point, length int, dst []byte) ([]byte, error) { - xof, err := blake2s.NewXOF(maxSize, nil) - if err != nil { - return nil, err - } - if _, err := xof.Write(dst); err != nil { +func gtToHash(s pairing.Suite, gt kyber.Point, length int, dst []byte) ([]byte, error) { + hash := s.Hash() + hash.Reset() + + if _, err := hash.Write(dst); err != nil { return nil, errors.New("err writing dst to gtHash") } - gt.MarshalTo(xof) + if _, err := gt.MarshalTo(hash); err != nil { + return nil, errors.New("err marshalling gt to the hash function") + } + + hashReader := bytes.NewReader(hash.Sum(make([]byte, hash.Size()))) var b = make([]byte, length) - if _, err := xof.Read(b); err != nil { + if _, err := hashReader.Read(b); err != nil { return nil, errors.New("couldn't read from xof") } return b[:], nil From 74c2d65f11ed26474ba6e624a2106f0ffa0ef9c7 Mon Sep 17 00:00:00 2001 From: Patrick McClurg Date: Wed, 3 Aug 2022 17:55:24 +0200 Subject: [PATCH 2/5] Updated from PR comments --- encrypt/ibe/ibe.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/encrypt/ibe/ibe.go b/encrypt/ibe/ibe.go index dbfbdb550..2dfa24e70 100644 --- a/encrypt/ibe/ibe.go +++ b/encrypt/ibe/ibe.go @@ -42,10 +42,10 @@ func H4Tag() []byte { // - seed is the random seed to generate the random element (sigma) of the encryption // The suite must produce points which implements the `HashablePoint` interface. func Encrypt(s pairing.Suite, master kyber.Point, ID, msg []byte) (*Ciphertext, error) { - if len(msg)>>16 > 0 { - // we're using blake2 as XOF which only outputs 2^16-1 length - return nil, errors.New("plaintext too long for blake2") + if len(msg) > s.Hash().Size() { + return nil, errors.New("plaintext too long for the hash function provided") } + // 1. Compute Gid = e(master,Q_id) hG2, ok := s.G2().Point().(kyber.HashablePoint) if !ok { @@ -90,6 +90,10 @@ func Encrypt(s pairing.Suite, master kyber.Point, ID, msg []byte) (*Ciphertext, } func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error) { + if len(c.W) > s.Hash().Size() { + return nil, errors.New("ciphertext too long for the hash function provided") + } + // 1. Compute sigma = V XOR H2(e(rP,private)) gidt := s.Pair(c.U, private) hgidt, err := gtToHash(s, gidt, len(c.W), H2Tag()) @@ -125,7 +129,6 @@ func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error // hash sigma and msg to get r func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) { h3 := s.Hash() - h3.Reset() if _, err := h3.Write(H3Tag()); err != nil { return nil, fmt.Errorf("err hashing h3 tag: %v", err) @@ -139,14 +142,13 @@ func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) { panic("scalar can't be created from hash") } - h3Reader := bytes.NewReader(h3.Sum(make([]byte, h3.Size()))) + h3Reader := bytes.NewReader(h3.Sum(nil)) return hashable.Hash(s, h3Reader) } func h4(s pairing.Suite, sigma []byte, length int) ([]byte, error) { h4 := s.Hash() - h4.Reset() if _, err := h4.Write(H4Tag()); err != nil { return nil, fmt.Errorf("err writing h4tag: %v", err) @@ -155,7 +157,7 @@ func h4(s pairing.Suite, sigma []byte, length int) ([]byte, error) { return nil, fmt.Errorf("err writing sigma to h4: %v", err) } - h4Reader := bytes.NewReader(h4.Sum(make([]byte, h4.Size()))) + h4Reader := bytes.NewReader(h4.Sum(nil)) h4sigma := make([]byte, length) if _, err := h4Reader.Read(h4sigma); err != nil { @@ -166,7 +168,6 @@ func h4(s pairing.Suite, sigma []byte, length int) ([]byte, error) { func gtToHash(s pairing.Suite, gt kyber.Point, length int, dst []byte) ([]byte, error) { hash := s.Hash() - hash.Reset() if _, err := hash.Write(dst); err != nil { return nil, errors.New("err writing dst to gtHash") @@ -175,7 +176,7 @@ func gtToHash(s pairing.Suite, gt kyber.Point, length int, dst []byte) ([]byte, return nil, errors.New("err marshalling gt to the hash function") } - hashReader := bytes.NewReader(hash.Sum(make([]byte, hash.Size()))) + hashReader := bytes.NewReader(hash.Sum(nil)) var b = make([]byte, length) if _, err := hashReader.Read(b); err != nil { return nil, errors.New("couldn't read from xof") From bd91dd857119090610720353b025235c509e06b3 Mon Sep 17 00:00:00 2001 From: Patrick McClurg Date: Wed, 3 Aug 2022 17:56:38 +0200 Subject: [PATCH 3/5] removed mentions of xof in text --- encrypt/ibe/ibe.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/encrypt/ibe/ibe.go b/encrypt/ibe/ibe.go index 2dfa24e70..6c687a3bf 100644 --- a/encrypt/ibe/ibe.go +++ b/encrypt/ibe/ibe.go @@ -134,7 +134,7 @@ func h3(s pairing.Suite, sigma, msg []byte) (kyber.Scalar, error) { return nil, fmt.Errorf("err hashing h3 tag: %v", err) } if _, err := h3.Write(sigma); err != nil { - return nil, fmt.Errorf("err hashing sigma to XOF: %v", err) + return nil, fmt.Errorf("err hashing sigma: %v", err) } _, _ = h3.Write(msg) hashable, ok := s.G1().Scalar().(kyber.HashableScalar) @@ -179,7 +179,7 @@ func gtToHash(s pairing.Suite, gt kyber.Point, length int, dst []byte) ([]byte, hashReader := bytes.NewReader(hash.Sum(nil)) var b = make([]byte, length) if _, err := hashReader.Read(b); err != nil { - return nil, errors.New("couldn't read from xof") + return nil, errors.New("couldn't read from hash output") } return b[:], nil } From ce5cbcb440ac129f9eb0bb1a1dbe6eb9ca670128 Mon Sep 17 00:00:00 2001 From: Yolan Romailler Date: Wed, 3 Aug 2022 21:30:17 +0200 Subject: [PATCH 4/5] patching newly discovered race condition with a mutex in StatusMatrix --- encrypt/ibe/ibe.go | 10 ++++----- encrypt/ibe/ibe_test.go | 2 +- share/dkg/status.go | 50 ++++++++++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/encrypt/ibe/ibe.go b/encrypt/ibe/ibe.go index 6c687a3bf..146edd7ec 100644 --- a/encrypt/ibe/ibe.go +++ b/encrypt/ibe/ibe.go @@ -95,15 +95,15 @@ func Decrypt(s pairing.Suite, private kyber.Point, c *Ciphertext) ([]byte, error } // 1. Compute sigma = V XOR H2(e(rP,private)) - gidt := s.Pair(c.U, private) - hgidt, err := gtToHash(s, gidt, len(c.W), H2Tag()) + rGid := s.Pair(c.U, private) + hrGid, err := gtToHash(s, rGid, len(c.W), H2Tag()) if err != nil { return nil, err } - if len(hgidt) != len(c.V) { - return nil, fmt.Errorf("XorSigma is of invalid length: exp %d vs got %d", len(hgidt), len(c.V)) + if len(hrGid) != len(c.V) { + return nil, fmt.Errorf("XorSigma is of invalid length: exp %d vs got %d", len(hrGid), len(c.V)) } - sigma := xor(hgidt, c.V) + sigma := xor(hrGid, c.V) // 2. Compute M = W XOR H4(sigma) hsigma, err := h4(s, sigma, len(c.W)) diff --git a/encrypt/ibe/ibe_test.go b/encrypt/ibe/ibe_test.go index 9a7beb946..c333479a4 100644 --- a/encrypt/ibe/ibe_test.go +++ b/encrypt/ibe/ibe_test.go @@ -79,5 +79,5 @@ func TestVeryLongCipherFailsDecryptionBecauseOfLength(t *testing.T) { _, err = Decrypt(suite, sQid, c) require.Error(t, err) - require.ErrorContains(t, err, "XorSigma is of invalid length") + require.ErrorContains(t, err, "ciphertext too long for the hash function provided") } diff --git a/share/dkg/status.go b/share/dkg/status.go index f18bb31d2..1abb51d39 100644 --- a/share/dkg/status.go +++ b/share/dkg/status.go @@ -4,6 +4,7 @@ import ( "fmt" "sort" "strings" + "sync" ) const ( @@ -12,7 +13,10 @@ const ( ) type BitSet map[uint32]bool -type StatusMatrix map[uint32]BitSet +type StatusMatrix struct { + b map[uint32]BitSet + m sync.Mutex +} func NewStatusMatrix(dealers []Node, shareHolders []Node, status bool) *StatusMatrix { statuses := make(map[uint32]BitSet) @@ -23,13 +27,15 @@ func NewStatusMatrix(dealers []Node, shareHolders []Node, status bool) *StatusMa } statuses[dealer.Index] = bitset } - sm := StatusMatrix(statuses) - return &sm + sm := &StatusMatrix{b: statuses} + return sm } func (s *StatusMatrix) StatusesForShare(shareIndex uint32) BitSet { bt := make(BitSet) - for dealerIdx, bs := range *s { + s.m.Lock() + defer s.m.Unlock() + for dealerIdx, bs := range (*s).b { status, ok := bs[shareIndex] if !ok { panic("index out of range - not supposed to happen") @@ -40,22 +46,28 @@ func (s *StatusMatrix) StatusesForShare(shareIndex uint32) BitSet { } func (s *StatusMatrix) StatusesOfDealer(dealerIndex uint32) BitSet { - return (*s)[dealerIndex] + s.m.Lock() + defer s.m.Unlock() + return (*s).b[dealerIndex] } // can panic if indexes are not from the original list of nodes func (s *StatusMatrix) Set(dealer, share uint32, status bool) { - (*s)[dealer][share] = status + s.m.Lock() + defer s.m.Unlock() + (*s).b[dealer][share] = status } func (s *StatusMatrix) SetAll(dealer uint32, status bool) { - for share := range (*s)[dealer] { - (*s)[dealer][share] = status + s.m.Lock() + defer s.m.Unlock() + for share := range (*s).b[dealer] { + (*s).b[dealer][share] = status } } func (s *StatusMatrix) AllTrue(dealer uint32) bool { - for _, status := range (*s)[dealer] { + for _, status := range (*s).b[dealer] { if status == Complaint { return false } @@ -64,7 +76,9 @@ func (s *StatusMatrix) AllTrue(dealer uint32) bool { } func (s *StatusMatrix) CompleteSuccess() bool { - for dealer := range *s { + s.m.Lock() + defer s.m.Unlock() + for dealer := range (*s).b { if !s.AllTrue(dealer) { return false } @@ -74,18 +88,22 @@ func (s *StatusMatrix) CompleteSuccess() bool { // can panic if indexes are not from the original list of nodes func (s *StatusMatrix) Get(dealer, share uint32) bool { - return (*s)[dealer][share] + s.m.Lock() + defer s.m.Unlock() + return (*s).b[dealer][share] } func (s *StatusMatrix) String() string { + s.m.Lock() + defer s.m.Unlock() // get dealer indexes - dealerIdx := make([]int, 0, len(*s)) - for didx := range *s { + dealerIdx := make([]int, 0, len((*s).b)) + for didx := range (*s).b { dealerIdx = append(dealerIdx, int(didx)) } // get share holder indexes - sharesIdx := make([]int, 0, len((*s)[uint32(dealerIdx[0])])) - for sidx := range (*s)[uint32(dealerIdx[0])] { + sharesIdx := make([]int, 0, len((*s).b[uint32(dealerIdx[0])])) + for sidx := range (*s).b[uint32(dealerIdx[0])] { sharesIdx = append(sharesIdx, int(sidx)) } sort.Ints(dealerIdx) @@ -94,7 +112,7 @@ func (s *StatusMatrix) String() string { for _, dealerIndex := range dealerIdx { var statuses []string for _, shareIndex := range sharesIdx { - status := (*s)[uint32(dealerIndex)][uint32(shareIndex)] + status := (*s).b[uint32(dealerIndex)][uint32(shareIndex)] var st string if status { st = fmt.Sprintf(" %d: ok", shareIndex) From bc98c414480ec8e073256e618f9036e146d4634a Mon Sep 17 00:00:00 2001 From: Yolan Romailler Date: Wed, 3 Aug 2022 21:34:35 +0200 Subject: [PATCH 5/5] adding xorSigma length test --- encrypt/ibe/ibe_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/encrypt/ibe/ibe_test.go b/encrypt/ibe/ibe_test.go index c333479a4..fea259dab 100644 --- a/encrypt/ibe/ibe_test.go +++ b/encrypt/ibe/ibe_test.go @@ -81,3 +81,16 @@ func TestVeryLongCipherFailsDecryptionBecauseOfLength(t *testing.T) { require.Error(t, err) require.ErrorContains(t, err, "ciphertext too long for the hash function provided") } + +func TestInvalidWFailsDecryptionBecauseOfLength(t *testing.T) { + suite, Ppub, ID, sQid := newSetting() + msg := []byte("hello world") + c, err := Encrypt(suite, Ppub, ID, msg) + require.NoError(t, err) + + c.W = []byte(strings.Repeat("A", 25)) + _, err = Decrypt(suite, sQid, c) + + require.Error(t, err) + require.ErrorContains(t, err, "XorSigma is of invalid length") +}