Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding reencryption command to DKG #251

Merged
merged 36 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cf2698c
structural change so DKG can accept reencryption commands
jbsv Apr 4, 2023
5c15807
attempt to tidy up the encryption code with the help of OCS
jbsv Apr 12, 2023
9492b5b
created Pedersen reencryption scenario
jbsv Apr 13, 2023
7aa55f0
temporary verifiable encrypt
jbsv Apr 25, 2023
ec32b7f
pederson test to reencrypt some data - part1
jbsv May 17, 2023
c6e89fd
working pederson test to reencrypt some data
jbsv May 24, 2023
2ec15f6
fixed lint warnings
jbsv May 30, 2023
2efa54a
fix go vet: avoid output like comment too long in libc
jbsv May 31, 2023
e73a8a3
clean up
jbsv Jun 5, 2023
3643363
fixed TestDKGInstance
jbsv Jun 5, 2023
b7776f8
reencryption works
jbsv Jun 5, 2023
e72586c
restaured comment length in go vet
jbsv Jun 5, 2023
1cea29e
reduce sonar warnings
jbsv Jun 5, 2023
df635fa
cleanups
jbsv Jun 5, 2023
5ce9b50
tidy up code after review
jbsv Jun 13, 2023
b336d30
finished clean up after review
jbsv Jun 14, 2023
14879bc
fix failing test
jbsv Jun 14, 2023
5807982
cleanups
jbsv Jun 5, 2023
2b7c529
align interfaces Encrypt/EncryptSecret
jbsv Jun 13, 2023
8f1ab3c
fix missing encryption tests
jbsv Jun 13, 2023
ee177b3
fix rebase whoops
jbsv Jun 14, 2023
e28af43
cleaned up dkg interface
jbsv Jun 19, 2023
0788a6e
changes after 1st review
jbsv Jun 21, 2023
a2a9480
improve coverage
jbsv Jun 21, 2023
80d6b7b
changes after review
jbsv Jun 26, 2023
86be3a6
more changes after review
jbsv Jun 26, 2023
127857e
improved coverage
jbsv Jun 27, 2023
be71904
reduce code smell
jbsv Jun 28, 2023
50ca841
typo
jbsv Jun 28, 2023
1fb4078
Merge pull request #255 from dedis/reencrypt-cli
jbsv Jun 28, 2023
8372319
Test threshold at DKG setup
jbsv Jul 18, 2023
aefac52
Refactor Reencrypt status
jbsv Jul 18, 2023
96596fd
Update threshold condition
jbsv Jul 19, 2023
6c8bc18
clean up after review
jbsv Jul 19, 2023
0f1fd03
tidy up threshold
jbsv Jul 19, 2023
f418006
Merge pull request #257 from dedis/reencrypt-cli2
jbsv Jul 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions dkg/dkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"go.dedis.ch/dela/crypto"
"go.dedis.ch/dela/dkg/pedersen/types"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/share"
)

// DKG defines the primitive to start a DKG protocol
Expand All @@ -25,16 +24,32 @@ type Actor interface {
// setup has not been done.
GetPublicKey() (kyber.Point, error)

// Encrypt encrypts the given message into kyber points
jbsv marked this conversation as resolved.
Show resolved Hide resolved
// using the DKG public key
Encrypt(message []byte) (K, C kyber.Point, remainder []byte, err error)
// Decrypt decrypts a pair of kyber points into the original message
// using the DKG internal private key
Decrypt(K, C kyber.Point) ([]byte, error)

// Reshare recreates the DKG with an updated list of participants.
Reshare(co crypto.CollectiveAuthority, newThreshold int) error

// VerifiableEncrypt encrypts the given message into kyber points
// using the DKG public key and proof of work algorithm.
VerifiableEncrypt(message []byte, GBar kyber.Point) (ciphertext types.Ciphertext, remainder []byte, err error)

// VerifiableDecrypt decrypts a pair of kyber points into the original message
// using the DKG internal private key and a proof of work algorithm.
VerifiableDecrypt(ciphertexts []types.Ciphertext) ([][]byte, error)
jbsv marked this conversation as resolved.
Show resolved Hide resolved

// EncryptSecret encrypts the given message the calypso way
EncryptSecret(message []byte) (U kyber.Point, Cs []kyber.Point)
ReencryptSecret(U kyber.Point, Pk kyber.Point, threshold int) (Uis []*share.PubShare, err error)

// ReencryptSecret is the first version of the calypso
// reencryption algorithm in DELA
ReencryptSecret(U kyber.Point, Pk kyber.Point) (XhatEnc kyber.Point, err error)

// DecryptSecret is a helper function to decrypt a secret message previously
// encrypted and reencrypted by the DKG
DecryptSecret(Cs []kyber.Point, XhatEnc kyber.Point, Sk kyber.Scalar) (message []byte, err error)
}
6 changes: 3 additions & 3 deletions dkg/pedersen/controller/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ type listenAction struct {
}

func (a listenAction) Execute(ctx node.Context) error {
var d dkg.DKG
var dkgObject dkg.DKG

err := ctx.Injector.Resolve(&d)
err := ctx.Injector.Resolve(&dkgObject)
if err != nil {
return xerrors.Errorf("failed to resolve dkg: %v", err)
}

actor, err := d.Listen()
actor, err := dkgObject.Listen()
if err != nil {
return xerrors.Errorf("failed to listen: %v", err)
}
Expand Down
14 changes: 0 additions & 14 deletions dkg/pedersen/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,6 @@ func (m minimal) SetCommands(builder node.Builder) {
)
sub.SetAction(builder.MakeAction(decryptAction{}))

//sub = cmd.SetSubCommand("reencrypt")
//sub.SetDescription("reencrypt a message")
//sub.SetFlags(
// cli.StringFlag{
// Name: "encrypted",
// Usage: "the encrypted string, as <hex(K)>:<hex(C)>",
// },
// cli.StringFlag{
// Name: "publickey",
// Usage: "the new public key to reencrypt the message, as <hex(pk)>",
// },
//)
//sub.SetAction(builder.MakeAction(reencryptAction{}))

sub = cmd.SetSubCommand("verifiableEncrypt")
sub.SetDescription("encrypt a message and provides a proof. " +
"Outputs <hex(K)>:<hex(C)>:<hex(Ubar)>:<hex(E)>:<hex(F)>:<hex(remainder)>")
Expand Down
169 changes: 169 additions & 0 deletions dkg/pedersen/ocs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package pedersen

import (
"go.dedis.ch/dela"
"go.dedis.ch/dela/dkg/pedersen/types"
"go.dedis.ch/dela/internal/tracing"
"go.dedis.ch/dela/mino"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/share"
"go.dedis.ch/kyber/v3/suites"
"golang.org/x/net/context"
"golang.org/x/xerrors"
)

type onChainSecret struct {
U kyber.Point // U is the random part of the encrypted secret
pubk kyber.Point // The client's public key
jbsv marked this conversation as resolved.
Show resolved Hide resolved

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.
func newOCS(pubk kyber.Point) *onChainSecret {
return &onChainSecret{
pubk: pubk,
}
}

// ReencryptSecret implements dkg.Actor.
func (a *Actor) ReencryptSecret(U kyber.Point, pubk kyber.Point) (XhatEnc kyber.Point, err error) {
if !a.startRes.Done() {
return nil, xerrors.Errorf(initDkgFirst)
}

ctx, cancel := context.WithTimeout(context.Background(), decryptTimeout)
defer cancel()
ctx = context.WithValue(ctx, tracing.ProtocolKey, protocolNameDecrypt)

players := mino.NewAddresses(a.startRes.getParticipants()...)

sender, receiver, err := a.rpc.Stream(ctx, players)
if err != nil {
return nil, xerrors.Errorf(failedStreamCreation, err)
}

iterator := players.AddressIterator()
addrs := make([]mino.Address, 0, players.Len())

for iterator.HasNext() {
addrs = append(addrs, iterator.GetNext())
}

txMsg := types.NewReencryptRequest(U, pubk)

err = <-sender.Send(txMsg, addrs...)
if err != nil {
return nil, xerrors.Errorf("failed to send reencrypt request: %v", err)
}

ocs := newOCS(pubk)
ocs.U = U
ocs.nbnodes = len(addrs)
ocs.threshold = a.startRes.getThreshold()

for i := 0; i < len(addrs); i++ {
src, rxMsg, err := receiver.Recv(ctx)
if err != nil {
return nil, xerrors.Errorf(unexpectedStreamStop, err)
}

dela.Logger.Debug().Msgf("Received a decryption reply from %v", src)

reply, ok := rxMsg.(types.ReencryptReply)
if !ok {
return nil, xerrors.Errorf(unexpectedReply, reply, rxMsg)
}

err = processReencryptReply(ocs, &reply)
if err == nil {
dela.Logger.Debug().Msgf("Reencryption Uis: %v", ocs.Uis)

XhatEnc, err := share.RecoverCommit(suites.MustFind("Ed25519"), ocs.Uis, ocs.threshold, ocs.nbnodes)
if err != nil {
return nil, xerrors.Errorf("Reencryption failed: %v", err)
}

// we have successfully reencrypted
return XhatEnc, nil
}
}

return nil, xerrors.Errorf("Reencryption failed: %v", err)
}

func processReencryptReply(ocs *onChainSecret, reply *types.ReencryptReply) (err error) {
if reply.Ui == nil {
err = xerrors.Errorf("Received empty reply")
dela.Logger.Warn().Msg("Empty reply received")
ocs.nbfailures++
if ocs.nbfailures > ocs.nbnodes-ocs.threshold {
err = xerrors.Errorf("couldn't get enough shares")
dela.Logger.Warn().Msg(err.Error())
}
return err
}

ocs.replies = append(ocs.replies, *reply)

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 = 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
}

// If we are leaving by here it means that we do not have
// enough replies yet. We must eventually trigger a finish()
// somehow. It will either happen because we get another
// reply, and now we have enough, or because we get enough
// failures and know to give up, or because o.timeout triggers
// and calls finish(false) in its callback function.

err = xerrors.Errorf("not enough replies")
dela.Logger.Debug().Msg(err.Error())
return err
}

// min is a helper functions
func min(a, b int) int {
if a < b {
return a
}
return b
}
Loading