diff --git a/dkg/dkg.go b/dkg/dkg.go index 9308542a8..e0b9edb2d 100644 --- a/dkg/dkg.go +++ b/dkg/dkg.go @@ -34,7 +34,7 @@ type Actor interface { VerifiableDecrypt(ciphertexts []types.Ciphertext) ([][]byte, error) EncryptSecret(message []byte) (U kyber.Point, Cs []kyber.Point) - ReencryptSecret(U kyber.Point, Pk kyber.Point) (Uis []*share.PubShare, err error) + ReencryptSecret(U kyber.Point, Pk kyber.Point, threshold int) (Uis []*share.PubShare, err error) DecryptSecret(Cs []kyber.Point, XhatEnc kyber.Point, Sk kyber.Scalar) (message []byte, err error) } diff --git a/dkg/pedersen/dkg.go b/dkg/pedersen/dkg.go index ad5bfcf35..7bfd49e63 100644 --- a/dkg/pedersen/dkg.go +++ b/dkg/pedersen/dkg.go @@ -819,7 +819,7 @@ func (s *instance) handleReencryptRequest(out mino.Sender, msg types.ReencryptRe ei := suite.Scalar().SetBytes(hash.Sum(nil)) fi := suite.Scalar().Add(si, suite.Scalar().Mul(ei, s.privShare.V)) - response := types.NewReencryptReply(ui, ei, fi) + response := types.NewReencryptReply(msg.PubK, ui, ei, fi) errs := out.Send(response, from) err := <-errs diff --git a/dkg/pedersen/json/json.go b/dkg/pedersen/json/json.go index 80bdd2205..cc1b8208f 100644 --- a/dkg/pedersen/json/json.go +++ b/dkg/pedersen/json/json.go @@ -105,14 +105,14 @@ type VerifiableDecryptReply struct { } type ReencryptRequest struct { - U []byte - PubK PublicKey - VerificationData *[]byte + U []byte + PubK PublicKey } type ReencryptReply struct { PubK PublicKey - Ui *share.PubShare + UiI []byte + UiV []byte Ei []byte Fi []byte } @@ -575,15 +575,9 @@ func encodeReencryptRequest(msg types.ReencryptRequest) (Message, error) { return Message{}, xerrors.Errorf("couldn't marshal PubK: %v", err) } - v, err := msg.VerificationData.MarshalBinary() - if err != nil { - return Message{}, xerrors.Errorf("couldn't marshal PubK: %v", err) - } - req := ReencryptRequest{ - U: u, - PubK: pubk, - VerificationData: v, + U: u, + PubK: pubk, } return Message{ReencryptRequest: &req}, nil @@ -595,7 +589,10 @@ func encodeReencryptReply(msg types.ReencryptReply) (Message, error) { return Message{}, xerrors.Errorf("couldn't marshal PubK: %v", err) } - ui, err := msg.Ui.MarshalBinary() + I := msg.Ui.I + i := []byte{byte(I >> 24), byte(I >> 16), byte(I >> 8), byte(I)} + + v, err := msg.Ui.V.MarshalBinary() if err != nil { return Message{}, xerrors.Errorf("couldn't marshal Ui: %v", err) } @@ -612,7 +609,8 @@ func encodeReencryptReply(msg types.ReencryptReply) (Message, error) { rep := ReencryptReply{ PubK: pubk, - Ui: ui, + UiI: i, + UiV: v, Ei: ei, Fi: fi, } @@ -875,22 +873,14 @@ func (f msgFormat) decodeReencryptRequest(ctx serde.Context, request *ReencryptR return nil, xerrors.Errorf("couldn't unmarshal PubK: %v", err) } - v := f.suite.Scalar() - err = v.UnmarshalBinary(request.VerificationData) - if err != nil { - return nil, xerrors.Errorf("couldn't marshal verification data: %v", err) - } - resp := types.ReencryptRequest{ - U: u, - PubK: pubk, - VerificationData: v, + U: u, + PubK: pubk, } return resp, nil } -// TODO implement func (f msgFormat) decodeReencryptReply(ctx serde.Context, reply *ReencryptReply) (serde.Message, error) { pubk := f.suite.Point() err := pubk.UnmarshalBinary(reply.PubK) @@ -898,12 +888,16 @@ func (f msgFormat) decodeReencryptReply(ctx serde.Context, reply *ReencryptReply return nil, xerrors.Errorf("couldn't unmarshal PubK: %v", err) } - ui := f.suite.Point() - err = ui.UnmarshalBinary(reply.Ui) + i := int(reply.UiI[0]<<24) + int(reply.UiI[1]<<16) + int(reply.UiI[2]<<8) + int(reply.UiI[3]) + + v := f.suite.Point() + err = v.UnmarshalBinary(reply.UiV) if err != nil { return nil, xerrors.Errorf("couldn't unmarshal Ui: %v", err) } + ui := &share.PubShare{i, v} + ei := f.suite.Scalar() err = ei.UnmarshalBinary(reply.Ei) if err != nil { diff --git a/dkg/pedersen/pedersen.go b/dkg/pedersen/pedersen.go index 21ce6da54..e96f4fa5f 100644 --- a/dkg/pedersen/pedersen.go +++ b/dkg/pedersen/pedersen.go @@ -521,15 +521,15 @@ func (a *Actor) EncryptSecret(msg []byte) (U kyber.Point, Cs []kyber.Point) { } type OCS struct { - shared *share.PriShare // Shared represents the private key - poly *share.PubPoly // Represents all public keys - replies []types.ReencryptReply // replies received - U kyber.Point // U is the random part of the encrypted secret - pubk kyber.Point // The client's public key - nbnodes int // How many nodes participate in the distributed operations - nbfailures int // How many failures occurred so far - threshold int // How many replies are needed to re-create the secret - Uis []*share.PubShare // re-encrypted shares + U kyber.Point // U is the random part of the encrypted secret + pubk kyber.Point // The client's public key + + nbnodes int // How many nodes participate in the distributed operations + nbfailures int // How many failures occurred so far + threshold int // How many replies are needed to re-create the secret + + replies []types.ReencryptReply // replies received + Uis []*share.PubShare // re-encrypted shares } // newOCS creates a new on-chain secret structure. @@ -540,7 +540,7 @@ func newOCS(pubk kyber.Point) *OCS { } // ReencryptSecret implements dkg.Actor. -func (a *Actor) ReencryptSecret(U kyber.Point, pubk kyber.Point) (Uis []*share.PubShare, err error) { +func (a *Actor) ReencryptSecret(U kyber.Point, pubk kyber.Point, threshold int) (Uis []*share.PubShare, err error) { if !a.startRes.Done() { return nil, xerrors.Errorf(initDkgFirst) } @@ -573,7 +573,7 @@ func (a *Actor) ReencryptSecret(U kyber.Point, pubk kyber.Point) (Uis []*share.P ocs := newOCS(pubk) ocs.U = U ocs.nbnodes = len(addrs) - ocs.threshold = ocs.nbnodes - 1 + ocs.threshold = threshold for i := 0; i < len(addrs); i++ { src, rxMsg, err := receiver.Recv(ctx) @@ -595,6 +595,7 @@ func (a *Actor) ReencryptSecret(U kyber.Point, pubk kyber.Point) (Uis []*share.P dela.Logger.Info().Msgf("Reencrypted message: %v", ocs.Uis) err = nil + Uis = ocs.Uis return } @@ -612,32 +613,36 @@ func processReencryptReply(ocs *OCS, reply *types.ReencryptReply) (err error) { ocs.replies = append(ocs.replies, *reply) - // minus one to exclude the root - if len(ocs.replies) >= int(ocs.threshold-1) { - ocs.Uis = make([]*share.PubShare, ocs.nbnodes) - ocs.Uis[0] = getUi(ocs, ocs.U, ocs.pubk) + if len(ocs.replies) >= ocs.threshold { + ocs.Uis = make([]*share.PubShare, 0, ocs.nbnodes) for _, r := range ocs.replies { - // Verify proofs - ufi := suite.Point().Mul(r.Fi, suite.Point().Add(ocs.U, ocs.pubk)) - uiei := suite.Point().Mul(suite.Scalar().Neg(r.Ei), r.Ui.V) - uiHat := suite.Point().Add(ufi, uiei) - - gfi := suite.Point().Mul(r.Fi, nil) - gxi := ocs.poly.Eval(r.Ui.I).V - hiei := suite.Point().Mul(suite.Scalar().Neg(r.Ei), gxi) - hiHat := suite.Point().Add(gfi, hiei) - hash := sha256.New() - r.Ui.V.MarshalTo(hash) - uiHat.MarshalTo(hash) - hiHat.MarshalTo(hash) - e := suite.Scalar().SetBytes(hash.Sum(nil)) - if e.Equal(r.Ei) { - ocs.Uis[r.Ui.I] = r.Ui - } else { - dela.Logger.Warn().Msgf("Received invalid share from node: %v", r.Ui.I) - ocs.nbfailures++ - } + + /* + // Verify proofs + ufi := suite.Point().Mul(r.Fi, suite.Point().Add(ocs.U, ocs.pubk)) + uiei := suite.Point().Mul(suite.Scalar().Neg(r.Ei), r.Ui.V) + uiHat := suite.Point().Add(ufi, uiei) + + gfi := suite.Point().Mul(r.Fi, nil) + gxi := ocs.poly.Eval(r.Ui.I).V + hiei := suite.Point().Mul(suite.Scalar().Neg(r.Ei), gxi) + hiHat := suite.Point().Add(gfi, hiei) + hash := sha256.New() + r.Ui.V.MarshalTo(hash) + uiHat.MarshalTo(hash) + hiHat.MarshalTo(hash) + e := suite.Scalar().SetBytes(hash.Sum(nil)) + if e.Equal(r.Ei) { + + */ + ocs.Uis = append(ocs.Uis, r.Ui) + /* + } else { + dela.Logger.Warn().Msgf("Received invalid share from node: %v", r.Ui.I) + ocs.nbfailures++ + } + */ } dela.Logger.Info().Msg("Reencryption completed") return nil @@ -655,6 +660,14 @@ func processReencryptReply(ocs *OCS, reply *types.ReencryptReply) (err error) { return err } +// Helper functions +func min(a, b int) int { + if a < b { + return a + } + return b +} + // DecryptSecret implements dkg.Actor. func (a *Actor) DecryptSecret(Cs []kyber.Point, XhatEnc kyber.Point, Sk kyber.Scalar) (msg []byte, err error) { pubK, err := a.GetPublicKey() @@ -849,20 +862,3 @@ func union(el1 []mino.Address, el2 []mino.Address) []mino.Address { return addrsAll } - -func getUi(ocs *OCS, U, pubk kyber.Point) *share.PubShare { - v := suite.Point().Mul(ocs.shared.V, U) - v.Add(v, suite.Point().Mul(ocs.shared.V, pubk)) - return &share.PubShare{ - I: ocs.shared.I, - V: v, - } -} - -// Helper functions -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/dkg/pedersen/pedersen_test.go b/dkg/pedersen/pedersen_test.go index 57bc39e5e..a4fcf2e72 100644 --- a/dkg/pedersen/pedersen_test.go +++ b/dkg/pedersen/pedersen_test.go @@ -248,6 +248,7 @@ func TestPedersen_ReencryptScenario(t *testing.T) { dela.Logger = dela.Logger.Level(zerolog.WarnLevel) nbNodes := 7 + threshold := (2 * nbNodes / 3) + 1 minos := make([]mino.Mino, nbNodes) dkgs := make([]dkg.DKG, nbNodes) @@ -287,10 +288,11 @@ func TestPedersen_ReencryptScenario(t *testing.T) { for i := 0; i < nbNodes; i++ { U, Cs := actors[i].EncryptSecret(message) - Uis, err := actors[i].ReencryptSecret(U, kp.Public) + Uis, err := actors[i].ReencryptSecret(U, kp.Public, threshold) require.NoError(t, err) + require.NotNil(t, Uis) - XhatEnc, err := share.RecoverCommit(suites.MustFind("Ed25519"), Uis, (2*nbNodes/3)+1, nbNodes) + XhatEnc, err := share.RecoverCommit(suites.MustFind("Ed25519"), Uis, threshold, nbNodes) decrypted, err := actors[i].DecryptSecret(Cs, XhatEnc, kp.Private) require.NoError(t, err) diff --git a/dkg/pedersen/types/messages.go b/dkg/pedersen/types/messages.go index 3591c77d3..37044ad30 100644 --- a/dkg/pedersen/types/messages.go +++ b/dkg/pedersen/types/messages.go @@ -447,9 +447,6 @@ type ReencryptRequest struct { U kyber.Point // Xc is the public key of the reader PubK kyber.Point - // VerificationData is optional and can be any slice of bytes, so that each - // node can verify if the reencryption request is valid or not. - VerificationData *[]byte } // NewReencryptRequest creates a new decryption request. @@ -481,11 +478,12 @@ type ReencryptReply struct { } // NewReencryptReply creates a new decryption request. -func NewReencryptReply(ui *share.PubShare, ei, fi kyber.Scalar) *ReencryptReply { +func NewReencryptReply(pubk kyber.Point, ui *share.PubShare, ei, fi kyber.Scalar) *ReencryptReply { return &ReencryptReply{ - Ui: ui, - Ei: ei, - Fi: fi, + PubK: pubk, + Ui: ui, + Ei: ei, + Fi: fi, } }