diff --git a/Makefile b/Makefile index f1955bd0c974351c212a82888947bf58774343fa..ccae033ac35c7db20c21aab397eeef6b9d364bd0 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ version: go run main.go generate - sed -i.bak 's/package\ cmd/package\ api/g' version_vars.go - mv version_vars.go api/version_vars.go + sed -i.bak 's/package\ cmd/package\ xxdk/g' version_vars.go + mv version_vars.go xxdk/version_vars.go clean: rm -rf vendor/ diff --git a/api/identity.go b/api/identity.go deleted file mode 100644 index 2ef5c5bb4cb5bfc468b368ab8d5f1ff4cf25b740..0000000000000000000000000000000000000000 --- a/api/identity.go +++ /dev/null @@ -1,53 +0,0 @@ -package api - -import ( - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/diffieHellman" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/crypto/xx" - "gitlab.com/xx_network/primitives/id" -) - -type Identity struct { - ID *id.ID - RSAPrivatePem *rsa.PrivateKey - Salt []byte - DHKeyPrivate *cyclic.Int -} - -// MakeIdentity generates a new cryptographic identity for receiving messages -func MakeIdentity(rng csprng.Source, grp *cyclic.Group) (Identity, error) { - //make RSA Key - rsaKey, err := rsa.GenerateKey(rng, - rsa.DefaultRSABitLen) - if err != nil { - return Identity{}, err - } - - //make salt - salt := make([]byte, 32) - _, err = rng.Read(salt) - - //make dh private key - privkey := diffieHellman.GeneratePrivateKey( - len(grp.GetPBytes()), - grp, rng) - - //make the ID - newId, err := xx.NewID(rsaKey.GetPublic(), - salt, id.User) - if err != nil { - return Identity{}, err - } - - //create the identity object - I := Identity{ - ID: newId, - RSAPrivatePem: rsaKey, - Salt: salt, - DHKeyPrivate: privkey, - } - - return I, nil -} diff --git a/api/messenger/precan.go b/api/messenger/precan.go deleted file mode 100644 index 16717bbfa04bb986e9069931da62126e700c5509..0000000000000000000000000000000000000000 --- a/api/messenger/precan.go +++ /dev/null @@ -1,87 +0,0 @@ -package messenger - -import ( - "encoding/binary" - "github.com/cloudflare/circl/dh/sidh" - "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/e2e/ratchet/partner/session" - util "gitlab.com/elixxir/client/storage/utility" - "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/diffieHellman" - "gitlab.com/elixxir/primitives/fact" - "math/rand" -) - -func generatePrecanDHKeypair(precannedID uint, e2eGrp *cyclic.Group) *cyclic.Int { - // DH Keygen - prng := rand.New(rand.NewSource(int64(precannedID))) - prime := e2eGrp.GetPBytes() - keyLen := len(prime) - priv := diffieHellman.GeneratePrivateKey(keyLen, e2eGrp, prng) - return priv -} - -// Create an insecure e2e relationship with a precanned user -func (m *Client) MakePrecannedAuthenticatedChannel(precannedID uint) ( - contact.Contact, error) { - - precan := m.MakePrecannedContact(precannedID) - - myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:]) - // Pick a variant based on if their ID is bigger than mine. - myVariant := sidh.KeyVariantSidhA - theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB) - if myID > uint64(precannedID) { - myVariant = sidh.KeyVariantSidhB - theirVariant = sidh.KeyVariantSidhA - } - prng1 := rand.New(rand.NewSource(int64(precannedID))) - theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant) - theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant) - theirSIDHPrivKey.Generate(prng1) - theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey) - - prng2 := rand.New(rand.NewSource(int64(myID))) - mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant) - mySIDHPubKey := util.NewSIDHPublicKey(myVariant) - mySIDHPrivKey.Generate(prng2) - mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey) - - // add the precanned user as a e2e contact - // FIXME: these params need to be threaded through... - sesParam := session.GetDefaultParams() - _, err := m.e2e.AddPartner(precan.ID, precan.DhPubKey, - m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey, - mySIDHPrivKey, sesParam, sesParam) - - // check garbled messages in case any messages arrived before creating - // the channel - m.GetCmix().CheckInProgressMessages() - - return precan, err -} - -// Create an insecure e2e contact object for a precanned user -func (m *Client) MakePrecannedContact(precannedID uint) contact.Contact { - - e2eGrp := m.GetStorage().GetE2EGroup() - - rng := m.GetRng().GetStream() - precanned := api.CreatePrecannedUser(precannedID, rng) - rng.Close() - - precanned.E2eDhPrivateKey = generatePrecanDHKeypair(precannedID, - m.GetStorage().GetE2EGroup()) - - // compute their public e2e key - partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey, - e2eGrp.NewInt(1)) - - return contact.Contact{ - ID: precanned.ReceptionID, - DhPubKey: partnerPubKey, - OwnershipProof: nil, - Facts: make([]fact.Fact, 0), - } -} diff --git a/api/precan.go b/api/precan.go deleted file mode 100644 index 150d90fa9a806db81277fe9677a9a6ecc13e64dc..0000000000000000000000000000000000000000 --- a/api/precan.go +++ /dev/null @@ -1,85 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package api - -import ( - "encoding/binary" - - jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/user" - "gitlab.com/elixxir/crypto/fastRNG" - "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id" -) - -// CreatePrecannedUser creates a precanned user -func CreatePrecannedUser(precannedID uint, rng csprng.Source) user.Info { - - // Salt, UID, etc gen - salt := make([]byte, SaltSize) - - userID := id.ID{} - binary.BigEndian.PutUint64(userID[:], uint64(precannedID)) - userID.SetType(id.User) - - // NOTE: not used... RSA Keygen (4096 bit defaults) - rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - - return user.Info{ - TransmissionID: &userID, - TransmissionSalt: salt, - ReceptionID: &userID, - ReceptionSalt: salt, - Precanned: true, - E2eDhPrivateKey: nil, - E2eDhPublicKey: nil, - TransmissionRSA: rsaKey, - ReceptionRSA: rsaKey, - } -} - -// NewPrecannedClient creates an insecure user with predetermined keys -// with nodes It creates client storage, generates keys, connects, and -// registers with the network. Note that this does not register a -// username/identity, but merely creates a new cryptographic identity -// for adding such information at a later date. -func NewPrecannedClient(precannedID uint, defJSON, storageDir string, - password []byte) error { - jww.INFO.Printf("NewPrecannedClient()") - rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, - csprng.NewSystemRNG) - rngStream := rngStreamGen.GetStream() - - def, err := ParseNDF(defJSON) - if err != nil { - return err - } - cmixGrp, e2eGrp := DecodeGroups(def) - - protoUser := CreatePrecannedUser(precannedID, rngStream) - - store, err := CheckVersionAndSetupStorage(def, storageDir, password, - protoUser, cmixGrp, e2eGrp, "") - if err != nil { - return err - } - - // Mark the precanned user as finished with permissioning and registered - // with the network. - err = store.ForwardRegistrationStatus(storage.PermissioningComplete) - if err != nil { - return err - } - - return nil -} diff --git a/auth/callbacks.go b/auth/callbacks.go new file mode 100644 index 0000000000000000000000000000000000000000..781164bb89e374f166b0ace4d4fb639e7c250d10 --- /dev/null +++ b/auth/callbacks.go @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package auth + +import ( + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/xx_network/primitives/id" + "sync" +) + +// partnerCallbacks is a thread-safe wrapper for Callbacks specific to partnerIds +// For auth operations with a specific partner, these Callbacks will be used instead +type partnerCallbacks struct { + callbacks map[id.ID]Callbacks + sync.RWMutex +} + +// AddPartnerCallback that overrides the generic auth callback for the given partnerId +func (p *partnerCallbacks) AddPartnerCallback(partnerId *id.ID, cb Callbacks) { + p.Lock() + defer p.Unlock() + if _, ok := p.callbacks[*partnerId]; !ok { + p.callbacks[*partnerId] = cb + } +} + +// DeletePartnerCallback that overrides the generic auth callback for the given partnerId +func (p *partnerCallbacks) DeletePartnerCallback(partnerId *id.ID) { + p.Lock() + defer p.Unlock() + if _, ok := p.callbacks[*partnerId]; ok { + delete(p.callbacks, *partnerId) + } +} + +// getPartnerCallback returns the Callbacks for the given partnerId +func (p *partnerCallbacks) getPartnerCallback(partnerId *id.ID) Callbacks { + return p.callbacks[*partnerId] +} + +// DefaultAuthCallbacks is a simple structure for providing a default Callbacks implementation +// It should generally not be used. +type DefaultAuthCallbacks struct{} + +// Confirm will be called when an auth Confirm message is processed. +func (a DefaultAuthCallbacks) Confirm(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + jww.ERROR.Printf("No valid auth callback assigned!") +} + +// Request will be called when an auth Request message is processed. +func (a DefaultAuthCallbacks) Request(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + jww.ERROR.Printf("No valid auth callback assigned!") +} + +// Reset will be called when an auth Reset operation occurs. +func (a DefaultAuthCallbacks) Reset(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + jww.ERROR.Printf("No valid auth callback assigned!") +} diff --git a/auth/interface.go b/auth/interface.go index e01e5576685fede4971dbcf8ccd542f08a464bb4..40f5e72e4ddefcb46bb716765cc163dca94876a6 100644 --- a/auth/interface.go +++ b/auth/interface.go @@ -96,11 +96,18 @@ type State interface { // VerifyOwnership checks if the received ownership proof is valid VerifyOwnership(received, verified contact.Contact, e2e e2e.Handler) bool + // AddPartnerCallback that overrides the generic auth callback for the given partnerId + AddPartnerCallback(partnerId *id.ID, cb Callbacks) + + // DeletePartnerCallback that overrides the generic auth callback for the given partnerId + DeletePartnerCallback(partnerId *id.ID) + //Closer stops listening to auth io.Closer } // Callbacks is the interface for auth callback methods. +// TODO: Document this type Callbacks interface { Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity, round rounds.Round) diff --git a/auth/receivedConfirm.go b/auth/receivedConfirm.go index 8ee24bd341ba6c03e2f00a7a5158d76558b6800e..538329e1b532a1a34d813f866dfb739319c09d3b 100644 --- a/auth/receivedConfirm.go +++ b/auth/receivedConfirm.go @@ -25,21 +25,21 @@ type receivedConfirmService struct { func (rcs *receivedConfirmService) Process(msg format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) { - state := rcs.s + authState := rcs.s //parse the confirm - baseFmt, partnerPubKey, err := handleBaseFormat(msg, state.e2e.GetGroup()) + baseFmt, partnerPubKey, err := handleBaseFormat(msg, authState.e2e.GetGroup()) if err != nil { em := fmt.Sprintf("Failed to handle auth confirm: %s", err) jww.WARN.Print(em) - state.event.Report(10, "Auth", "ConfirmError", em) + authState.event.Report(10, "Auth", "ConfirmError", em) return } jww.TRACE.Printf("processing confirm: \n\t MYHISTORICALPUBKEY: %s\n\t"+ "MYPUBKEY: %s\n\t PARTNERPUBKEY: %s \n\t "+ "ECRPAYLOAD: %s \n\t MAC: %s", - state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0), + authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0), rcs.SentRequest.GetMyPubKey().TextVerbose(16, 0), partnerPubKey.TextVerbose(16, 0), base64.StdEncoding.EncodeToString(baseFmt.data), @@ -47,13 +47,13 @@ func (rcs *receivedConfirmService) Process(msg format.Message, // decrypt the payload success, payload := cAuth.Decrypt(rcs.GetMyPrivKey(), partnerPubKey, - baseFmt.GetEcrPayload(), msg.GetMac(), state.e2e.GetGroup()) + baseFmt.GetEcrPayload(), msg.GetMac(), authState.e2e.GetGroup()) if !success { em := fmt.Sprintf("Received auth confirmation " + "failed its mac check") jww.WARN.Print(em) - state.event.Report(10, "Auth", "ConfirmError", em) + authState.event.Report(10, "Auth", "ConfirmError", em) return } @@ -63,7 +63,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message, em := fmt.Sprintf("Failed to unmarshal auth confirmation's "+ "encrypted payload: %s", err) jww.WARN.Print(em) - state.event.Report(10, "Auth", "ConfirmError", em) + authState.event.Report(10, "Auth", "ConfirmError", em) return } @@ -72,7 +72,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message, em := fmt.Sprintf("Could not get auth conf SIDH Pubkey: %s", err) jww.WARN.Print(em) - state.event.Report(10, "Auth", "ConfirmError", em) + authState.event.Report(10, "Auth", "ConfirmError", em) return } @@ -83,7 +83,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message, // initial identity if !cAuth.VerifyOwnershipProof(rcs.SentRequest.GetMyPrivKey(), rcs.GetPartnerHistoricalPubKey(), - state.e2e.GetGroup(), ecrFmt.GetOwnership()) { + authState.e2e.GetGroup(), ecrFmt.GetOwnership()) { jww.WARN.Printf("Failed authenticate identity for auth "+ "confirmation of %s", rcs.GetPartner()) return @@ -91,7 +91,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message, // add the partner p := session.GetDefaultParams() - _, err = state.e2e.AddPartner(rcs.GetPartner(), partnerPubKey, + _, err = authState.e2e.AddPartner(rcs.GetPartner(), partnerPubKey, rcs.GetMyPrivKey(), partnerSIDHPubKey, rcs.GetMySIDHPrivKey(), p, p) if err != nil { jww.WARN.Printf("Failed to create channel with partner %s and "+ @@ -103,7 +103,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message, } // remove the service used for notifications of the confirm - state.net.DeleteService(receptionID.Source, rcs.notificationsService, nil) + authState.net.DeleteService(receptionID.Source, rcs.notificationsService, nil) // callbacks c := contact.Contact{ @@ -112,7 +112,14 @@ func (rcs *receivedConfirmService) Process(msg format.Message, OwnershipProof: ecrFmt.GetOwnership(), Facts: make([]fact.Fact, 0), } - state.callbacks.Confirm(c, receptionID, round) + + authState.partnerCallbacks.RLock() + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Confirm(c, receptionID, round) + } else { + authState.callbacks.Confirm(c, receptionID, round) + } + authState.partnerCallbacks.RUnlock() } func (rcs *receivedConfirmService) String() string { diff --git a/auth/receivedRequest.go b/auth/receivedRequest.go index 944c1880b3ac0a744331abbcbb44c4f8dba79949..b410b04a3e29cca95dedd8bc14d310507e8bce57 100644 --- a/auth/receivedRequest.go +++ b/auth/receivedRequest.go @@ -28,11 +28,11 @@ type receivedRequestService struct { func (rrs *receivedRequestService) Process(message format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) { - state := rrs.s + authState := rrs.s // check if the timestamp is before the id was created and therefore // should be ignored - tid, err := state.net.GetIdentity(receptionID.Source) + tid, err := authState.net.GetIdentity(receptionID.Source) if err != nil { jww.ERROR.Printf("received a request on %s which does not exist, "+ "this should not be possible: %+v", receptionID.Source.String(), err) @@ -47,7 +47,7 @@ func (rrs *receivedRequestService) Process(message format.Message, //decode the outer format baseFmt, partnerPubKey, err := handleBaseFormat( - message, state.e2e.GetGroup()) + message, authState.e2e.GetGroup()) if err != nil { jww.WARN.Printf("Failed to handle auth request: %s", err) return @@ -57,15 +57,15 @@ func (rrs *receivedRequestService) Process(message format.Message, jww.TRACE.Printf("processing requests: \n\t MYHISTORICALPUBKEY: %s "+ "\n\t PARTNERPUBKEY: %s \n\t ECRPAYLOAD: %s \n\t MAC: %s", - state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0), + authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0), partnerPubKey.TextVerbose(16, 0), base64.StdEncoding.EncodeToString(baseFmt.data), base64.StdEncoding.EncodeToString(message.GetMac())) //Attempt to decrypt the payload - success, payload := cAuth.Decrypt(state.e2e.GetHistoricalDHPrivkey(), + success, payload := cAuth.Decrypt(authState.e2e.GetHistoricalDHPrivkey(), partnerPubKey, baseFmt.GetEcrPayload(), message.GetMac(), - state.e2e.GetGroup()) + authState.e2e.GetGroup()) if !success { jww.WARN.Printf("Received auth request of %s failed its mac "+ @@ -97,11 +97,11 @@ func (rrs *receivedRequestService) Process(message format.Message, format.DigestContents(message.GetContents()), base64.StdEncoding.EncodeToString(fp)) jww.INFO.Print(em) - state.event.Report(1, "Auth", "RequestReceived", em) + authState.event.Report(1, "Auth", "RequestReceived", em) // check the uniqueness of the request. Requests can be duplicated, so we // must verify this is is not a duplicate, and drop if it is - newFP, position := state.store.CheckIfNegotiationIsNew(partnerID, fp) + newFP, position := authState.store.CheckIfNegotiationIsNew(partnerID, fp) if !newFP { // if its the newest, resend the confirm @@ -113,10 +113,10 @@ func (rrs *receivedRequestService) Process(message format.Message, // check if we already accepted, if we did, resend the confirm if // we can load it - if _, err = state.e2e.GetPartner(partnerID); err != nil { + if _, err = authState.e2e.GetPartner(partnerID); err != nil { //attempt to load the confirm, if we can, resend it confirmPayload, mac, keyfp, err := - state.store.LoadConfirmation(partnerID) + authState.store.LoadConfirmation(partnerID) if err != nil { jww.ERROR.Printf("Could not reconfirm a duplicate "+ "request of an accepted confirm from %s to %s because "+ @@ -125,14 +125,26 @@ func (rrs *receivedRequestService) Process(message format.Message, } // resend the confirm. It sends as a critical message, so errors // do not need to be handled - _, _ = sendAuthConfirm(state.net, partnerID, keyfp, - confirmPayload, mac, state.event, state.params.ResetConfirmTag) - } else if state.params.ReplayRequests { + _, _ = sendAuthConfirm(authState.net, partnerID, keyfp, + confirmPayload, mac, authState.event, authState.params.ResetConfirmTag) + } else if authState.params.ReplayRequests { //if we did not already accept, auto replay the request if rrs.reset { - state.callbacks.Reset(c, receptionID, round) + authState.partnerCallbacks.RLock() + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Reset(c, receptionID, round) + } else { + authState.callbacks.Reset(c, receptionID, round) + } + authState.partnerCallbacks.RUnlock() } else { - state.callbacks.Request(c, receptionID, round) + authState.partnerCallbacks.RLock() + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Request(c, receptionID, round) + } else { + authState.callbacks.Request(c, receptionID, round) + } + authState.partnerCallbacks.RUnlock() } } //if not confirm, and params.replay requests is true, we need to replay @@ -159,21 +171,21 @@ func (rrs *receivedRequestService) Process(message format.Message, // error to see if it did or didnt exist // Note: due to the newFP handling above, this can ONLY run in the event of // a reset or when the partner doesnt exist, so it is safe - if err = state.e2e.DeletePartner(partnerID); err != nil { + if err = authState.e2e.DeletePartner(partnerID); err != nil { if !strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) { jww.FATAL.Panicf("Failed to do actual partner deletion: %+v", err) } } else { reset = true - _ = state.store.DeleteConfirmation(partnerID) - _ = state.store.DeleteSentRequest(partnerID) + _ = authState.store.DeleteConfirmation(partnerID) + _ = authState.store.DeleteSentRequest(partnerID) } } // if a new, unique request is received when one already exists, delete the // old one and process the new one // this works because message pickup is generally time-sequential. - if err = state.store.DeleteReceivedRequest(partnerID); err != nil { + if err = authState.store.DeleteReceivedRequest(partnerID); err != nil { if !strings.Contains(err.Error(), store.NoRequestFound) { jww.FATAL.Panicf("Failed to delete old received request: %+v", err) @@ -187,7 +199,7 @@ func (rrs *receivedRequestService) Process(message format.Message, // (SIDH keys have polarity, so both sent keys cannot be used together) autoConfirm := false bail := false - err = state.store.HandleSentRequest(partnerID, + err = authState.store.HandleSentRequest(partnerID, func(request *store.SentRequest) error { //if this code is running, then we know we sent a request and can @@ -195,8 +207,8 @@ func (rrs *receivedRequestService) Process(message format.Message, //This runner will auto delete the sent request if successful //verify ownership proof - if !cAuth.VerifyOwnershipProof(state.e2e.GetHistoricalDHPrivkey(), - partnerPubKey, state.e2e.GetGroup(), ownershipProof) { + if !cAuth.VerifyOwnershipProof(authState.e2e.GetHistoricalDHPrivkey(), + partnerPubKey, authState.e2e.GetGroup(), ownershipProof) { jww.WARN.Printf("Invalid ownership proof from %s to %s "+ "received, discarding msgDigest: %s, fp: %s", partnerID, receptionID.Source, @@ -233,25 +245,39 @@ func (rrs *receivedRequestService) Process(message format.Message, // warning: the client will never be notified of the channel creation if a // crash occurs after the store but before the conclusion of the callback //create the auth storage - if err = state.store.AddReceived(c, partnerSIDHPubKey, round); err != nil { + if err = authState.store.AddReceived(c, partnerSIDHPubKey, round); err != nil { em := fmt.Sprintf("failed to store contact Auth "+ "Request: %s", err) jww.WARN.Print(em) - state.event.Report(10, "Auth", "RequestError", em) + authState.event.Report(10, "Auth", "RequestError", em) return } - //autoconfirm if we should + // auto-confirm if we should + authState.partnerCallbacks.RLock() + defer authState.partnerCallbacks.RUnlock() if autoConfirm || reset { - _, _ = state.confirm(c, state.params.getConfirmTag(reset)) + _, _ = authState.confirm(c, authState.params.getConfirmTag(reset)) //handle callbacks if autoConfirm { - state.callbacks.Confirm(c, receptionID, round) + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Confirm(c, receptionID, round) + } else { + authState.callbacks.Confirm(c, receptionID, round) + } } else if reset { - state.callbacks.Reset(c, receptionID, round) + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Reset(c, receptionID, round) + } else { + authState.callbacks.Reset(c, receptionID, round) + } } } else { - state.callbacks.Request(c, receptionID, round) + if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil { + cb.Request(c, receptionID, round) + } else { + authState.callbacks.Request(c, receptionID, round) + } } } diff --git a/auth/state.go b/auth/state.go index 607275a3075372141b799cfab0e9a2aa73cebbdd..43e1d9735fde5bd0e5c4bbc396ec3ff74727c4b5 100644 --- a/auth/state.go +++ b/auth/state.go @@ -9,7 +9,6 @@ package auth import ( "encoding/base64" - "github.com/pkg/errors" "gitlab.com/elixxir/client/auth/store" "gitlab.com/elixxir/client/cmix" @@ -24,7 +23,10 @@ import ( // state is an implementation of the State interface. type state struct { + // Main Callbacks for all auth operations callbacks Callbacks + // partner-specific Callbacks + partnerCallbacks partnerCallbacks net cmixClient e2e e2eHandler @@ -70,13 +72,14 @@ func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler, callbacks Callbacks, backupTrigger func(reason string)) (State, error) { s := &state{ - callbacks: callbacks, - net: net, - e2e: e2e, - rng: rng, - event: event, - params: params, - backupTrigger: backupTrigger, + callbacks: callbacks, + partnerCallbacks: partnerCallbacks{callbacks: make(map[id.ID]Callbacks)}, + net: net, + e2e: e2e, + rng: rng, + event: event, + params: params, + backupTrigger: backupTrigger, } // create the store @@ -112,7 +115,13 @@ func (s *state) CallAllReceivedRequests() { rr := rrList[i] eph := receptionID.BuildIdentityFromRound(rr.GetContact().ID, rr.GetRound()) - s.callbacks.Request(rr.GetContact(), eph, rr.GetRound()) + s.partnerCallbacks.RLock() + if cb := s.partnerCallbacks.getPartnerCallback(rr.GetContact().ID); cb != nil { + cb.Request(rr.GetContact(), eph, rr.GetRound()) + } else { + s.callbacks.Request(rr.GetContact(), eph, rr.GetRound()) + } + s.partnerCallbacks.RUnlock() } } @@ -134,3 +143,13 @@ func (s *state) Close() error { }, nil) return nil } + +// AddPartnerCallback that overrides the generic auth callback for the given partnerId +func (s *state) AddPartnerCallback(partnerId *id.ID, cb Callbacks) { + s.partnerCallbacks.AddPartnerCallback(partnerId, cb) +} + +// DeletePartnerCallback that overrides the generic auth callback for the given partnerId +func (s *state) DeletePartnerCallback(partnerId *id.ID) { + s.partnerCallbacks.DeletePartnerCallback(partnerId) +} diff --git a/backup/backup.go b/backup/backup.go index 46f5bf73019e9c26e66b2a780f141a5b788647a4..992968668b08cce3a8d9819bbc6991f738b1ce18 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -8,10 +8,10 @@ package backup import ( + "gitlab.com/elixxir/client/xxdk" "sync" "time" - "gitlab.com/elixxir/client/api/messenger" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/fact" @@ -41,11 +41,11 @@ type Backup struct { // Callback that is called with the encrypted backup when triggered updateBackupCb UpdateBackupFn - container *messenger.Container + container *xxdk.Container jsonParams string - // Client structures + // E2e structures e2e E2e session Session ud UserDiscovery @@ -91,7 +91,7 @@ type UpdateBackupFn func(encryptedBackup []byte) // Call this to turn on backups for the first time or to replace the user's // password. func InitializeBackup(password string, updateBackupCb UpdateBackupFn, - container *messenger.Container, e2e E2e, session Session, ud UserDiscovery, + container *xxdk.Container, e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) { b := &Backup{ updateBackupCb: updateBackupCb, @@ -135,7 +135,7 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn, // ResumeBackup resumes a backup by restoring the Backup object and registering // a new callback. Call this to resume backups that have already been // initialized. Returns an error if backups have not already been initialized. -func ResumeBackup(updateBackupCb UpdateBackupFn, container *messenger.Container, +func ResumeBackup(updateBackupCb UpdateBackupFn, container *xxdk.Container, e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) { _, _, _, err := loadBackup(kv) diff --git a/api/messenger/backupRestore.go b/backup/backupRestore.go similarity index 72% rename from api/messenger/backupRestore.go rename to backup/backupRestore.go index d3187f7fcc4b9f4535559351bc2d2ff68c7484ac..93ba6778ea16e2a7982ee5a1c7e487b7d08bf406 100644 --- a/api/messenger/backupRestore.go +++ b/backup/backupRestore.go @@ -1,22 +1,28 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + // FIXME: This is placeholder, there's got to be a better place to put // backup restoration than inside messenger. -package messenger +package backup import ( "github.com/pkg/errors" - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/rekey" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/ud" + "gitlab.com/elixxir/client/xxdk" cryptoBackup "gitlab.com/elixxir/crypto/backup" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/id" ) -// NewClientFromBackup constructs a new Client from an encrypted +// NewClientFromBackup constructs a new E2e from an encrypted // backup. The backup is decrypted using the backupPassphrase. On // success a successful client creation, the function will return a // JSON encoded list of the E2E partners contained in the backup and a @@ -34,16 +40,16 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, usr := user.NewUserFromBackup(backUp) - def, err := api.ParseNDF(ndfJSON) + def, err := xxdk.ParseNDF(ndfJSON) if err != nil { return nil, "", err } - cmixGrp, e2eGrp := api.DecodeGroups(def) + cmixGrp, e2eGrp := xxdk.DecodeGroups(def) // Note we do not need registration here - storageSess, err := api.CheckVersionAndSetupStorage(def, storageDir, - []byte(sessionPassword), usr, cmixGrp, e2eGrp, + storageSess, err := xxdk.CheckVersionAndSetupStorage(def, storageDir, + sessionPassword, usr, cmixGrp, e2eGrp, backUp.RegistrationCode) if err != nil { return nil, "", err @@ -84,7 +90,6 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, phone = f } } - ud.InitStoreFromBackup(storageSess.GetKV(), username, email, phone) - - return backUp.Contacts.Identities, backUp.JSONParams, nil + err = ud.InitStoreFromBackup(storageSess.GetKV(), username, email, phone) + return backUp.Contacts.Identities, backUp.JSONParams, err } diff --git a/backup/backup_test.go b/backup/backup_test.go index f61dc0a06b02adcaa3218c909a90dda6c90c3985..bcaf8cf35bb4c7d0044cbf7e2a79e445e0d9c207 100644 --- a/backup/backup_test.go +++ b/backup/backup_test.go @@ -9,12 +9,12 @@ package backup import ( "bytes" + "gitlab.com/elixxir/client/xxdk" "reflect" "strings" "testing" "time" - "gitlab.com/elixxir/client/api/messenger" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" @@ -32,7 +32,7 @@ func Test_InitializeBackup(t *testing.T) { cbChan := make(chan []byte, 2) cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup } expectedPassword := "MySuperSecurePassword" - b, err := InitializeBackup(expectedPassword, cb, &messenger.Container{}, + b, err := InitializeBackup(expectedPassword, cb, &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen) if err != nil { @@ -84,7 +84,7 @@ func Test_ResumeBackup(t *testing.T) { cbChan1 := make(chan []byte) cb1 := func(encryptedBackup []byte) { cbChan1 <- encryptedBackup } expectedPassword := "MySuperSecurePassword" - b, err := InitializeBackup(expectedPassword, cb1, &messenger.Container{}, + b, err := InitializeBackup(expectedPassword, cb1, &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen) if err != nil { t.Errorf("Failed to initialize new Backup: %+v", err) @@ -106,7 +106,7 @@ func Test_ResumeBackup(t *testing.T) { // Resume the backup with a new callback cbChan2 := make(chan []byte) cb2 := func(encryptedBackup []byte) { cbChan2 <- encryptedBackup } - b2, err := ResumeBackup(cb2, &messenger.Container{}, newMockE2e(t), newMockSession(t), + b2, err := ResumeBackup(cb2, &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen) if err != nil { t.Errorf("ResumeBackup returned an error: %+v", err) @@ -149,7 +149,7 @@ func Test_resumeBackup_NoKeyError(t *testing.T) { expectedErr := "object not found" s := storage.InitTestingSession(t) rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) - _, err := ResumeBackup(nil, &messenger.Container{}, newMockE2e(t), newMockSession(t), + _, err := ResumeBackup(nil, &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), s.GetKV(), rngGen) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("ResumeBackup did not return the expected error when no "+ @@ -392,7 +392,7 @@ func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup { b, err := InitializeBackup( password, cb, - &messenger.Container{}, + &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), @@ -416,7 +416,7 @@ func Benchmark_InitializeBackup(t *testing.B) { expectedPassword := "MySuperSecurePassword" for i := 0; i < t.N; i++ { _, err := InitializeBackup(expectedPassword, cb, - &messenger.Container{}, + &xxdk.Container{}, newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen) if err != nil { diff --git a/bindings/autheticatedConnection.go b/bindings/autheticatedConnection.go index 758b8c741972d61dd6616d9e5691db83837df3d9..5e1f78f4e08f813881f01b3695b423a4c1cd2f1e 100644 --- a/bindings/autheticatedConnection.go +++ b/bindings/autheticatedConnection.go @@ -23,18 +23,18 @@ func (_ *AuthenticatedConnection) IsAuthenticated() bool { // ConnectWithAuthentication is called by the client (i.e. the one establishing // connection with the server). Once a connect.Connection has been established // with the server and then authenticate their identity to the server. -// accepts a marshalled Identity and contact.Contact object -func (c *Client) ConnectWithAuthentication(recipientContact []byte, myIdentity []byte) (*AuthenticatedConnection, error) { +// accepts a marshalled TransmissionIdentity and contact.Contact object +func (c *Cmix) ConnectWithAuthentication(e2eId int, recipientContact []byte) (*AuthenticatedConnection, error) { cont, err := contact.Unmarshal(recipientContact) if err != nil { return nil, err } - myID, rsaPriv, salt, myDHPriv, err := c.unmarshalIdentity(myIdentity) + + e2eClient, err := e2eTrackerSingleton.get(e2eId) if err != nil { return nil, err } - connection, err := connect.ConnectWithAuthentication(cont, myID, salt, rsaPriv, myDHPriv, c.api.GetRng(), - c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams()) + connection, err := connect.ConnectWithAuthentication(cont, e2eClient.api, connect.GetDefaultParams()) return authenticatedConnectionTrackerSingleton.make(connection), nil } diff --git a/bindings/clientTracker.go b/bindings/clientTracker.go deleted file mode 100644 index a93bfc62a1e5b8fc35672ab2ff55701278012cc9..0000000000000000000000000000000000000000 --- a/bindings/clientTracker.go +++ /dev/null @@ -1,54 +0,0 @@ -package bindings - -import ( - "github.com/pkg/errors" - "gitlab.com/elixxir/client/api" - "sync" -) - -// clientTracker is a singleton used to keep track of extant clients, allowing -// for race condition free passing over the bindings - -type clientTracker struct { - clients map[int]*Client - count int - mux sync.RWMutex -} - -// make makes a client from an API client, assigning it a unique ID -func (ct *clientTracker) make(c *api.Client) *Client { - ct.mux.Lock() - defer ct.mux.Unlock() - - id := ct.count - ct.count++ - - ct.clients[id] = &Client{ - api: c, - id: id, - } - - return ct.clients[id] -} - -//get returns a client given its ID -func (ct *clientTracker) get(id int) (*Client, error) { - ct.mux.RLock() - defer ct.mux.RUnlock() - - c, exist := ct.clients[id] - if !exist { - return nil, errors.Errorf("Cannot get client for id %d, client "+ - "does not exist", id) - } - - return c, nil -} - -//deletes a client if it exists -func (ct *clientTracker) delete(id int) { - ct.mux.Lock() - defer ct.mux.Unlock() - - delete(ct.clients, id) -} diff --git a/bindings/client.go b/bindings/cmix.go similarity index 65% rename from bindings/client.go rename to bindings/cmix.go index 24f69dceef7ecd992c6ebdb3543aae8dad18f209..85b847defc73caad18bbbb02de502cb093b57660 100644 --- a/bindings/client.go +++ b/bindings/cmix.go @@ -4,26 +4,26 @@ import ( "fmt" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/api" + "gitlab.com/elixxir/client/xxdk" ) -// sets the log level +// init sets the log level func init() { jww.SetLogThreshold(jww.LevelInfo) jww.SetStdoutThreshold(jww.LevelInfo) } -//client tracker singleton, used to track clients so they can be referenced by -//id back over the bindings -var clientTrackerSingleton = &clientTracker{ - clients: make(map[int]*Client), +// cmixTrackerSingleton is used to track Cmix objects so that +// they can be referenced by id back over the bindings +var cmixTrackerSingleton = &cmixTracker{ + clients: make(map[int]*Cmix), count: 0, } -// Client BindingsClient wraps the api.Client, implementing additional functions -// to support the gomobile Client interface -type Client struct { - api *api.Client +// Cmix BindingsClient wraps the xxdk.Cmix, implementing additional functions +// to support the gomobile Cmix interface +type Cmix struct { + api *xxdk.Cmix id int } @@ -34,7 +34,7 @@ type Client struct { // // Users of this function should delete the storage directory on error. func NewClient(network, storageDir string, password []byte, regCode string) error { - if err := api.NewClient(network, storageDir, password, regCode); err != nil { + if err := xxdk.NewClient(network, storageDir, password, regCode); err != nil { return errors.New(fmt.Sprintf("Failed to create new client: %+v", err)) } @@ -49,19 +49,15 @@ func NewClient(network, storageDir string, password []byte, regCode string) erro // Login does not block on network connection, and instead loads and // starts subprocesses to perform network operations. // TODO: add in custom parameters instead of the default -func Login(storageDir string, password []byte) (*Client, error) { - - client, err := api.Login(storageDir, password, api.GetDefaultParams()) +func Login(storageDir string, password []byte) (*Cmix, error) { + client, err := xxdk.LoadCmix(storageDir, password, xxdk.GetDefaultParams()) if err != nil { return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err)) } - return clientTrackerSingleton.make(client), nil + return cmixTrackerSingleton.make(client), nil } -func (c *Client) GetID() int { +func (c *Cmix) GetID() int { return c.id } - - - diff --git a/bindings/cmixTracker.go b/bindings/cmixTracker.go new file mode 100644 index 0000000000000000000000000000000000000000..cb7d215a0613c780cc228998c381efec8b9ad36a --- /dev/null +++ b/bindings/cmixTracker.go @@ -0,0 +1,54 @@ +package bindings + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/client/xxdk" + "sync" +) + +// cmixTracker is a singleton used to keep track of extant Cmix objects, +// preventing race conditions created by passing it over the bindings +type cmixTracker struct { + clients map[int]*Cmix + count int + mux sync.RWMutex +} + +// make a Cmix from an xxdk.Cmix, assigns it a unique ID, +// and adds it to the cmixTracker +func (ct *cmixTracker) make(c *xxdk.Cmix) *Cmix { + ct.mux.Lock() + defer ct.mux.Unlock() + + id := ct.count + ct.count++ + + ct.clients[id] = &Cmix{ + api: c, + id: id, + } + + return ct.clients[id] +} + +// get a Cmix from the cmixTracker given its ID +func (ct *cmixTracker) get(id int) (*Cmix, error) { + ct.mux.RLock() + defer ct.mux.RUnlock() + + c, exist := ct.clients[id] + if !exist { + return nil, errors.Errorf("Cannot get client for id %d, client "+ + "does not exist", id) + } + + return c, nil +} + +// delete a Cmix if it exists in the cmixTracker +func (ct *cmixTracker) delete(id int) { + ct.mux.Lock() + defer ct.mux.Unlock() + + delete(ct.clients, id) +} diff --git a/bindings/connect.go b/bindings/connect.go index 9910af952b93165e769b15e9e54d508adcf378e3..8be9e4881ec5f345fd7d80b932e22d8d693ae19f 100644 --- a/bindings/connect.go +++ b/bindings/connect.go @@ -31,21 +31,20 @@ func (c *Connection) GetId() int { // This function is to be used sender-side and will block until the // partner.Manager is confirmed. // recipientContact - marshalled contact.Contact object -// myIdentity - marshalled Identity object -func (c *Client) Connect(recipientContact []byte, myIdentity []byte) ( +// myIdentity - marshalled TransmissionIdentity object +func (c *Cmix) Connect(e2eId int, recipientContact []byte) ( *Connection, error) { cont, err := contact.Unmarshal(recipientContact) if err != nil { return nil, err } - myID, _, _, myDHPriv, err := c.unmarshalIdentity(myIdentity) + + e2eClient, err := e2eTrackerSingleton.get(e2eId) if err != nil { return nil, err } - connection, err := connect.Connect(cont, myID, myDHPriv, c.api.GetRng(), - c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams()) - + connection, err := connect.Connect(cont, e2eClient.api, connect.GetDefaultParams()) if err != nil { return nil, err } diff --git a/bindings/contact.go b/bindings/contact.go index cf5647bd1b5a93ec31390d1b9cce2b28719cc907..c07b66f8f790eb9ffb4bdf0081aad25c32c8185c 100644 --- a/bindings/contact.go +++ b/bindings/contact.go @@ -2,16 +2,15 @@ package bindings import ( "encoding/json" - "gitlab.com/elixxir/client/api" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" ) -// Identity struct -// Example marshalled Identity: +// TransmissionIdentity struct +// Example marshalled TransmissionIdentity: // {"ID":"emV6aW1hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD", // User ID (base64) // // RSA Private key (PEM format) // "RSAPrivatePem":"LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBNU15dTdhYjBJOS9UL1BFUUxtd2x3ejZHV3FjMUNYemVIVXhoVEc4bmg1WWRWSXMxCmJ2THpBVjNOMDJxdXN6K2s4TVFEWjBtejMzdkswUmhPczZIY0NUSFdzTEpXRkE5WWpzWWlCRi9qTDd1bmd1ckIKL2tvK1JJSnNrWGFWaEZaazRGdERoRXhTNWY4RnR0Qmk1NmNLZmdJQlVKT3ozZi9qQllTMkxzMlJ6cWV5YXM3SApjV2RaME9TclBTT3BiYlViU1FPbS9LWnlweGZHU21yZ2oxRUZuU1dZZ2xGZTdUOTRPbHF5MG14QTV5clVXbHorCk9sK3hHbXpCNUp4WUFSMU9oMFQrQTk4RWMrTUZHNm43L1MraDdzRDgybGRnVnJmbStFTzRCdmFKeTRESGZGMWgKNnp6QnVnY25NUVFGc0dLeDFYWC9COTVMdUpPVjdyeXlDbzZGbHdJREFRQUJBb0lCQVFDaUh6OGNlcDZvQk9RTAphUzBVRitHeU5VMnlVcVRNTWtTWThoUkh1c09CMmFheXoybHZVb3RLUHBPbjZRSWRWVTJrcE4vY2dtY0lSb2x5CkhBMDRUOHJBWVNaRlVqaVlRajkzKzRFREpJYXd2Z0YyVEs1bFoyb3oxVTdreStncU82V0RMR2Z0Q0wvODVQWEIKa210aXhnUXpRV3g1RWcvemtHdm03eURBalQxeDloNytsRjJwNFlBam5kT2xTS0dmQjFZeTR1RXBQd0kwc1lWdgpKQWc0MEFxbllZUmt4emJPbmQxWGNjdEJFN2Z1VDdrWXhoeSs3WXYrUTJwVy9BYmh6NGlHOEY1MW9GMGZwV0czCmlISDhsVXZFTkp2SUZEVHZ0UEpESlFZalBRN3lUbGlGZUdrMXZUQkcyQkpQNExzVzhpbDZOeUFuRktaY1hOQ24KeHVCendiSlJBb0dCQVBUK0dGTVJGRHRHZVl6NmwzZmg3UjJ0MlhrMysvUmpvR3BDUWREWDhYNERqR1pVd1RGVQpOS2tQTTNjS29ia2RBYlBDb3FpL0tOOVBibk9QVlZ3R3JkSE9vSnNibFVHYmJGamFTUzJQMFZnNUVhTC9rT2dUCmxMMUdoVFpIUWk1VUlMM0p4M1Z3T0ZRQ3RQOU1UQlQ0UEQvcEFLbDg3VTJXN3JTY1dGV1ZGbFNkQW9HQkFPOFUKVmhHWkRpVGFKTWVtSGZIdVYrNmtzaUlsam9aUVVzeGpmTGNMZ2NjV2RmTHBqS0ZWTzJNN3NqcEJEZ0w4NmFnegorVk14ZkQzZ1l0SmNWN01aMVcwNlZ6TlNVTHh3a1dRY1hXUWdDaXc5elpyYlhCUmZRNUVjMFBlblVoWWVwVzF5CkpkTC8rSlpQeDJxSzVrQytiWU5EdmxlNWdpcjlDSGVzTlR5enVyckRBb0dCQUl0cTJnN1RaazhCSVFUUVNrZ24Kb3BkRUtzRW4wZExXcXlBdENtVTlyaWpHL2l2eHlXczMveXZDQWNpWm5VVEp0QUZISHVlbXVTeXplQ2g5QmRkegoyWkRPNUdqQVBxVHlQS3NudFlNZkY4UDczZ1NES1VSWWVFbHFDejdET0c5QzRzcitPK3FoN1B3cCtqUmFoK1ZiCkNuWllNMDlBVDQ3YStJYUJmbWRkaXpLbEFvR0JBSmo1dkRDNmJIQnNISWlhNUNJL1RZaG5YWXUzMkVCYytQM0sKMHF3VThzOCtzZTNpUHBla2Y4RjVHd3RuUU4zc2tsMk1GQWFGYldmeVFZazBpUEVTb0p1cGJzNXA1enNNRkJ1bwpncUZrVnQ0RUZhRDJweTVwM2tQbDJsZjhlZXVwWkZScGE0WmRQdVIrMjZ4eWYrNEJhdlZJeld3NFNPL1V4Q3crCnhqbTNEczRkQW9HQWREL0VOa1BjU004c1BCM3JSWW9MQ2twcUV2U0MzbVZSbjNJd3c1WFAwcDRRVndhRmR1ckMKYUhtSE1EekNrNEUvb0haQVhFdGZ2S2tRaUI4MXVYM2c1aVo4amdYUVhXUHRteTVIcVVhcWJYUTlENkxWc3B0egpKL3R4SWJLMXp5c1o2bk9IY1VoUUwyVVF6SlBBRThZNDdjYzVzTThEN3kwZjJ0QURTQUZNMmN3PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==", @@ -20,7 +19,7 @@ import ( // // DH Private key // "DHKeyPrivate":"eyJWYWx1ZSI6NDU2MDgzOTEzMjA0OTIyODA5Njg2MDI3MzQ0MzM3OTA0MzAyODYwMjM2NDk2NDM5NDI4NTcxMTMwNDMzOTQwMzgyMTIyMjY4OTQzNTMyMjIyMzc1MTkzNTEzMjU4MjA4MDA0NTczMDY4MjEwNzg2NDI5NjA1MjA0OTA3MjI2ODI5OTc3NTczMDkxODY0NTY3NDExMDExNjQxNCwiRmluZ2VycHJpbnQiOjE2ODAxNTQxNTExMjMzMDk4MzYzfQ==" // } -type Identity struct { +type TransmissionIdentity struct { ID []byte RSAPrivatePem []byte Salt []byte @@ -28,17 +27,17 @@ type Identity struct { } // MakeIdentity generates a new cryptographic identity for receiving messages -func (c *Client) MakeIdentity() ([]byte, error) { +func (c *Cmix) MakeIdentity() ([]byte, error) { s := c.api.GetRng().GetStream() defer s.Close() - ident, err := api.MakeIdentity(s, c.api.GetStorage().GetE2EGroup()) + ident, err := xxdk.MakeTransmissionIdentity(s, c.api.GetStorage().GetE2EGroup()) dhPrivJson, err := ident.DHKeyPrivate.MarshalJSON() if err != nil { return nil, err } //create the identity object - I := Identity{ + I := TransmissionIdentity{ ID: ident.ID.Marshal(), RSAPrivatePem: rsa.CreatePrivateKeyPem(ident.RSAPrivatePem), Salt: ident.Salt, @@ -48,19 +47,19 @@ func (c *Client) MakeIdentity() ([]byte, error) { return json.Marshal(&I) } -// GetContactFromIdentity accepts a marshalled Identity object and returns a marshalled contact.Contact object -func (c *Client) GetContactFromIdentity(identity []byte) ([]byte, error) { - uID, _, _, dhKey, err := c.unmarshalIdentity(identity) +// GetContactFromIdentity accepts a marshalled TransmissionIdentity object and returns a marshalled contact.Contact object +func (c *Cmix) GetContactFromIdentity(identity []byte) ([]byte, error) { + unmarshalledIdentity, err := c.unmarshalIdentity(identity) if err != nil { return nil, err } grp := c.api.GetStorage().GetE2EGroup() - dhPub := grp.ExpG(dhKey, grp.NewInt(1)) + dhPub := grp.ExpG(unmarshalledIdentity.DHKeyPrivate, grp.NewInt(1)) ct := contact.Contact{ - ID: uID, + ID: unmarshalledIdentity.ID, DhPubKey: dhPub, OwnershipProof: nil, Facts: nil, @@ -69,31 +68,34 @@ func (c *Client) GetContactFromIdentity(identity []byte) ([]byte, error) { return ct.Marshal(), nil } -func (c *Client) unmarshalIdentity(marshaled []byte) (*id.ID, *rsa.PrivateKey, []byte, - *cyclic.Int, error) { - I := Identity{} - err := json.Unmarshal(marshaled, &I) +func (c *Cmix) unmarshalIdentity(marshaled []byte) (xxdk.TransmissionIdentity, error) { + newIdentity := xxdk.TransmissionIdentity{} + + // Unmarshal given identity into TransmissionIdentity object + givenIdentity := TransmissionIdentity{} + err := json.Unmarshal(marshaled, &givenIdentity) if err != nil { - return nil, nil, nil, nil, err + return xxdk.TransmissionIdentity{}, err } - uID, err := id.Unmarshal(I.ID) + newIdentity.ID, err = id.Unmarshal(givenIdentity.ID) if err != nil { - return nil, nil, nil, nil, err + return xxdk.TransmissionIdentity{}, err } - dhkey := c.api.GetStorage().GetE2EGroup().NewInt(1) - err = dhkey.UnmarshalJSON([]byte(I.DHKeyPrivate)) + newIdentity.DHKeyPrivate = c.api.GetStorage().GetE2EGroup().NewInt(1) + err = newIdentity.DHKeyPrivate.UnmarshalJSON(givenIdentity.DHKeyPrivate) if err != nil { - return nil, nil, nil, nil, err + return xxdk.TransmissionIdentity{}, err } - rsaPriv, err := rsa.LoadPrivateKeyFromPem([]byte(I.RSAPrivatePem)) + newIdentity.RSAPrivatePem, err = rsa.LoadPrivateKeyFromPem(givenIdentity.RSAPrivatePem) if err != nil { - return nil, nil, nil, nil, err + return xxdk.TransmissionIdentity{}, err } - return uID, rsaPriv, I.Salt, dhkey, nil + newIdentity.Salt = givenIdentity.Salt + return newIdentity, nil } // GetIDFromContact accepts a marshalled contact.Contact object & returns a marshalled id.ID object diff --git a/bindings/contact_test.go b/bindings/contact_test.go index adbf4d9c2a5d3c48e899ee5ba7f4123f44890034..97af0264f4bd9b76c9fe83017ff09477947b7a3d 100644 --- a/bindings/contact_test.go +++ b/bindings/contact_test.go @@ -22,14 +22,14 @@ func TestIdentity_JSON(t *testing.T) { dhpkJson, _ := dhpk.MarshalJSON() op := make([]byte, 64) _, _ = rng.Read(op) - identity := Identity{ + identity := TransmissionIdentity{ ID: uid.Marshal(), RSAPrivatePem: rsa.CreatePrivateKeyPem(pk), Salt: salt, DHKeyPrivate: dhpkJson, } im, _ := json.Marshal(identity) - t.Log("Marshalled Identity object") + t.Log("Marshalled TransmissionIdentity object") t.Log(string(im)) } diff --git a/bindings/delivery.go b/bindings/delivery.go index 57fcbfa4d34ede1307cb628691ca5fde4210bd47..9146e838f4381661385e4769b20a95ff4f74320b 100644 --- a/bindings/delivery.go +++ b/bindings/delivery.go @@ -65,7 +65,7 @@ type MessageDeliveryCallback interface { // This function takes the marshaled send report to ensure a memory leak does // not occur as a result of both sides of the bindings holding a reference to // the same pointer. -func (c *Client) WaitForMessageDelivery(roundList []byte, +func (c *Cmix) WaitForMessageDelivery(roundList []byte, mdc MessageDeliveryCallback, timeoutMS int) error { jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)", roundList, timeoutMS) diff --git a/bindings/e2e.go b/bindings/e2e.go new file mode 100644 index 0000000000000000000000000000000000000000..6134db25db442727b6d32873f1f11d795f8d8f2c --- /dev/null +++ b/bindings/e2e.go @@ -0,0 +1,100 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "gitlab.com/elixxir/client/auth" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/crypto/contact" +) + +// e2eTrackerSingleton is used to track E2e objects so that +// they can be referenced by id back over the bindings +var e2eTrackerSingleton = &e2eTracker{ + clients: make(map[int]*E2e), + count: 0, +} + +// E2e BindingsClient wraps the xxdk.E2e, implementing additional functions +// to support the gomobile E2e interface +type E2e struct { + api *xxdk.E2e + id int +} + +// Login creates and returns a new E2e object and adds it to the e2eTrackerSingleton +// identity should be created via MakeIdentity() and passed in here +// If callbacks is left nil, a default auth.Callbacks will be used +func (e *E2e) Login(cmixId int, callbacks AuthCallbacks, identity []byte) (*E2e, error) { + cmix, err := cmixTrackerSingleton.get(cmixId) + if err != nil { + return nil, err + } + + newIdentity, err := cmix.unmarshalIdentity(identity) + if err != nil { + return nil, err + } + + var authCallbacks auth.Callbacks + if callbacks == nil { + authCallbacks = auth.DefaultAuthCallbacks{} + } else { + authCallbacks = &authCallback{bindingsCbs: callbacks} + } + + newE2e, err := xxdk.Login(cmix.api, authCallbacks, newIdentity) + if err != nil { + return nil, err + } + return e2eTrackerSingleton.make(newE2e), nil +} + +// AuthCallbacks is the bindings-specific interface for auth.Callbacks methods. +type AuthCallbacks interface { + Request(contact, receptionId []byte, ephemeralId, roundId int64) + Confirm(contact, receptionId []byte, ephemeralId, roundId int64) + Reset(contact, receptionId []byte, ephemeralId, roundId int64) +} + +// authCallback implements AuthCallbacks as a way of obtaining +// an auth.Callbacks over the bindings +type authCallback struct { + bindingsCbs AuthCallbacks +} + +// convertAuthCallbacks turns an auth.Callbacks into an AuthCallbacks +func convertAuthCallbacks(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, + round rounds.Round) (contact []byte, receptionId []byte, ephemeralId int64, roundId int64) { + + contact = requestor.Marshal() + receptionId = receptionID.Source.Marshal() + ephemeralId = int64(receptionID.EphId.UInt64()) + roundId = int64(round.ID) + return +} + +// Confirm will be called when an auth Confirm message is processed. +func (a *authCallback) Confirm(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + a.bindingsCbs.Confirm(convertAuthCallbacks(requestor, receptionID, round)) +} + +// Request will be called when an auth Request message is processed. +func (a *authCallback) Request(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + a.bindingsCbs.Request(convertAuthCallbacks(requestor, receptionID, round)) +} + +// Reset will be called when an auth Reset operation occurs. +func (a *authCallback) Reset(requestor contact.Contact, + receptionID receptionID.EphemeralIdentity, round rounds.Round) { + a.bindingsCbs.Reset(convertAuthCallbacks(requestor, receptionID, round)) +} diff --git a/bindings/e2eTracker.go b/bindings/e2eTracker.go new file mode 100644 index 0000000000000000000000000000000000000000..8f3ff5374ddb048642eeeda0a74a04a7f6bc3c44 --- /dev/null +++ b/bindings/e2eTracker.go @@ -0,0 +1,61 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/client/xxdk" + "sync" +) + +// e2eTracker is a singleton used to keep track of extant E2e objects, +// preventing race conditions created by passing it over the bindings +type e2eTracker struct { + // TODO: Key on Identity.ID to prevent duplication + clients map[int]*E2e + count int + mux sync.RWMutex +} + +// make a E2e from an xxdk.E2e, assigns it a unique ID, +// and adds it to the e2eTracker +func (ct *e2eTracker) make(c *xxdk.E2e) *E2e { + ct.mux.Lock() + defer ct.mux.Unlock() + + id := ct.count + ct.count++ + + ct.clients[id] = &E2e{ + api: c, + id: id, + } + + return ct.clients[id] +} + +// get an E2e from the e2eTracker given its ID +func (ct *e2eTracker) get(id int) (*E2e, error) { + ct.mux.RLock() + defer ct.mux.RUnlock() + + c, exist := ct.clients[id] + if !exist { + return nil, errors.Errorf("Cannot get client for id %d, client "+ + "does not exist", id) + } + + return c, nil +} + +// delete an E2e if it exists in the e2eTracker +func (ct *e2eTracker) delete(id int) { + ct.mux.Lock() + defer ct.mux.Unlock() + + delete(ct.clients, id) +} diff --git a/bindings/follow.go b/bindings/follow.go index ae81595b23ed0bbb627f6e112b86c5af47903919..34bb4c58eabffb120a2fc1dbad6cfc57b51324d5 100644 --- a/bindings/follow.go +++ b/bindings/follow.go @@ -35,7 +35,7 @@ import ( // Responds to sent rekeys and executes them // - KeyExchange Confirm (/keyExchange/confirm.go) // Responds to confirmations of successful rekey operations -func (c *Client) StartNetworkFollower(timeoutMS int) error { +func (c *Cmix) StartNetworkFollower(timeoutMS int) error { timeout := time.Duration(timeoutMS) * time.Millisecond return c.api.StartNetworkFollower(timeout) } @@ -45,7 +45,7 @@ func (c *Client) StartNetworkFollower(timeoutMS int) error { // fails to stop it. // if the network follower is running and this fails, the client object will // most likely be in an unrecoverable state and need to be trashed. -func (c *Client) StopNetworkFollower() error { +func (c *Cmix) StopNetworkFollower() error { if err := c.api.StopNetworkFollower(); err != nil { return errors.New(fmt.Sprintf("Failed to stop the "+ "network follower: %+v", err)) @@ -55,7 +55,7 @@ func (c *Client) StopNetworkFollower() error { // WaitForNewtwork will block until either the network is healthy or the // passed timeout. It will return true if the network is healthy -func (c *Client) WaitForNetwork(timeoutMS int) bool { +func (c *Cmix) WaitForNetwork(timeoutMS int) bool { start := netTime.Now() timeout := time.Duration(timeoutMS) * time.Millisecond for netTime.Since(start) < timeout { @@ -72,7 +72,7 @@ func (c *Client) WaitForNetwork(timeoutMS int) bool { // Starting - 1000 // Running - 2000 // Stopping - 3000 -func (c *Client) NetworkFollowerStatus() int { +func (c *Cmix) NetworkFollowerStatus() int { return int(c.api.NetworkFollowerStatus()) } @@ -82,13 +82,13 @@ func (c *Client) NetworkFollowerStatus() int { // Due to the handling of comms on iOS, where the OS can // block indefiently, it may not enter the stopped // state apropreatly. This can be used instead. -func (c *Client) HasRunningProcessies() bool { +func (c *Cmix) HasRunningProcessies() bool { return c.api.HasRunningProcessies() } // IsNetworkHealthy returns true if the network is read to be in a healthy state where // messages can be sent -func (c *Client) IsNetworkHealthy() bool { +func (c *Cmix) IsNetworkHealthy() bool { return c.api.GetCmix().IsHealthy() } @@ -101,11 +101,11 @@ type NetworkHealthCallback interface { // RegisterNetworkHealthCB registers the network health callback to be called // any time the network health changes. Returns a unique ID that can be used to // unregister the network health callback. -func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 { +func (c *Cmix) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 { return int64(c.api.GetCmix().AddHealthCallback(nhc.Callback)) } -func (c *Client) UnregisterNetworkHealthCB(funcID int64) { +func (c *Cmix) UnregisterNetworkHealthCB(funcID int64) { c.api.GetCmix().RemoveHealthCallback(uint64(funcID)) } @@ -115,7 +115,7 @@ type ClientError interface { // RegisterClientErrorCallback registers the callback to handle errors from the // long running threads controlled by StartNetworkFollower and StopNetworkFollower -func (c *Client) RegisterClientErrorCallback(clientError ClientError) { +func (c *Cmix) RegisterClientErrorCallback(clientError ClientError) { errChan := c.api.GetErrorsChannel() go func() { for report := range errChan { diff --git a/bindings/ndf.go b/bindings/ndf.go index 05e7d40b364678a028b66001c5de907840d1f6a7..ed72aa1d6a98c33861d814d18f032c7396e1a099 100644 --- a/bindings/ndf.go +++ b/bindings/ndf.go @@ -1,11 +1,11 @@ package bindings -import "gitlab.com/elixxir/client/api" +import "gitlab.com/elixxir/client/xxdk" // DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL. // The NDF is processed into a protobuf containing a signature which // is verified using the cert string passed in. The NDF is returned as marshaled // byte data which may be used to start a client. func DownloadAndVerifySignedNdfWithUrl(url, cert string) ([]byte, error) { - return api.DownloadAndVerifySignedNdfWithUrl(url, cert) + return xxdk.DownloadAndVerifySignedNdfWithUrl(url, cert) } diff --git a/bindings/restlike.go b/bindings/restlike.go index 7d7e649310d47d8fb4b28f7091569b195e131b83..c6c31c7ae744e644747a8da6018471fd03b8680e 100644 --- a/bindings/restlike.go +++ b/bindings/restlike.go @@ -34,7 +34,7 @@ type RestlikeMessage struct { // request - marshalled RestlikeMessage // Returns marshalled result RestlikeMessage func RestlikeRequest(clientID int, connectionID int, request []byte) ([]byte, error) { - cl, err := clientTrackerSingleton.get(clientID) + cl, err := cmixTrackerSingleton.get(clientID) if err != nil { return nil, err } @@ -78,7 +78,7 @@ func RestlikeRequest(clientID int, connectionID int, request []byte) ([]byte, er // request - marshalled RestlikeMessage // Returns marshalled result RestlikeMessage func RestlikeRequestAuth(clientID int, authConnectionID int, request []byte) ([]byte, error) { - cl, err := clientTrackerSingleton.get(clientID) + cl, err := cmixTrackerSingleton.get(clientID) if err != nil { return nil, err } diff --git a/bindings/version.go b/bindings/version.go index 7e84bbd2ed1a0de0825e47a24e5e62ffa2f9f78a..4d6a4b2dc2dd86b1881aa3c918062cd50052fd98 100644 --- a/bindings/version.go +++ b/bindings/version.go @@ -6,19 +6,19 @@ package bindings -import "gitlab.com/elixxir/client/api" +import "gitlab.com/elixxir/client/xxdk" // GetVersion returns the api SEMVER func GetVersion() string { - return api.SEMVER + return xxdk.SEMVER } // GetGitVersion rturns the api GITVERSION func GetGitVersion() string { - return api.GITVERSION + return xxdk.GITVERSION } // GetDependencies returns the api DEPENDENCIES func GetDependencies() string { - return api.DEPENDENCIES + return xxdk.DEPENDENCIES } diff --git a/broadcast/asymmetric_test.go b/broadcast/asymmetric_test.go index 2df1c2eb3d5c46de22c0c530b01f08ab97e6cd94..88aa2219d3495beb4659b97f5aa34ca4baf9c27f 100644 --- a/broadcast/asymmetric_test.go +++ b/broadcast/asymmetric_test.go @@ -66,7 +66,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { // Test that Get returns the expected channel if !reflect.DeepEqual(s.Get(), channel) { - t.Errorf("Client %d returned wrong channel."+ + t.Errorf("Cmix %d returned wrong channel."+ "\nexpected: %+v\nreceived: %+v", i, channel, s.Get()) } } @@ -86,12 +86,12 @@ func Test_asymmetricClient_Smoke(t *testing.T) { select { case r := <-cbChan: if !bytes.Equal(payload, r) { - t.Errorf("Client %d failed to receive expected "+ + t.Errorf("Cmix %d failed to receive expected "+ "payload from client %d."+ "\nexpected: %q\nreceived: %q", j, i, payload, r) } case <-time.After(time.Second): - t.Errorf("Client %d timed out waiting for broadcast "+ + t.Errorf("Cmix %d timed out waiting for broadcast "+ "payload from client %d.", j, i) } }(i, j, cbChans[j]) @@ -100,7 +100,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { // Broadcast payload _, _, err := clients[i].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams()) if err != nil { - t.Errorf("Client %d failed to send broadcast: %+v", i, err) + t.Errorf("Cmix %d failed to send broadcast: %+v", i, err) } // Wait for all clients to receive payload or time out @@ -123,7 +123,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { defer wg.Done() select { case r := <-cbChan: - t.Errorf("Client %d received message: %q", i, r) + t.Errorf("Cmix %d received message: %q", i, r) case <-time.After(25 * time.Millisecond): } }(i, cbChans[i]) @@ -132,7 +132,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { // Broadcast payload _, _, err = clients[0].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams()) if err != nil { - t.Errorf("Client 0 failed to send broadcast: %+v", err) + t.Errorf("Cmix 0 failed to send broadcast: %+v", err) } wg.Wait() diff --git a/broadcast/symmetric_test.go b/broadcast/symmetric_test.go index a35ea5ecdca77b9abb5d874b3a28c99be6f08a7a..de76da504ca02fa6b8b1aa558bbef20a865a7730 100644 --- a/broadcast/symmetric_test.go +++ b/broadcast/symmetric_test.go @@ -72,7 +72,7 @@ func Test_symmetricClient_Smoke(t *testing.T) { // Test that Get returns the expected channel if !reflect.DeepEqual(s.Get(), channel) { - t.Errorf("Client %d returned wrong channel."+ + t.Errorf("Cmix %d returned wrong channel."+ "\nexpected: %+v\nreceived: %+v", i, channel, s.Get()) } } @@ -92,12 +92,12 @@ func Test_symmetricClient_Smoke(t *testing.T) { select { case r := <-cbChan: if !bytes.Equal(payload, r) { - t.Errorf("Client %d failed to receive expected "+ + t.Errorf("Cmix %d failed to receive expected "+ "payload from client %d."+ "\nexpected: %q\nreceived: %q", j, i, payload, r) } case <-time.After(25 * time.Millisecond): - t.Errorf("Client %d timed out waiting for broadcast "+ + t.Errorf("Cmix %d timed out waiting for broadcast "+ "payload from client %d.", j, i) } }(i, j, cbChans[j]) @@ -106,7 +106,7 @@ func Test_symmetricClient_Smoke(t *testing.T) { // Broadcast payload _, _, err := clients[i].Broadcast(payload, cmix.GetDefaultCMIXParams()) if err != nil { - t.Errorf("Client %d failed to send broadcast: %+v", i, err) + t.Errorf("Cmix %d failed to send broadcast: %+v", i, err) } // Wait for all clients to receive payload or time out @@ -129,7 +129,7 @@ func Test_symmetricClient_Smoke(t *testing.T) { defer wg.Done() select { case r := <-cbChan: - t.Errorf("Client %d received message: %q", i, r) + t.Errorf("Cmix %d received message: %q", i, r) case <-time.After(25 * time.Millisecond): } }(i, cbChans[i]) @@ -138,7 +138,7 @@ func Test_symmetricClient_Smoke(t *testing.T) { // Broadcast payload _, _, err = clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams()) if err != nil { - t.Errorf("Client 0 failed to send broadcast: %+v", err) + t.Errorf("Cmix 0 failed to send broadcast: %+v", err) } wg.Wait() diff --git a/broadcast/utils_test.go b/broadcast/utils_test.go index 944fd3c3993dce55cfe153b8b1c29cd828b66c5c..7bd4ac341a47f98359c76c7a06a5adb70f85f05f 100644 --- a/broadcast/utils_test.go +++ b/broadcast/utils_test.go @@ -34,7 +34,7 @@ func newRsaPubKey(seed int64, t *testing.T) *rsa.PublicKey { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/cmd/callbacks.go b/cmd/callbacks.go index 07a4c66acd68cd14601ea63d32d9a30ddce28b4f..66a6ba9f2784540811ad192334d8270ded4005d1 100644 --- a/cmd/callbacks.go +++ b/cmd/callbacks.go @@ -10,7 +10,7 @@ package cmd import ( "fmt" - "gitlab.com/elixxir/client/api/messenger" + "gitlab.com/elixxir/client/xxdk" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" @@ -25,10 +25,10 @@ import ( type authCallbacks struct { autoConfirm bool confCh chan *id.ID - client *messenger.Client + client *xxdk.E2e } -func makeAuthCallbacks(client *messenger.Client, autoConfirm bool) *authCallbacks { +func makeAuthCallbacks(client *xxdk.E2e, autoConfirm bool) *authCallbacks { return &authCallbacks{ autoConfirm: autoConfirm, confCh: make(chan *id.ID, 10), @@ -71,7 +71,7 @@ func (a *authCallbacks) Reset(requestor contact.Contact, fmt.Printf(msg) } -func registerMessageListener(client *messenger.Client) chan receive.Message { +func registerMessageListener(client *xxdk.E2e) chan receive.Message { recvCh := make(chan receive.Message, 10000) listenerID := client.GetE2E().RegisterChannel("DefaultCLIReceiver", receive.AnyUser(), catalog.NoType, recvCh) diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go index 5122d9d526f958462e5a71f9bcfac24f6a32ec72..e11e320de7c44ae9fb164cb7b1160090df8fc80f 100644 --- a/cmd/fileTransfer.go +++ b/cmd/fileTransfer.go @@ -9,7 +9,7 @@ package cmd import ( "fmt" - "gitlab.com/elixxir/client/api/messenger" + "gitlab.com/elixxir/client/xxdk" "io/ioutil" "time" @@ -132,7 +132,7 @@ type receivedFtResults struct { // initFileTransferManager creates a new file transfer manager with a new // reception callback. Returns the file transfer manager and the channel that // will be triggered when the callback is called. -func initFileTransferManager(client *messenger.Client, maxThroughput int) ( +func initFileTransferManager(client *xxdk.E2e, maxThroughput int) ( *ftE2e.Wrapper, chan receivedFtResults) { // Create interfaces.ReceiveCallback that returns the results on a channel diff --git a/cmd/getndf.go b/cmd/getndf.go index 7b54755091ee841590d0b0fe1b5daf52c7d503b9..429f2238df30350497c1d0dd178fae7079847761 100644 --- a/cmd/getndf.go +++ b/cmd/getndf.go @@ -18,7 +18,7 @@ import ( // "gitlab.com/elixxir/client/switchboard" // "gitlab.com/elixxir/client/ud" // "gitlab.com/elixxir/primitives/fact" - "gitlab.com/elixxir/client/api" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/comms/client" "gitlab.com/xx_network/comms/connect" //"time" @@ -47,23 +47,23 @@ var getNDFCmd = &cobra.Command{ var err error switch viper.GetString("env") { case mainnet: - ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(mainNetUrl, mainNetCert) + ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(mainNetUrl, mainNetCert) if err != nil { jww.FATAL.Panicf(err.Error()) } case release: - ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(releaseUrl, releaseCert) + ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(releaseUrl, releaseCert) if err != nil { jww.FATAL.Panicf(err.Error()) } case dev: - ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(devUrl, devCert) + ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(devUrl, devCert) if err != nil { jww.FATAL.Panicf(err.Error()) } case testnet: - ndfJSON, err = api.DownloadAndVerifySignedNdfWithUrl(testNetUrl, testNetCert) + ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(testNetUrl, testNetCert) if err != nil { jww.FATAL.Panicf(err.Error()) } @@ -113,7 +113,7 @@ var getNDFCmd = &cobra.Command{ }, LastUpdate: uint64(0), ReceptionID: dummyID[:], - ClientVersion: []byte(api.SEMVER), + ClientVersion: []byte(xxdk.SEMVER), } resp, err := comms.SendPoll(host, pollMsg) if err != nil { diff --git a/cmd/group.go b/cmd/group.go index fce4f5989c733a0fe2b7fa3f72ab625d29797698..8ea7fd73870ec504605674be1f3c2817412abe75 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -12,9 +12,9 @@ package cmd import ( "bufio" "fmt" - "gitlab.com/elixxir/client/api/messenger" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/primitives/format" "os" "time" @@ -115,7 +115,7 @@ var groupCmd = &cobra.Command{ // initGroupManager creates a new group chat manager and starts the process // service. -func initGroupManager(client *messenger.Client) (groupChat.GroupChat, +func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat, chan groupChat.MessageReceive, chan groupStore.Group) { recChan := make(chan groupChat.MessageReceive, 10) diff --git a/cmd/init.go b/cmd/init.go index ad48ca4850e5046c89b6e7b73ea212cad77856d9..6c42b9cfc6a887d5f1dd3aacec85eb36ab47fb9e 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -10,21 +10,21 @@ package cmd import ( "fmt" + "gitlab.com/elixxir/client/xxdk" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/api/messenger" ) // initCmd creates a new user object with the given NDF var initCmd = &cobra.Command{ Use: "init", - Short: ("Initialize a user ID but do not connect to the network"), + Short: "Initialize a user ID but do not connect to the network", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { client := createClient() - e2e, err := messenger.LoadOrInitE2e(client) + e2e, err := xxdk.LoadOrInitE2e(client) if err != nil { jww.FATAL.Panicf("%+v", err) } diff --git a/cmd/precan.go b/cmd/precan.go index 4a4050efe99237135d5dfb3c9aaf028f3d77974f..64a558ee167f0d3ad9bdb5e1e04326947f510d3d 100644 --- a/cmd/precan.go +++ b/cmd/precan.go @@ -11,7 +11,7 @@ package cmd import ( "encoding/binary" - "gitlab.com/elixxir/client/api/messenger" + "gitlab.com/elixxir/client/xxdk" "strconv" jww "github.com/spf13/jwalterweatherman" @@ -67,7 +67,7 @@ func getPrecanID(recipientID *id.ID) uint { return uint(recipientID.Bytes()[7]) } -func addPrecanAuthenticatedChannel(client *messenger.Client, recipientID *id.ID, +func addPrecanAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, recipient contact.Contact) { jww.WARN.Printf("Precanned user id detected: %s", recipientID) preUsr, err := client.MakePrecannedAuthenticatedChannel( diff --git a/cmd/root.go b/cmd/root.go index 2cb00cb226da464c30039c07cd125e79f37b90b9..f4f26ef17080c2caded6f8ade4a240658658cd14 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -25,9 +25,9 @@ import ( "sync" "time" - "gitlab.com/elixxir/client/api/messenger" "gitlab.com/elixxir/client/backup" "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" @@ -36,7 +36,6 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/api" backupCrypto "gitlab.com/elixxir/crypto/backup" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/excludedRounds" @@ -516,7 +515,7 @@ var rootCmd = &cobra.Command{ }, } -func createClient() *api.Client { +func createClient() *xxdk.Cmix { logLevel := viper.GetUint("logLevel") initLog(logLevel, viper.GetString("log")) jww.INFO.Printf(Version()) @@ -539,17 +538,17 @@ func createClient() *api.Client { } if precannedID != 0 { - err = api.NewPrecannedClient(precannedID, + err = xxdk.NewPrecannedClient(precannedID, string(ndfJSON), storeDir, pass) } else if protoUserPath != "" { protoUserJson, err := utils.ReadFile(protoUserPath) if err != nil { jww.FATAL.Panicf("%v", err) } - err = api.NewProtoClient_Unsafe(string(ndfJSON), storeDir, + err = xxdk.NewProtoClient_Unsafe(string(ndfJSON), storeDir, pass, protoUserJson) } else if userIDprefix != "" { - err = api.NewVanityClient(string(ndfJSON), storeDir, + err = xxdk.NewVanityClient(string(ndfJSON), storeDir, pass, regCode, userIDprefix) } else if backupPath != "" { @@ -568,7 +567,7 @@ func createClient() *api.Client { } // Construct client from backup data - backupIdList, _, err := messenger.NewClientFromBackup(string(ndfJSON), storeDir, + backupIdList, _, err := backup.NewClientFromBackup(string(ndfJSON), storeDir, pass, backupPass, backupFile) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -591,7 +590,7 @@ func createClient() *api.Client { } } else { - err = api.NewClient(string(ndfJSON), storeDir, + err = xxdk.NewClient(string(ndfJSON), storeDir, pass, regCode) } @@ -602,15 +601,15 @@ func createClient() *api.Client { params := initParams() - client, err := api.OpenClient(storeDir, pass, params) + client, err := xxdk.OpenCmix(storeDir, pass, params) if err != nil { jww.FATAL.Panicf("%+v", err) } return client } -func initParams() api.Params { - p := api.GetDefaultParams() +func initParams() xxdk.Params { + p := xxdk.GetDefaultParams() p.Session.MinKeys = uint16(viper.GetUint("e2eMinKeys")) p.Session.MaxKeys = uint16(viper.GetUint("e2eMaxKeys")) p.Session.NumRekeys = uint16(viper.GetUint("e2eNumReKeys")) @@ -630,7 +629,7 @@ func initParams() api.Params { return p } -func initClient() *messenger.Client { +func initClient() *xxdk.E2e { createClient() pass := parsePassword(viper.GetString("password")) @@ -640,7 +639,7 @@ func initClient() *messenger.Client { params := initParams() // load the client - baseclient, err := api.Login(storeDir, pass, params) + baseclient, err := xxdk.LoadCmix(storeDir, pass, params) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -649,7 +648,7 @@ func initClient() *messenger.Client { authCbs = makeAuthCallbacks(nil, viper.GetBool("unsafe-channel-creation")) - client, err := messenger.Login(baseclient, authCbs) + client, err := xxdk.LoginLegacy(baseclient, authCbs) if err != nil { jww.FATAL.Panicf("%+v", err) } @@ -716,7 +715,7 @@ func initClient() *messenger.Client { return client } -func acceptChannel(client *messenger.Client, recipientID *id.ID) id.Round { +func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round { recipientContact, err := client.GetAuth().GetReceivedRequest( recipientID) if err != nil { @@ -731,14 +730,14 @@ func acceptChannel(client *messenger.Client, recipientID *id.ID) id.Round { return rid } -func deleteChannel(client *messenger.Client, partnerId *id.ID) { +func deleteChannel(client *xxdk.E2e, partnerId *id.ID) { err := client.DeleteContact(partnerId) if err != nil { jww.FATAL.Panicf("%+v", err) } } -func addAuthenticatedChannel(client *messenger.Client, recipientID *id.ID, +func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, recipient contact.Contact) { var allowed bool if viper.GetBool("unsafe-channel-creation") { @@ -784,7 +783,7 @@ func addAuthenticatedChannel(client *messenger.Client, recipientID *id.ID, } } -func resetAuthenticatedChannel(client *messenger.Client, recipientID *id.ID, +func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, recipient contact.Contact) { var allowed bool if viper.GetBool("unsafe-channel-creation") { @@ -825,7 +824,7 @@ func resetAuthenticatedChannel(client *messenger.Client, recipientID *id.ID, } } -func acceptChannelVerified(client *messenger.Client, recipientID *id.ID, +func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID, roundTimeout time.Duration) { done := make(chan struct{}, 1) retryChan := make(chan struct{}, 1) @@ -859,7 +858,7 @@ func acceptChannelVerified(client *messenger.Client, recipientID *id.ID, } } -func requestChannelVerified(client *messenger.Client, +func requestChannelVerified(client *xxdk.E2e, recipientContact, me contact.Contact) { paramsE2E := e2e.GetDefaultParams() roundTimeout := paramsE2E.CMIXParams.SendTimeout @@ -899,7 +898,7 @@ func requestChannelVerified(client *messenger.Client, } } -func resetChannelVerified(client *messenger.Client, recipientContact contact.Contact) { +func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact) { paramsE2E := e2e.GetDefaultParams() roundTimeout := paramsE2E.CMIXParams.SendTimeout @@ -1177,7 +1176,7 @@ func init() { viper.BindPFlag("log", rootCmd.PersistentFlags().Lookup("log")) rootCmd.Flags().StringP("regcode", "", "", - "Identity code (optional)") + "TransmissionIdentity code (optional)") viper.BindPFlag("regcode", rootCmd.Flags().Lookup("regcode")) rootCmd.PersistentFlags().StringP("message", "m", "", diff --git a/cmd/single.go b/cmd/single.go index 558ad39ebe3700900732d7e10379138acd04a4ab..2ce03e5c35162a909d3c502410ed35bede436c13 100644 --- a/cmd/single.go +++ b/cmd/single.go @@ -16,11 +16,11 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/single" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/utils" ) @@ -92,7 +92,7 @@ var singleCmd = &cobra.Command{ partner := readSingleUseContact("contact") maxMessages := uint8(viper.GetUint("maxMessages")) - sendSingleUse(client.Client, partner, payload, + sendSingleUse(client.Cmix, partner, payload, maxMessages, timeout, tag) } @@ -152,7 +152,7 @@ func (r *Response) Callback(payload []byte, receptionID receptionID.EphemeralIde } // sendSingleUse sends a single use message. -func sendSingleUse(m *api.Client, partner contact.Contact, payload []byte, +func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte, maxMessages uint8, timeout time.Duration, tag string) { // Construct callback callback := &Response{ diff --git a/cmd/version.go b/cmd/version.go index f657df9a85100c56590cdbe93873a13f0da75678..41055fef35186085ee0747b89bc17332b13a95df 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -13,7 +13,7 @@ import ( "fmt" "github.com/spf13/cobra" - "gitlab.com/elixxir/client/api" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/xx_network/primitives/utils" ) @@ -21,9 +21,9 @@ import ( const currentVersion = "4.2.0" func Version() string { - out := fmt.Sprintf("Elixxir Client v%s -- %s\n\n", api.SEMVER, - api.GITVERSION) - out += fmt.Sprintf("Dependencies:\n\n%s\n", api.DEPENDENCIES) + out := fmt.Sprintf("Elixxir Cmix v%s -- %s\n\n", xxdk.SEMVER, + xxdk.GITVERSION) + out += fmt.Sprintf("Dependencies:\n\n%s\n", xxdk.DEPENDENCIES) return out } diff --git a/cmix/client.go b/cmix/client.go index 15318e5f7cd4cdad302547f09bef96a3d09f8655..92c2d1a1486f1a68c2e2d7672bab34e126cd4a16 100644 --- a/cmix/client.go +++ b/cmix/client.go @@ -140,7 +140,7 @@ func (c *client) Connect(ndf *ndf.NetworkDefinition) error { // Set up gateway.Sender poolParams := gateway.DefaultPoolParams() - // Client will not send KeepAlive packets + // Disable KeepAlive packets poolParams.HostParams.KaClientOpts.Time = time.Duration(math.MaxInt64) // Enable optimized HostPool initialization diff --git a/cmix/follow.go b/cmix/follow.go index 58c693d09d31642af19fd8a8115b35037bce96ae..29eb9035a252a00b3af8cc80a0768b54d8e528b1 100644 --- a/cmix/follow.go +++ b/cmix/follow.go @@ -224,7 +224,7 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source, marshaledTid := c.session.GetTransmissionID().Marshal() for _, clientErr := range update.ClientErrors { - // If this Client appears in the ClientError + // If this ClientId appears in the ClientError if bytes.Equal(clientErr.ClientId, marshaledTid) { // Obtain relevant NodeGateway information diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go index 52b29d45f1661cb025799d993e401e2dd9108cc3..33bf7e9837fd51a9fa059cd3ddef7ae11158ced1 100644 --- a/cmix/gateway/hostPool.go +++ b/cmix/gateway/hostPool.go @@ -66,7 +66,7 @@ type HostManager interface { // accepted. type Filter func(map[id.ID]int, *ndf.NetworkDefinition) map[id.ID]int -// HostPool Handles providing hosts to the Client +// HostPool Handles providing hosts to the client type HostPool struct { hostMap map[id.ID]uint32 // Map key to its index in the slice hostList []*connect.Host // Each index in the slice contains the value diff --git a/cmix/identity/tracker.go b/cmix/identity/tracker.go index 18e68d2f7bc34eab98affbf202e88c1a1efef296..7d9b7aaae3cbae55e8a7b5d83ed06b59649807c5 100644 --- a/cmix/identity/tracker.go +++ b/cmix/identity/tracker.go @@ -103,21 +103,8 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager }) } else { jww.WARN.Printf("No tracked identities found and no legacy " + - "stored timestamp found; creating a new tracked identity " + - "from scratch.") - - t.tracked = append(t.tracked, TrackedID{ - // Make the next generation now so a generation triggers on - // first run - NextGeneration: netTime.Now(), - // Start generation 24 hours ago to make sure all resent - // ephemeral do pickups - // TODO: Should we go back farther? - LastGeneration: netTime.Now().Add(-time.Duration(ephemeral.Period)), - Source: t.session.GetReceptionID(), - ValidUntil: Forever, - Persistent: true, - }) + "stored timestamp found; no messages can be picked up until an " + + "identity is added.") } } else if err != nil { jww.FATAL.Panicf("Unable to create new Tracker: %+v", err) diff --git a/cmix/interface.go b/cmix/interface.go index c03dc1296249a8174916e87f7de2836bd1c7d39f..41e15dd3e981daf718f53f2198d0d708aa525e48 100644 --- a/cmix/interface.go +++ b/cmix/interface.go @@ -212,7 +212,7 @@ type Client interface { /* === Nodes ============================================================ */ /* Keys must be registered with nodes in order to send messages through them. This process is, in general, automatically handled by the Network - Client. */ + client. */ // HasNode can be used to determine if a keying relationship exists with a // node. @@ -229,7 +229,7 @@ type Client interface { /* === Rounds =========================================================== */ /* A complete set of round info is not kept on the client, and sometimes the network will need to be queried to get round info. Historical rounds - is the system internal to the Network Client to do this. It can be used + is the system internal to the Network client to do this. It can be used externally as well. */ // GetRoundResults adjudicates on the rounds requested. Checks if they are diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go index f41b6b88e2cf476c59f8b00344cfff7101537673..4a99c358427314446ccd557afe9596f15ffd7440 100644 --- a/cmix/nodes/request.go +++ b/cmix/nodes/request.go @@ -218,6 +218,6 @@ func processRequestResponse(signedKeyResponse *pb.SignedKeyResponse, // Construct the transmission key from the client key transmissionKey := grp.NewIntFromBytes(clientKey) - // Use Client keypair to sign Server nonce + // Use Cmix keypair to sign Server nonce return transmissionKey, keyResponse.KeyID, keyResponse.ValidUntil, nil } diff --git a/cmix/nodes/utils_test.go b/cmix/nodes/utils_test.go index 5c97dadf3c77bd1309251a23850d3eb252389c93..5370705a4a72e11638a98b5f54d7aaa15800f9d5 100644 --- a/cmix/nodes/utils_test.go +++ b/cmix/nodes/utils_test.go @@ -234,7 +234,7 @@ func (m *MockClientComms) SendRequestClientKeyMessage(_ *connect.Host, // Extract RSA pubkey clientRsaPub := clientTransmissionConfirmation.RSAPubKey - // Assemble Client public key into rsa.PublicKey + // Assemble client public key into rsa.PublicKey userPublicKey, err := rsa.LoadPublicKeyFromPem([]byte(clientRsaPub)) if err != nil { m.t.Fatalf("Failed to load public key: %+v", err) diff --git a/connect/authenticated.go b/connect/authenticated.go index 518bbc2eb482f12c23005071e4e81f42c47caf38..0638c292c02f7f1fff154013a4bebba6f3e339bb 100644 --- a/connect/authenticated.go +++ b/connect/authenticated.go @@ -13,6 +13,7 @@ import ( "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" clientE2e "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" @@ -51,24 +52,23 @@ type AuthenticatedCallback func(connection AuthenticatedConnection) // ConnectWithAuthentication is called by the client, ie the one establishing // connection with the server. Once a connect.Connection has been established // with the server and then authenticate their identity to the server. -func ConnectWithAuthentication(recipient contact.Contact, myId *id.ID, - salt []byte, myRsaPrivKey *rsa.PrivateKey, myDhPrivKey *cyclic.Int, - rng *fastRNG.StreamGenerator, grp *cyclic.Group, net cmix.Client, +func ConnectWithAuthentication(recipient contact.Contact, e2eClient *xxdk.E2e, p Params) (AuthenticatedConnection, error) { // Track the time since we started to attempt to establish a connection timeStart := netTime.Now() // Establish a connection with the server - conn, err := Connect(recipient, myId, myDhPrivKey, rng, grp, net, p) + conn, err := Connect(recipient, e2eClient, p) if err != nil { return nil, errors.Errorf("failed to establish connection "+ "with recipient %s: %+v", recipient.ID, err) } // Build the authenticated connection and return - return connectWithAuthentication(conn, timeStart, recipient, salt, myRsaPrivKey, - rng, net, p) + identity := e2eClient.GetTransmissionIdentity() + return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, identity.RSAPrivatePem, + e2eClient.GetRng(), e2eClient.GetCmix(), p) } // connectWithAuthentication builds and sends an IdentityAuthentication to diff --git a/connect/connect.go b/connect/connect.go index 0de11c560d74c6e085fe5fc3276cedb69a81490c..6ebb2b7c4893d3cc0891cd43ad73c8e36b3f8498 100644 --- a/connect/connect.go +++ b/connect/connect.go @@ -8,6 +8,12 @@ package connect import ( "encoding/json" + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/ekv" "io" "time" @@ -15,7 +21,6 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/auth" "gitlab.com/elixxir/client/catalog" - "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/rounds" clientE2e "gitlab.com/elixxir/client/e2e" @@ -23,12 +28,8 @@ import ( "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/e2e/rekey" "gitlab.com/elixxir/client/event" - "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" - "gitlab.com/elixxir/crypto/fastRNG" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" ) @@ -118,41 +119,19 @@ func GetParameters(params string) (Params, error) { // and returns a Connection object for the newly-created partner.Manager // This function is to be used sender-side and will block until the // partner.Manager is confirmed. -func Connect(recipient contact.Contact, myId *id.ID, privKey *cyclic.Int, - rng *fastRNG.StreamGenerator, grp *cyclic.Group, net cmix.Client, +func Connect(recipient contact.Contact, e2eClient *xxdk.E2e, p Params) (Connection, error) { - //add the identity - net.AddIdentity(myId, time.Time{}, false) - - // Build an ephemeral KV - kv := versioned.NewKV(ekv.MakeMemstore()) - - // Build E2e handler - err := clientE2e.Init(kv, myId, privKey, grp, p.Rekey) - if err != nil { - return nil, err - } - e2eHandler, err := clientE2e.Load(kv, net, myId, grp, rng, p.Event) - if err != nil { - return nil, err - } // Build callback for E2E negotiation signalChannel := make(chan Connection, 1) cb := func(connection Connection) { signalChannel <- connection } - callback := getAuthCallback(cb, nil, e2eHandler, p) - - // Build auth object for E2E negotiation - authState, err := auth.NewState(kv, net, e2eHandler, - rng, p.Event, p.Auth, callback, nil) - if err != nil { - return nil, err - } + callback := getAuthCallback(cb, nil, e2eClient.GetE2E(), e2eClient.GetAuth(), p) + e2eClient.GetAuth().AddPartnerCallback(recipient.ID, callback) // Perform the auth request - _, err = authState.Request(recipient, nil) + _, err := e2eClient.GetAuth().Request(recipient, nil) if err != nil { return nil, err } @@ -199,7 +178,7 @@ func StartServer(cb Callback, myId *id.ID, privKey *cyclic.Int, } // Build callback for E2E negotiation - callback := getAuthCallback(nil, cb, e2eHandler, p) + callback := getAuthCallback(nil, cb, e2eHandler, nil, p) // Build auth object for E2E negotiation authState, err := auth.NewState(kv, net, e2eHandler, @@ -269,7 +248,7 @@ func (h *handler) Unregister(listenerID receive.ListenerID) { // building new Connection objects when an auth Request is received. type authCallback struct { // Used for signaling confirmation of E2E partnership - confrimCallback Callback + confirmCallback Callback requestCallback Callback // Used for building new Connection objects @@ -282,12 +261,13 @@ type authCallback struct { // of an auth.State object. // it will accept requests only if a request callback is passed in func getAuthCallback(confirm, request Callback, e2e clientE2e.Handler, - params Params) *authCallback { + auth auth.State, params Params) *authCallback { return &authCallback{ - confrimCallback: confirm, + confirmCallback: confirm, requestCallback: request, connectionE2e: e2e, connectionParams: params, + authState: auth, } } @@ -296,6 +276,7 @@ func (a authCallback) Confirm(requestor contact.Contact, receptionID receptionID.EphemeralIdentity, round rounds.Round) { jww.DEBUG.Printf("Connection auth request for %s confirmed", requestor.ID.String()) + defer a.authState.DeletePartnerCallback(requestor.ID) // After confirmation, get the new partner newPartner, err := a.connectionE2e.GetPartner(requestor.ID) @@ -303,26 +284,24 @@ func (a authCallback) Confirm(requestor contact.Contact, jww.ERROR.Printf("Unable to build connection with "+ "partner %s: %+v", requestor.ID, err) // Send a nil connection to avoid hold-ups down the line - if a.confrimCallback != nil { - a.confrimCallback(nil) + if a.confirmCallback != nil { + a.confirmCallback(nil) } - return } // Return the new Connection object - if a.confrimCallback != nil { - a.confrimCallback(BuildConnection(newPartner, a.connectionE2e, + if a.confirmCallback != nil { + a.confirmCallback(BuildConnection(newPartner, a.connectionE2e, a.authState, a.connectionParams)) } - } // Request will be called when an auth Request message is processed. func (a authCallback) Request(requestor contact.Contact, receptionID receptionID.EphemeralIdentity, round rounds.Round) { if a.requestCallback == nil { - jww.ERROR.Printf("Recieved a request when requests are" + + jww.ERROR.Printf("Received a request when requests are" + "not enable, will not accept") } _, err := a.authState.Confirm(requestor) @@ -371,7 +350,7 @@ func (h *handler) PartitionSize(payloadIndex uint) uint { return h.e2e.PartitionSize(payloadIndex) } -// PayloadSize Returns the max payload size for a partitionable E2E +// PayloadSize Returns the max payload size for a partition-able E2E // message func (h *handler) PayloadSize() uint { return h.e2e.PayloadSize() diff --git a/connect/utils_test.go b/connect/utils_test.go index 2d5bb68cfacf229904ce521590c175c035b0f538..45038764f61017d7caf2403cd629f8c3e821ca39 100644 --- a/connect/utils_test.go +++ b/connect/utils_test.go @@ -187,7 +187,7 @@ func (m mockConnection) Unregister(listenerID receive.ListenerID) { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmix struct { diff --git a/dummy/manager.go b/dummy/manager.go index b7c94096101b293e5ee5f7b9ca42a4e9f89b4276..28ddd25e69c7e40bd2ee8a31a4b84d16ac9a7f5a 100644 --- a/dummy/manager.go +++ b/dummy/manager.go @@ -12,10 +12,10 @@ package dummy import ( "github.com/pkg/errors" - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/fastRNG" "sync/atomic" "time" @@ -56,8 +56,8 @@ type Manager struct { // Pauses/Resumes the dummy send thread when triggered statusChan chan bool - // Client interfaces - client *api.Client + // Cmix interfaces + client *xxdk.Cmix store *storage.Session net interfaces.NetworkManager rng *fastRNG.StreamGenerator @@ -66,7 +66,7 @@ type Manager struct { // NewManager creates a new dummy Manager with the specified average send delta // and the range used for generating random durations. func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - client *api.Client, manager interfaces.NetworkManager) *Manager { + client *xxdk.Cmix, manager interfaces.NetworkManager) *Manager { clientStorage := client.GetStorage() return newManager(maxNumMessages, avgSendDelta, randomRange, client, &clientStorage, manager, client.GetRng()) @@ -75,7 +75,7 @@ func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, // newManager builds a new dummy Manager from fields explicitly passed in. This // function is a helper function for NewManager to make it easier to test. func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - client *api.Client, store *storage.Session, net interfaces.NetworkManager, + client *xxdk.Cmix, store *storage.Session, net interfaces.NetworkManager, rng *fastRNG.StreamGenerator) *Manager { return &Manager{ maxNumMessages: maxNumMessages, @@ -91,7 +91,7 @@ func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, } // StartDummyTraffic starts the process of sending dummy traffic. This function -// matches the api.Service type. +// matches the xxdk.Service type. func (m *Manager) StartDummyTraffic() (stoppable.Stoppable, error) { stop := stoppable.NewSingle(dummyTrafficStoppableName) go m.sendThread(stop) diff --git a/e2e/fpGenerator_test.go b/e2e/fpGenerator_test.go index ada64460a28221276304055f21056b3be92ae3dd..daf82b417700983987618f9c1a1df171ecd1436c 100644 --- a/e2e/fpGenerator_test.go +++ b/e2e/fpGenerator_test.go @@ -98,7 +98,7 @@ func (m mockSessionCypher) Decrypt(format.Message) ([]byte, error) { return ni func (m mockSessionCypher) Use() {} //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockFpgCmix struct { diff --git a/e2e/utils_test.go b/e2e/utils_test.go index 0f84f037f132416f8ad0eb75d7faa9414cbde869..36bccbe729f8d9f72b650f960d85a81e110575f2 100644 --- a/e2e/utils_test.go +++ b/e2e/utils_test.go @@ -121,7 +121,7 @@ func (m *mockServices) DeleteService( } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go index 246923be543a5404ac8b3249559ec370f6b75d73..03701de6adccc62944952c695a3126b7b26ef830 100644 --- a/fileTransfer/manager.go +++ b/fileTransfer/manager.go @@ -197,7 +197,7 @@ func NewManager(receiveCB ReceiveCallback, params Params, myID *id.ID, return m, nil } -// StartProcesses starts the sending threads. Adheres to the api.Service type. +// StartProcesses starts the sending threads. Adheres to the xxdk.Service type. func (m *manager) StartProcesses() (stoppable.Stoppable, error) { // Register listener to receive new file transfers m.e2e.RegisterListener( diff --git a/fileTransfer/send.go b/fileTransfer/send.go index ca66ae68118f6b11f6f433b5ee15658d9ce89432..f605f7ef03aa247384830b2cb57ed81ebe4d621d 100644 --- a/fileTransfer/send.go +++ b/fileTransfer/send.go @@ -85,7 +85,7 @@ func (m *manager) sendingThread(cMixParams cmix.CMIXParams, stop *stoppable.Sing } } -// sendCmix sends the parts in the packet via Client.SendMany. +// sendCmix sends the parts in the packet via Cmix.SendMany. func (m *manager) sendCmix(packet []store.Part, cMixParams cmix.CMIXParams) { // validParts will contain all parts in the original packet excluding those // that return an error from GetEncryptedPart diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go index d54a1257f57b6c4625eaa2c819202bc8e35d49ff..0fe87093612f4229ebe8f276c82be74f7a212caf 100644 --- a/fileTransfer/utils_test.go +++ b/fileTransfer/utils_test.go @@ -80,7 +80,7 @@ func RandStringBytes(n int, prng *rand.Rand) string { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/fileTransfer2/connect/utils_test.go b/fileTransfer2/connect/utils_test.go index 43eaaa09400b2e0d3feeafd96a46a8809011e6cb..bd155a4825642ec6cf629241b10e3a4e1e561523 100644 --- a/fileTransfer2/connect/utils_test.go +++ b/fileTransfer2/connect/utils_test.go @@ -32,7 +32,7 @@ import ( ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/fileTransfer2/e2e/utils_test.go b/fileTransfer2/e2e/utils_test.go index 30b9edd67c1daccf35854efe661f9a174b5f64f8..b5c57bcc2ed01ba1a8e9d07aa3401569bf23a579 100644 --- a/fileTransfer2/e2e/utils_test.go +++ b/fileTransfer2/e2e/utils_test.go @@ -32,7 +32,7 @@ import ( ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/fileTransfer2/groupChat/utils_test.go b/fileTransfer2/groupChat/utils_test.go index 0c0b21bffae44be1b49a0c18892e33cc6c18ed8d..087f095dd60b07648840e3c7d38424837be1a8ba 100644 --- a/fileTransfer2/groupChat/utils_test.go +++ b/fileTransfer2/groupChat/utils_test.go @@ -29,7 +29,7 @@ import ( ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/fileTransfer2/interface.go b/fileTransfer2/interface.go index b8e2f8ba08f66692b6bb45ae3f9afafcd5bca88f..b0fe8d5ac7137e08c72466865a68d1073f792c06 100644 --- a/fileTransfer2/interface.go +++ b/fileTransfer2/interface.go @@ -42,7 +42,7 @@ type SendNew func(transferInfo []byte) error type FileTransfer interface { // StartProcesses starts the sending threads that wait for file transfers to - // send. Adheres to the api.Service type. + // send. Adheres to the xxdk.Service type. StartProcesses() (stoppable.Stoppable, error) // MaxFileNameLen returns the max number of bytes allowed for a file name. diff --git a/fileTransfer2/manager.go b/fileTransfer2/manager.go index f2dfd75e4d0fae4a3ea36557d58fbbe9de12eb61..76cd42ffbce8eec07a2b274b1bfa54a4d2703ba8 100644 --- a/fileTransfer2/manager.go +++ b/fileTransfer2/manager.go @@ -199,7 +199,7 @@ func NewManager(params Params, myID *id.ID, cmix Cmix, storage Storage, return m, nil } -// StartProcesses starts the sending threads. Adheres to the api.Service type. +// StartProcesses starts the sending threads. Adheres to the xxdk.Service type. func (m *manager) StartProcesses() (stoppable.Stoppable, error) { // Construct stoppables multiStop := stoppable.NewMulti(workerPoolStoppable) diff --git a/fileTransfer2/send.go b/fileTransfer2/send.go index 5c0d2074a66e56a6f64a63f5db4704ee2c5ea9d0..1d06dcc80ea2815f1434fbeef61f37dfa64f2938 100644 --- a/fileTransfer2/send.go +++ b/fileTransfer2/send.go @@ -89,7 +89,7 @@ func (m *manager) sendingThread(stop *stoppable.Single) { } } -// sendCmix sends the parts in the packet via Client.SendMany. +// sendCmix sends the parts in the packet via Cmix.SendMany. func (m *manager) sendCmix(packet []store.Part) { // validParts will contain all parts in the original packet excluding those // that return an error from GetEncryptedPart diff --git a/fileTransfer2/utils_test.go b/fileTransfer2/utils_test.go index ef5722da07aa7e107c5272c5f998340129dafa20..7f2de0eb05a1bf0086cd2050c7794e02386033c7 100644 --- a/fileTransfer2/utils_test.go +++ b/fileTransfer2/utils_test.go @@ -81,7 +81,7 @@ func RandStringBytes(n int, prng *rand.Rand) string { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { diff --git a/groupChat/interface.go b/groupChat/interface.go index e9c71c51b0727167f97a63f05b8ab2a9f3d35d2a..9604b5d8b39726460f374d3531715be7697510f7 100644 --- a/groupChat/interface.go +++ b/groupChat/interface.go @@ -50,7 +50,7 @@ type GroupChat interface { // LeaveGroup removes a group from a list of groups the user is a part of. LeaveGroup(groupID *id.ID) error - // Send sends a message to all GroupChat members using Client.SendManyCMIX. + // Send sends a message to all GroupChat members using Cmix.SendManyCMIX. // The send fails if the message is too long. Returns the ID of the round // sent on and the timestamp of the message send. Send(groupID *id.ID, tag string, message []byte) ( diff --git a/groupChat/send.go b/groupChat/send.go index 9bed53b763ba45278ca9bd3abc37877fb155acd1..71624079ad5d42f1adce834249f8bdc9965edd4b 100644 --- a/groupChat/send.go +++ b/groupChat/send.go @@ -43,7 +43,7 @@ const ( saltReadLengthErr = "length of generated salt %d != %d required" ) -// Send sends a message to all group members using Client.SendMany. +// Send sends a message to all group members using Cmix.SendMany. // The send fails if the message is too long. func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( id.Round, time.Time, group.MessageID, error) { diff --git a/registration/permissioning.go b/registration/permissioning.go index 917692eefc0e53c21220665c78494a0d0c7eb3b2..cab953a8472df368a6bc7dd72218a5e49796c2c8 100644 --- a/registration/permissioning.go +++ b/registration/permissioning.go @@ -33,7 +33,7 @@ func Init(comms *client.Comms, def *ndf.NetworkDefinition) (*Registration, error //add the registration host to comms hParam := connect.GetDefaultHostParams() hParam.AuthEnabled = false - // Client will not send KeepAlive packets + // Do not send KeepAlive packets hParam.KaClientOpts.Time = time.Duration(math.MaxInt64) hParam.MaxRetries = 3 perm.host, err = comms.AddHost(&id.ClientRegistration, def.Registration.ClientRegistrationAddress, diff --git a/single/listener_test.go b/single/listener_test.go index f6f6bed68b4c5f1fe9f1a3e5849e73df2579e0ee..b7125f217866dbbefdd9e57757944a828da6f2ab 100644 --- a/single/listener_test.go +++ b/single/listener_test.go @@ -222,7 +222,7 @@ func Test_listener_Stop(t *testing.T) { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockListenCmixHandler struct { diff --git a/single/receivedRequest_test.go b/single/receivedRequest_test.go index d5d8b15fb500270160f657ad82db712094a61e88..fc7f64f4fc398a5ad3407690d40a269410e1d8c0 100644 --- a/single/receivedRequest_test.go +++ b/single/receivedRequest_test.go @@ -154,7 +154,7 @@ func Test_splitPayload(t *testing.T) { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockRequestCmix struct { diff --git a/single/utils_test.go b/single/utils_test.go index 473bb2dfa4025c02cee6bbca4d25e7e7506da3ef..66e7f0e6d670bfc0e19e8ef237d4e2277abb43ec 100644 --- a/single/utils_test.go +++ b/single/utils_test.go @@ -23,7 +23,7 @@ import ( ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix Client // +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// // Tests that mockCmix adheres to the Cmix interface. diff --git a/storage/user/info.go b/storage/user/info.go index 11d9381ef07cbad22a91dc49db8cff48d551fed8..62603c2225f0921f54684299f140fb33bfb6d182 100644 --- a/storage/user/info.go +++ b/storage/user/info.go @@ -105,7 +105,7 @@ func (u *User) PortableUserInfo() Info { ReceptionRSA: ci.GetReceptionRSA(), Precanned: ci.IsPrecanned(), //fixme: set these in the e2e layer, the command line layer - //needs more logical seperation so this can be removed + //needs more logical separation so this can be removed E2eDhPrivateKey: nil, E2eDhPublicKey: nil, } diff --git a/ud/interfaces.go b/ud/interfaces.go index ba5bff8b7eb20cd55da1a1f9c7cf91d3478d8df1..db7f0b60333ddbc559520aa5ee9a12eb51594eea 100644 --- a/ud/interfaces.go +++ b/ud/interfaces.go @@ -1,9 +1,9 @@ package ud import ( - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/storage/user" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" ) @@ -37,6 +37,6 @@ type UserInfo interface { GetReceptionRegistrationValidationSignature() []byte } -// NetworkStatus is an interface for the api.Client's +// NetworkStatus is an interface for the xxdk.Cmix's // NetworkFollowerStatus method. -type NetworkStatus func() api.Status +type NetworkStatus func() xxdk.Status diff --git a/ud/manager.go b/ud/manager.go index 3cd1b679a3586248c14f8608eb31cddb2e1f43e7..1ce22eac8d6c24812c381fdc60753e07ba5e5e66 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -7,10 +7,10 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/storage/versioned" store "gitlab.com/elixxir/client/ud/store" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/comms/connect" @@ -77,7 +77,7 @@ func NewManager(services CMix, e2e E2E, kv *versioned.KV) (*Manager, error) { jww.INFO.Println("ud.NewManager()") - if follower() != api.Running { + if follower() != xxdk.Running { return nil, errors.New( "cannot start UD Manager when network follower is not running.") } @@ -134,7 +134,7 @@ func NewManagerFromBackup(services CMix, events event.Reporter, comms Comms, userStore UserInfo, email, phone fact.Fact, kv *versioned.KV) (*Manager, error) { jww.INFO.Println("ud.NewManagerFromBackup()") - if follower() != api.Running { + if follower() != xxdk.Running { return nil, errors.New( "cannot start UD Manager when " + "network follower is not running.") diff --git a/api/messenger/backup.go b/xxdk/backup.go similarity index 80% rename from api/messenger/backup.go rename to xxdk/backup.go index a5e73eaaf743030acacea195229e13e409f091e8..6b02e9ad5635a3984c485487a6c714eacc003f62 100644 --- a/api/messenger/backup.go +++ b/xxdk/backup.go @@ -1,11 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / //////////////////////////////////////////////////////////////////////////////// -package messenger +package xxdk import "sync" diff --git a/api/client.go b/xxdk/cmix.go similarity index 89% rename from api/client.go rename to xxdk/cmix.go index 002542157ea6a8e49924aa0d44e4419566d1d450..6b5444bef2b5d2fad83e5bbe7cdad4b835dbb3d0 100644 --- a/api/client.go +++ b/xxdk/cmix.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "encoding/json" @@ -16,7 +16,6 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/auth" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/interfaces" @@ -39,7 +38,7 @@ import ( const followerStoppableName = "client" -type Client struct { +type Cmix struct { //generic RNG for client rng *fastRNG.StreamGenerator // the storage session securely stores data to disk and memoizes as is @@ -120,10 +119,10 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, return nil } -// OpenClient session, but don't connect to the network or log in -func OpenClient(storageDir string, password []byte, - parameters Params) (*Client, error) { - jww.INFO.Printf("OpenClient()") +// OpenCmix session, but don't connect to the network or log in +func OpenCmix(storageDir string, password []byte, + parameters Params) (*Cmix, error) { + jww.INFO.Printf("OpenCmix()") rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) @@ -141,7 +140,7 @@ func OpenClient(storageDir string, password []byte, return nil, err } - c := &Client{ + c := &Cmix{ storage: storageSess, rng: rngStreamGen, comms: nil, @@ -210,16 +209,16 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password, return nil } -// Login initializes a client object from existing storage. -func Login(storageDir string, password []byte, parameters Params) (*Client, error) { +// LoadCmix initializes a Cmix object from existing storage +func LoadCmix(storageDir string, password []byte, parameters Params) (*Cmix, error) { jww.INFO.Printf("Login()") - c, err := OpenClient(storageDir, password, parameters) + c, err := OpenCmix(storageDir, password, parameters) if err != nil { return nil, err } - jww.INFO.Printf("Client Logged in: \n\tTransmissionID: %s "+ + jww.INFO.Printf("Cmix Logged in: \n\tTransmissionID: %s "+ "\n\tReceptionID: %s", c.storage.GetTransmissionID(), c.storage.GetReceptionID()) def := c.storage.GetNDF() @@ -232,13 +231,13 @@ func Login(storageDir string, password []byte, parameters Params) (*Client, erro } } else { jww.WARN.Printf("Registration with permissioning skipped due " + - "to blank permissioning address. Client will not be " + + "to blank permissioning address. Cmix will not be " + "able to register or track network.") } if def.Notification.Address != "" { hp := connect.GetDefaultHostParams() - // Client will not send KeepAlive packets + // Do not send KeepAlive packets hp.KaClientOpts.Time = time.Duration(math.MaxInt64) hp.AuthEnabled = false hp.MaxRetries = 5 @@ -268,8 +267,7 @@ func Login(storageDir string, password []byte, parameters Params) (*Client, erro // while replacing the base NDF. This is designed for some specific deployment // procedures and is generally unsafe. func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, - newBaseNdf string, authCallbacks auth.Callbacks, - params Params) (*Client, error) { + newBaseNdf string, params Params) (*Cmix, error) { jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()") def, err := ParseNDF(newBaseNdf) @@ -277,7 +275,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, return nil, err } - c, err := OpenClient(storageDir, password, params) + c, err := OpenCmix(storageDir, password, params) if err != nil { return nil, err } @@ -292,7 +290,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, } } else { jww.WARN.Printf("Registration with permissioning skipped due " + - "to blank permissionign address. Client will not be " + + "to blank permissionign address. Cmix will not be " + "able to register or track network.") } @@ -314,7 +312,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, // some specific deployment procedures and is generally unsafe. func LoginWithProtoClient(storageDir string, password []byte, protoClientJSON []byte, newBaseNdf string, - params Params) (*Client, error) { + params Params) (*Cmix, error) { jww.INFO.Printf("LoginWithProtoClient()") def, err := ParseNDF(newBaseNdf) @@ -328,7 +326,7 @@ func LoginWithProtoClient(storageDir string, password []byte, return nil, err } - c, err := OpenClient(storageDir, password, params) + c, err := OpenCmix(storageDir, password, params) if err != nil { return nil, err } @@ -359,7 +357,7 @@ func LoginWithProtoClient(storageDir string, password []byte, return c, nil } -func (c *Client) initComms() error { +func (c *Cmix) initComms() error { var err error //get the user from session @@ -376,7 +374,7 @@ func (c *Client) initComms() error { return nil } -func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error { +func (c *Cmix) initPermissioning(def *ndf.NetworkDefinition) error { var err error //initialize registration c.permissioning, err = registration.Init(c.comms, def) @@ -387,15 +385,15 @@ func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error { //register with registration if necessary if c.storage.GetRegistrationStatus() == storage.KeyGenComplete { - jww.INFO.Printf("Client has not registered yet, " + + jww.INFO.Printf("Cmix has not registered yet, " + "attempting registration") err = c.registerWithPermissioning() if err != nil { - jww.ERROR.Printf("Client has failed registration: %s", + jww.ERROR.Printf("Cmix has failed registration: %s", err) return errors.WithMessage(err, "failed to load client") } - jww.INFO.Printf("Client successfully registered " + + jww.INFO.Printf("Cmix successfully registered " + "with the network") } return nil @@ -404,7 +402,7 @@ func (c *Client) initPermissioning(def *ndf.NetworkDefinition) error { // registerFollower adds the follower processes to the client's // follower service list. // This should only ever be called once -func (c *Client) registerFollower() error { +func (c *Cmix) registerFollower() error { //build the error callback cer := func(source, message, trace string) { select { @@ -436,12 +434,12 @@ func (c *Client) registerFollower() error { return nil } -// ----- Client Functions ----- +// ----- Cmix Functions ----- // GetErrorsChannel returns a channel which passes errors from the // long-running threads controlled by StartNetworkFollower and // StopNetworkFollower -func (c *Client) GetErrorsChannel() <-chan interfaces.ClientError { +func (c *Cmix) GetErrorsChannel() <-chan interfaces.ClientError { return c.clientErrorChannel } @@ -479,7 +477,7 @@ func (c *Client) GetErrorsChannel() <-chan interfaces.ClientError { // Responds to confirmations of successful rekey operations // - Auth Callback (/auth/callback.go) // Handles both auth confirm and requests -func (c *Client) StartNetworkFollower(timeout time.Duration) error { +func (c *Cmix) StartNetworkFollower(timeout time.Duration) error { jww.INFO.Printf("StartNetworkFollower() \n\tTransmissionID: %s "+ "\n\tReceptionID: %s", c.storage.GetTransmissionID(), c.storage.GetReceptionID()) @@ -491,7 +489,7 @@ func (c *Client) StartNetworkFollower(timeout time.Duration) error { // fails to stop it. // if the network follower is running and this fails, the client object will // most likely be in an unrecoverable state and need to be trashed. -func (c *Client) StopNetworkFollower() error { +func (c *Cmix) StopNetworkFollower() error { jww.INFO.Printf("StopNetworkFollower()") return c.followerServices.stop() } @@ -501,62 +499,62 @@ func (c *Client) StopNetworkFollower() error { // Starting - 1000 // Running - 2000 // Stopping - 3000 -func (c *Client) NetworkFollowerStatus() Status { +func (c *Cmix) NetworkFollowerStatus() Status { jww.INFO.Printf("NetworkFollowerStatus()") return c.followerServices.status() } // HasRunningProcessies checks if any background threads are running // and returns true if one or more are -func (c *Client) HasRunningProcessies() bool { +func (c *Cmix) HasRunningProcessies() bool { return !c.followerServices.stoppable.IsStopped() } // RegisterRoundEventsCb registers a callback for round // events. -func (c *Client) GetRoundEvents() interfaces.RoundEvents { +func (c *Cmix) GetRoundEvents() interfaces.RoundEvents { jww.INFO.Printf("GetRoundEvents()") - jww.WARN.Printf("GetRoundEvents does not handle Client Errors " + + jww.WARN.Printf("GetRoundEvents does not handle Cmix Errors " + "edge case!") return c.network.GetInstance().GetRoundEvents() } // AddService adds a service ot be controlled by the client thread control, // these will be started and stopped with the network follower -func (c *Client) AddService(sp Service) error { +func (c *Cmix) AddService(sp Service) error { return c.followerServices.add(sp) } // GetUser returns the current user Identity for this client. This // can be serialized into a byte stream for out-of-band sharing. -func (c *Client) GetUser() user.Info { +func (c *Cmix) GetUser() user.Info { jww.INFO.Printf("GetUser()") cMixUser := c.storage.PortableUserInfo() return cMixUser } // GetComms returns the client comms object -func (c *Client) GetComms() *client.Comms { +func (c *Cmix) GetComms() *client.Comms { return c.comms } // GetRng returns the client rng object -func (c *Client) GetRng() *fastRNG.StreamGenerator { +func (c *Cmix) GetRng() *fastRNG.StreamGenerator { return c.rng } // GetStorage returns the client storage object -func (c *Client) GetStorage() storage.Session { +func (c *Cmix) GetStorage() storage.Session { return c.storage } // GetCmix returns the client Network Interface -func (c *Client) GetCmix() cmix.Client { +func (c *Cmix) GetCmix() cmix.Client { return c.network } // GetEventReporter returns the event reporter -func (c *Client) GetEventReporter() event.Reporter { +func (c *Cmix) GetEventReporter() event.Reporter { return c.events } @@ -564,7 +562,7 @@ func (c *Client) GetEventReporter() event.Reporter { // returns the total number of nodes in the NDF and the number of those which // are currently registers with. An error is returned if the network is not // healthy. -func (c *Client) GetNodeRegistrationStatus() (int, int, error) { +func (c *Cmix) GetNodeRegistrationStatus() (int, int, error) { // Return an error if the network is not healthy if !c.GetCmix().IsHealthy() { return 0, 0, errors.New("Cannot get number of nodes " + @@ -596,7 +594,7 @@ func (c *Client) GetNodeRegistrationStatus() (int, int, error) { // GetPreferredBins returns the geographic bin or bins that the provided two // character country code is a part of. -func (c *Client) GetPreferredBins(countryCode string) ([]string, error) { +func (c *Cmix) GetPreferredBins(countryCode string) ([]string, error) { // get the bin that the country is in bin, exists := region.GetCountryBin(countryCode) if !exists { diff --git a/api/messenger/compress_test.go b/xxdk/compress_test.go similarity index 99% rename from api/messenger/compress_test.go rename to xxdk/compress_test.go index 19a4bcc414c112b9168b5da43b80f8e3d78721bf..75d020eebdd4efb15be25326c248e4f6b17834da 100644 --- a/api/messenger/compress_test.go +++ b/xxdk/compress_test.go @@ -1,11 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// -package messenger +package xxdk import ( "bytes" diff --git a/api/messenger/messenger.go b/xxdk/e2e.go similarity index 53% rename from api/messenger/messenger.go rename to xxdk/e2e.go index 2677e6fbaf23270e7eb6fc6009266da1638eaade..c3536ec8eb316f61bfc49643ab903ee393b1a99b 100644 --- a/api/messenger/messenger.go +++ b/xxdk/e2e.go @@ -1,12 +1,21 @@ -package messenger +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package xxdk import ( "encoding/binary" "encoding/json" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/xx" + "time" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/auth" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/rekey" @@ -16,16 +25,37 @@ import ( "gitlab.com/xx_network/primitives/id" ) -type Client struct { - *api.Client - auth auth.State - e2e e2e.Handler - backup *Container +// E2e object bundles a TransmissionIdentity with a Cmix +// and can be used for high level operations such as connections +type E2e struct { + *Cmix + auth auth.State + e2e e2e.Handler + backup *Container + e2eIdentity TransmissionIdentity +} + +// Login creates a new E2e backed by the xxdk.Cmix persistent versioned.KV +// If identity == nil, a new TransmissionIdentity will be generated automagically +func Login(client *Cmix, callbacks auth.Callbacks, + identity TransmissionIdentity) (m *E2e, err error) { + return login(client, callbacks, identity, client.GetStorage().GetKV()) +} + +// LoginEphemeral creates a new E2e backed by a totally ephemeral versioned.KV +// If identity == nil, a new TransmissionIdentity will be generated automagically +func LoginEphemeral(client *Cmix, callbacks auth.Callbacks, + identity TransmissionIdentity) (m *E2e, err error) { + return login(client, callbacks, identity, versioned.NewKV(ekv.MakeMemstore())) } -func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error) { - m = &Client{ - Client: client, +// LoginLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV +// Uses the pre-generated transmission ID used by xxdk.Cmix +// This function is designed to maintain backwards compatibility with previous xx messenger designs +// and should not be used for other purposes +func LoginLegacy(client *Cmix, callbacks auth.Callbacks) (m *E2e, err error) { + m = &E2e{ + Cmix: client, backup: &Container{}, } @@ -41,18 +71,73 @@ func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error) return nil, err } + u := m.Cmix.GetUser() + m.e2eIdentity = TransmissionIdentity{ + ID: u.TransmissionID, + RSAPrivatePem: u.TransmissionRSA, + Salt: u.TransmissionSalt, + DHKeyPrivate: u.E2eDhPrivateKey, + } + + return m, err +} + +// login creates a new e2eApi.E2e backed by the given versioned.KV +func login(client *Cmix, callbacks auth.Callbacks, + identity TransmissionIdentity, kv *versioned.KV) (m *E2e, err error) { + + // Verify the passed-in TransmissionIdentity matches its properties + generatedId, err := xx.NewID(identity.RSAPrivatePem.GetPublic(), identity.Salt, id.User) + if err != nil { + return nil, err + } + if !generatedId.Cmp(identity.ID) { + return nil, errors.Errorf("Given identity %s is invalid, generated ID does not match", + identity.ID.String()) + } + + e2eGrp := client.GetStorage().GetE2EGroup() + m = &E2e{ + Cmix: client, + backup: &Container{}, + e2eIdentity: identity, + } + + //initialize the e2e storage + err = e2e.Init(kv, identity.ID, identity.DHKeyPrivate, e2eGrp, + rekey.GetDefaultEphemeralParams()) + if err != nil { + return nil, err + } + + //load the new e2e storage + m.e2e, err = e2e.Load(kv, + client.GetCmix(), identity.ID, e2eGrp, client.GetRng(), + client.GetEventReporter()) + if err != nil { + return nil, errors.WithMessage(err, "Failed to load a "+ + "newly created e2e store") + } + + m.auth, err = auth.NewState(kv, client.GetCmix(), + m.e2e, client.GetRng(), client.GetEventReporter(), + auth.GetDefaultTemporaryParams(), callbacks, m.backup.TriggerBackup) + if err != nil { + return nil, err + } + return m, err } // LoadOrInitE2e loads the e2e handler or makes a new one, generating a new // e2e private key. It attempts to load via a legacy construction, then tries // to load the modern one, creating a new modern ID if neither can be found -func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) { +func LoadOrInitE2e(client *Cmix) (e2e.Handler, error) { usr := client.GetUser() e2eGrp := client.GetStorage().GetE2EGroup() kv := client.GetStorage().GetKV() - //try to load a legacy e2e hander + //try to load a legacy e2e handler e2eHandler, err := e2e.LoadLegacy(kv, client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(), client.GetEventReporter(), rekey.GetDefaultParams()) @@ -61,7 +146,7 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) { e2eHandler, err = e2e.Load(kv, client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(), client.GetEventReporter()) - //if no new e2e handler exists, initilize an e2e user + //if no new e2e handler exists, initialize an e2e user if err != nil { jww.WARN.Printf("Failed to load e2e instance for %s, "+ "creating a new one", usr.ReceptionID) @@ -102,6 +187,8 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) { return nil, errors.WithMessage(err, "Failed to load a "+ "newly created e2e store") } + + client.GetCmix().AddIdentity(usr.ReceptionID, time.Time{}, true) } else { jww.INFO.Printf("Loaded a modern e2e instance for %s", usr.ReceptionID) @@ -113,18 +200,23 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) { return e2eHandler, nil } -// GetUser replaces api.Client's GetUser with one which includes the e2e dh +// GetUser replaces xxdk.Cmix's GetUser with one which includes the e2e dh // private keys -func (m *Client) GetUser() user.Info { - u := m.Client.GetUser() +func (m *E2e) GetUser() user.Info { + u := m.Cmix.GetUser() u.E2eDhPrivateKey = m.e2e.GetHistoricalDHPrivkey() u.E2eDhPublicKey = m.e2e.GetHistoricalDHPubkey() return u } +// GetTransmissionIdentity returns a safe copy of the E2e TransmissionIdentity +func (m *E2e) GetTransmissionIdentity() TransmissionIdentity { + return m.e2eIdentity.DeepCopy() +} + // ConstructProtoUserFile is a helper function which is used for proto // client testing. This is used for development testing. -func (m *Client) ConstructProtoUserFile() ([]byte, error) { +func (m *E2e) ConstructProtoUserFile() ([]byte, error) { //load the registration code regCode, err := m.GetStorage().GetRegCode() @@ -158,20 +250,20 @@ func (m *Client) ConstructProtoUserFile() ([]byte, error) { return jsonBytes, nil } -func (m *Client) GetAuth() auth.State { +func (m *E2e) GetAuth() auth.State { return m.auth } -func (m *Client) GetE2E() e2e.Handler { +func (m *E2e) GetE2E() e2e.Handler { return m.e2e } -func (m *Client) GetBackupContainer() *Container { +func (m *E2e) GetBackupContainer() *Container { return m.backup } -// DeleteContact is a function which removes a partner from Client's storage -func (m *Client) DeleteContact(partnerId *id.ID) error { +// DeleteContact is a function which removes a partner from E2e's storage +func (m *E2e) DeleteContact(partnerId *id.ID) error { jww.DEBUG.Printf("Deleting contact with ID %s", partnerId) _, err := m.e2e.GetPartner(partnerId) @@ -190,7 +282,7 @@ func (m *Client) DeleteContact(partnerId *id.ID) error { // c.e2e.Conversations().Delete(partnerId) // call delete requests to make sure nothing is lingering. - // this is for saftey to ensure the contact can be readded + // this is for safety to ensure the contact can be re-added // in the future _ = m.auth.DeleteRequest(partnerId) diff --git a/api/event.go b/xxdk/event.go similarity index 76% rename from api/event.go rename to xxdk/event.go index 52fa3c1708dce3a5cd074d1a4030859219be7760..cd1897454b70731c4371de68804d5de154aff40d 100644 --- a/api/event.go +++ b/xxdk/event.go @@ -1,4 +1,4 @@ -package api +package xxdk import ( "gitlab.com/elixxir/client/event" @@ -6,20 +6,20 @@ import ( // ReportEvent reports an event from the client to api users, providing a // priority, category, eventType, and details -func (c *Client) ReportEvent(priority int, category, evtType, details string) { +func (c *Cmix) ReportEvent(priority int, category, evtType, details string) { c.events.Report(priority, category, evtType, details) } // RegisterEventCallback records the given function to receive // ReportableEvent objects. It returns the internal index // of the callback so that it can be deleted later. -func (c *Client) RegisterEventCallback(name string, +func (c *Cmix) RegisterEventCallback(name string, myFunc event.Callback) error { return c.events.RegisterEventCallback(name, myFunc) } // UnregisterEventCallback deletes the callback identified by the // index. It returns an error if it fails. -func (c *Client) UnregisterEventCallback(name string) { +func (c *Cmix) UnregisterEventCallback(name string) { c.events.UnregisterEventCallback(name) } diff --git a/xxdk/identity.go b/xxdk/identity.go new file mode 100644 index 0000000000000000000000000000000000000000..daef4c673bbf1668ae1a11dc294adfeaaa945e1c --- /dev/null +++ b/xxdk/identity.go @@ -0,0 +1,71 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package xxdk + +import ( + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/crypto/xx" + "gitlab.com/xx_network/primitives/id" +) + +type TransmissionIdentity struct { + ID *id.ID + RSAPrivatePem *rsa.PrivateKey + Salt []byte + DHKeyPrivate *cyclic.Int +} + +// MakeTransmissionIdentity generates a new cryptographic identity for receiving messages +func MakeTransmissionIdentity(rng csprng.Source, grp *cyclic.Group) (TransmissionIdentity, error) { + //make RSA Key + rsaKey, err := rsa.GenerateKey(rng, + rsa.DefaultRSABitLen) + if err != nil { + return TransmissionIdentity{}, err + } + + //make salt + salt := make([]byte, 32) + _, err = rng.Read(salt) + + //make dh private key + privKey := diffieHellman.GeneratePrivateKey( + len(grp.GetPBytes()), + grp, rng) + + //make the ID + newId, err := xx.NewID(rsaKey.GetPublic(), + salt, id.User) + if err != nil { + return TransmissionIdentity{}, err + } + + //create the identity object + I := TransmissionIdentity{ + ID: newId, + RSAPrivatePem: rsaKey, + Salt: salt, + DHKeyPrivate: privKey, + } + + return I, nil +} + +// DeepCopy produces a safe copy of a TransmissionIdentity +func (t TransmissionIdentity) DeepCopy() TransmissionIdentity { + saltCopy := make([]byte, len(t.Salt)) + copy(saltCopy, t.Salt) + return TransmissionIdentity{ + ID: t.ID.DeepCopy(), + RSAPrivatePem: t.RSAPrivatePem, + Salt: saltCopy, + DHKeyPrivate: t.DHKeyPrivate.DeepCopy(), + } +} diff --git a/api/mnemonic.go b/xxdk/mnemonic.go similarity index 99% rename from api/mnemonic.go rename to xxdk/mnemonic.go index 9b262da82c81bebcc01fd185adbc5d60a196cb6b..3a2e2051b9485d225704c2896caa6da6319b5dc0 100644 --- a/api/mnemonic.go +++ b/xxdk/mnemonic.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "github.com/pkg/errors" diff --git a/api/mnemonic_test.go b/xxdk/mnemonic_test.go similarity index 99% rename from api/mnemonic_test.go rename to xxdk/mnemonic_test.go index a56a73b1f524018f686af392478f89b7dc2d1dc9..326e16dc22f36ee6b6d9e91ba189fba19cb5e5cd 100644 --- a/api/mnemonic_test.go +++ b/xxdk/mnemonic_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "bytes" diff --git a/api/ndf.go b/xxdk/ndf.go similarity index 99% rename from api/ndf.go rename to xxdk/ndf.go index efe7e86ae0c6b0f38c3be734c7623e99a6e92823..d67edc0d93ec8a0e1928e5cf07fb851d4f4942f7 100644 --- a/api/ndf.go +++ b/xxdk/ndf.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "encoding/base64" diff --git a/api/messenger/notifications.go b/xxdk/notifications.go similarity index 88% rename from api/messenger/notifications.go rename to xxdk/notifications.go index 380029ebfaf68cdbe9b7310a731f6614b641d136..32fe156d9318985d964b95717126b701ece0865d 100644 --- a/api/messenger/notifications.go +++ b/xxdk/notifications.go @@ -1,11 +1,10 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// -package messenger +package xxdk import ( "github.com/pkg/errors" @@ -23,7 +22,7 @@ import ( // especially as these rely on third parties (i.e., Firebase *cough* // *cough* google's palantir *cough*) that may represent a security // risk to the user. -func (m *Client) RegisterForNotifications(token string) error { +func (m *E2e) RegisterForNotifications(token string) error { jww.INFO.Printf("RegisterForNotifications(%s)", token) // Pull the host from the manage notificationBotHost, ok := m.GetComms().GetHost(&id.NotificationBot) @@ -61,7 +60,7 @@ func (m *Client) RegisterForNotifications(token string) error { } // UnregisterForNotifications turns of notifications for this client -func (m *Client) UnregisterForNotifications() error { +func (m *E2e) UnregisterForNotifications() error { jww.INFO.Printf("UnregisterForNotifications()") // Pull the host from the manage notificationBotHost, ok := m.GetComms().GetHost(&id.NotificationBot) @@ -86,7 +85,7 @@ func (m *Client) UnregisterForNotifications() error { return nil } -func (m *Client) getIidAndSig() ([]byte, []byte, error) { +func (m *E2e) getIidAndSig() ([]byte, []byte, error) { intermediaryReceptionID, err := ephemeral.GetIntermediaryId(m.GetStorage().GetReceptionID()) if err != nil { return nil, nil, errors.WithMessage(err, "RegisterForNotifications: Failed to form intermediary ID") diff --git a/api/params.go b/xxdk/params.go similarity index 98% rename from api/params.go rename to xxdk/params.go index 39f9d8db3768ac00c454bf89d2ba8b5326c9fb4e..c5768a2a0512560367f9e0cb5ad3d7f9221ab3c9 100644 --- a/api/params.go +++ b/xxdk/params.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "encoding/json" diff --git a/api/params_test.go b/xxdk/params_test.go similarity index 99% rename from api/params_test.go rename to xxdk/params_test.go index 35bf61d8f10e5b494a8459f64d239d1569df36b4..13868e1fb03e192a9a94cc916960d4121a871b08 100644 --- a/api/params_test.go +++ b/xxdk/params_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "bytes" diff --git a/api/permissioning.go b/xxdk/permissioning.go similarity index 96% rename from api/permissioning.go rename to xxdk/permissioning.go index ee25a57e0ccf6adcf5820d432f49519a1493c4a5..2e1d735e1236c410bfb473e7d02bad87b6f73536 100644 --- a/api/permissioning.go +++ b/xxdk/permissioning.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "encoding/json" @@ -15,7 +15,7 @@ import ( ) // Returns an error if registration fails. -func (c *Client) registerWithPermissioning() error { +func (c *Cmix) registerWithPermissioning() error { //get the users public key transmissionPubKey := c.storage.GetTransmissionRSA().GetPublic() receptionPubKey := c.storage.GetReceptionRSA().GetPublic() @@ -54,7 +54,7 @@ func (c *Client) registerWithPermissioning() error { // ConstructProtoUserFile is a helper function which is used for proto // client testing. This is used for development testing. -func (c *Client) ConstructProtoUserFile() ([]byte, error) { +func (c *Cmix) ConstructProtoUserFile() ([]byte, error) { //load the registration code regCode, err := c.storage.GetRegCode() diff --git a/xxdk/precan.go b/xxdk/precan.go new file mode 100644 index 0000000000000000000000000000000000000000..b710954cc27f6901d5f4b0226a3b5aa920bb8f4a --- /dev/null +++ b/xxdk/precan.go @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package xxdk + +import ( + "encoding/binary" + "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/e2e/ratchet/partner/session" + util "gitlab.com/elixxir/client/storage/utility" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/elixxir/primitives/fact" + "math/rand" + + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/storage/user" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" +) + +// CreatePrecannedUser creates a precanned user +func CreatePrecannedUser(precannedID uint, rng csprng.Source) user.Info { + + // Salt, UID, etc gen + salt := make([]byte, SaltSize) + + userID := id.ID{} + binary.BigEndian.PutUint64(userID[:], uint64(precannedID)) + userID.SetType(id.User) + + // NOTE: not used... RSA Keygen (4096 bit defaults) + rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + return user.Info{ + TransmissionID: &userID, + TransmissionSalt: salt, + ReceptionID: &userID, + ReceptionSalt: salt, + Precanned: true, + E2eDhPrivateKey: nil, + E2eDhPublicKey: nil, + TransmissionRSA: rsaKey, + ReceptionRSA: rsaKey, + } +} + +// NewPrecannedClient creates an insecure user with predetermined keys +// with nodes It creates client storage, generates keys, connects, and +// registers with the network. Note that this does not register a +// username/identity, but merely creates a new cryptographic identity +// for adding such information at a later date. +func NewPrecannedClient(precannedID uint, defJSON, storageDir string, + password []byte) error { + jww.INFO.Printf("NewPrecannedClient()") + rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, + csprng.NewSystemRNG) + rngStream := rngStreamGen.GetStream() + + def, err := ParseNDF(defJSON) + if err != nil { + return err + } + cmixGrp, e2eGrp := DecodeGroups(def) + + protoUser := CreatePrecannedUser(precannedID, rngStream) + + store, err := CheckVersionAndSetupStorage(def, storageDir, password, + protoUser, cmixGrp, e2eGrp, "") + if err != nil { + return err + } + + // Mark the precanned user as finished with permissioning and registered + // with the network. + err = store.ForwardRegistrationStatus(storage.PermissioningComplete) + if err != nil { + return err + } + + return nil +} + +func generatePrecanDHKeypair(precannedID uint, e2eGrp *cyclic.Group) *cyclic.Int { + // DH Keygen + prng := rand.New(rand.NewSource(int64(precannedID))) + prime := e2eGrp.GetPBytes() + keyLen := len(prime) + priv := diffieHellman.GeneratePrivateKey(keyLen, e2eGrp, prng) + return priv +} + +// Create an insecure e2e relationship with a precanned user +func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( + contact.Contact, error) { + + precan := m.MakePrecannedContact(precannedID) + + myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:]) + // Pick a variant based on if their ID is bigger than mine. + myVariant := sidh.KeyVariantSidhA + theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB) + if myID > uint64(precannedID) { + myVariant = sidh.KeyVariantSidhB + theirVariant = sidh.KeyVariantSidhA + } + prng1 := rand.New(rand.NewSource(int64(precannedID))) + theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant) + theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant) + theirSIDHPrivKey.Generate(prng1) + theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey) + + prng2 := rand.New(rand.NewSource(int64(myID))) + mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant) + mySIDHPubKey := util.NewSIDHPublicKey(myVariant) + mySIDHPrivKey.Generate(prng2) + mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey) + + // add the precanned user as a e2e contact + // FIXME: these params need to be threaded through... + sesParam := session.GetDefaultParams() + _, err := m.e2e.AddPartner(precan.ID, precan.DhPubKey, + m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey, + mySIDHPrivKey, sesParam, sesParam) + + // check garbled messages in case any messages arrived before creating + // the channel + m.GetCmix().CheckInProgressMessages() + + return precan, err +} + +// Create an insecure e2e contact object for a precanned user +func (m *E2e) MakePrecannedContact(precannedID uint) contact.Contact { + + e2eGrp := m.GetStorage().GetE2EGroup() + + rng := m.GetRng().GetStream() + precanned := CreatePrecannedUser(precannedID, rng) + rng.Close() + + precanned.E2eDhPrivateKey = generatePrecanDHKeypair(precannedID, + m.GetStorage().GetE2EGroup()) + + // compute their public e2e key + partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey, + e2eGrp.NewInt(1)) + + return contact.Contact{ + ID: precanned.ReceptionID, + DhPubKey: partnerPubKey, + OwnershipProof: nil, + Facts: make([]fact.Fact, 0), + } +} diff --git a/api/services.go b/xxdk/services.go similarity index 99% rename from api/services.go rename to xxdk/services.go index 3acfddbfe32bc8cfb08ad3431b4932e9f3438922..b44149ec16fdf8ff5b01bd4dbc5f3c5bb5cd78c2 100644 --- a/api/services.go +++ b/xxdk/services.go @@ -1,4 +1,4 @@ -package api +package xxdk import ( "github.com/pkg/errors" diff --git a/api/services_test.go b/xxdk/services_test.go similarity index 99% rename from api/services_test.go rename to xxdk/services_test.go index be65c1a5faeec4964eeac8a8568b60aacda7a2d1..c87f3bcecb79775214992747eaad06cf826b159b 100644 --- a/api/services_test.go +++ b/xxdk/services_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "errors" diff --git a/api/status.go b/xxdk/status.go similarity index 98% rename from api/status.go rename to xxdk/status.go index 33e567725a16b457e936270a3f43acaf7c671129..f613f87d454032d05f2114999d95728b4e2670a9 100644 --- a/api/status.go +++ b/xxdk/status.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "fmt" diff --git a/api/user.go b/xxdk/user.go similarity index 99% rename from api/user.go rename to xxdk/user.go index cbe2b92a38041877a368291122016c9907ff9f12..4eb421050ed68c242dff2b1f509d01b41c05cdc8 100644 --- a/api/user.go +++ b/xxdk/user.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "regexp" diff --git a/api/messenger/utils.go b/xxdk/utils.go similarity index 98% rename from api/messenger/utils.go rename to xxdk/utils.go index 6e1ff51fd9be792124e30ee2a4e0487d3598efdc..d4ade6ce9f6d87f423da4b95e91a3aa5cfeb1019 100644 --- a/api/messenger/utils.go +++ b/xxdk/utils.go @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2021 Privategrity Corporation / +// Copyright © 2022 Privategrity Corporation / // / // All rights reserved. / //////////////////////////////////////////////////////////////////////////////// // Provides various utility functions for access over the bindings -package messenger +package xxdk import ( "bytes" diff --git a/api/utilsInterfaces_test.go b/xxdk/utilsInterfaces_test.go similarity index 99% rename from api/utilsInterfaces_test.go rename to xxdk/utilsInterfaces_test.go index 72e141698805b029a799d19ccd4ca7e5f4a82e3e..107fb06778868bdf829e537c51d3cd1ae6cb9571 100644 --- a/api/utilsInterfaces_test.go +++ b/xxdk/utilsInterfaces_test.go @@ -4,7 +4,7 @@ // Use of this source code is governed by a license that can be found in the // // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "gitlab.com/xx_network/primitives/ndf" diff --git a/api/utils_test.go b/xxdk/utils_test.go similarity index 97% rename from api/utils_test.go rename to xxdk/utils_test.go index b2f59f90739fa8bff71292d35d5bac9f09cdcbae..2f6afc7196c3f2e554482ab848f290a83084ec7c 100644 --- a/api/utils_test.go +++ b/xxdk/utils_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package api +package xxdk import ( "testing" @@ -26,7 +26,7 @@ import ( "gitlab.com/xx_network/primitives/utils" ) -func newTestingClient(face interface{}) (*Client, error) { +func newTestingClient(face interface{}) (*Cmix, error) { switch face.(type) { case *testing.T, *testing.M, *testing.B, *testing.PB: break @@ -45,7 +45,7 @@ func newTestingClient(face interface{}) (*Client, error) { "Could not construct a mock client: %v", err) } - c, err := OpenClient(storageDir, password, GetDefaultParams()) + c, err := OpenCmix(storageDir, password, GetDefaultParams()) if err != nil { return nil, errors.Errorf("Could not open a mock client: %v", err) diff --git a/api/version_vars.go b/xxdk/version_vars.go similarity index 93% rename from api/version_vars.go rename to xxdk/version_vars.go index dd52d6cf364f5fc60d6c08891c72b556e773498b..c7e51f9da6c60b59f90315518d4b4d80e1b4e09d 100644 --- a/api/version_vars.go +++ b/xxdk/version_vars.go @@ -1,9 +1,9 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2022-06-06 16:30:34.245821 -0500 CDT m=+0.030165276 -package api +// 2022-06-16 12:41:25.706495 -0500 CDT m=+0.027317522 +package xxdk -const GITVERSION = `48285297 Merge branch 'restructure' into 'release'` +const GITVERSION = `1e874329 fix Makefile` const SEMVER = "4.2.0" const DEPENDENCIES = `module gitlab.com/elixxir/client @@ -58,7 +58,6 @@ require ( gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/text v0.3.6 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go index 96e9c2b1b8d4fd26680bef805f27bbdb712d71b4..0f8b6a565b0903fd8ea98b279610a0e307902383 100644 --- a/xxmutils/restoreContacts.go +++ b/xxmutils/restoreContacts.go @@ -11,8 +11,8 @@ import ( "encoding/json" "errors" "fmt" - "gitlab.com/elixxir/client/api/messenger" "gitlab.com/elixxir/client/single" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/xx_network/primitives/netTime" "math" "strings" @@ -37,7 +37,7 @@ import ( // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func RestoreContactsFromBackup(backupPartnerIDs []byte, client *messenger.Client, +func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e, udManager *ud.Manager, updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID, []error, error) { @@ -178,7 +178,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *messenger.Client // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func LookupContacts(in chan *id.ID, out chan *contact.Contact, - failCh chan failure, client *messenger.Client, udContact contact.Contact, + failCh chan failure, client *xxdk.E2e, udContact contact.Contact, wg *sync.WaitGroup) { defer wg.Done() // Start looking up contacts with user discovery and feed this @@ -205,7 +205,7 @@ func LookupContacts(in chan *id.ID, out chan *contact.Contact, // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func ResetSessions(in, out chan *contact.Contact, failCh chan failure, - client *messenger.Client, wg *sync.WaitGroup) { + client *xxdk.E2e, wg *sync.WaitGroup) { defer wg.Done() for c := range in { _, err := client.GetAuth().Reset(*c) @@ -224,7 +224,7 @@ func ResetSessions(in, out chan *contact.Contact, failCh chan failure, // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func LookupContact(userID *id.ID, client *messenger.Client, udContact contact.Contact) ( +func LookupContact(userID *id.ID, client *xxdk.E2e, udContact contact.Contact) ( *contact.Contact, error) { // This is a little wonky, but wait until we get called then // set the result to the contact objects details if there is