diff --git a/backup/backupRestore.go b/backup/backupRestore.go
index 91950ce8ad8912a50cadbf0d3aa60051e17a4c1a..94e1180ae0d5a993d4d13ca63854e6b690885e1c 100644
--- a/backup/backupRestore.go
+++ b/backup/backupRestore.go
@@ -8,6 +8,7 @@ package backup
 
 import (
 	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/e2e"
 	"gitlab.com/elixxir/client/e2e/rekey"
 	"gitlab.com/elixxir/client/storage"
@@ -35,6 +36,9 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
 			"Failed to unmarshal decrypted client contents.")
 	}
 
+	jww.INFO.Printf("Decrypted backup ID to Restore: %v",
+		backUp.ReceptionIdentity.ComputedID)
+
 	userInfo := user.NewUserFromBackup(backUp)
 
 	def, err := xxdk.ParseNDF(ndfJSON)
diff --git a/bindings/e2e.go b/bindings/e2e.go
index 6edf2a9ff5d070bafcb32cee0a22c7e1a9977dc5..c2ddab490032145b15675d191c0a0fceaab9dda4 100644
--- a/bindings/e2e.go
+++ b/bindings/e2e.go
@@ -117,41 +117,6 @@ func LoginE2eEphemeral(cmixId int, callbacks AuthCallbacks, identity,
 	return e2eTrackerSingleton.make(newE2e), nil
 }
 
-// LoginE2eLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
-// Uses the pre-generated transmission ID used by xxdk.Cmix
-// If callbacks is left nil, a default auth.Callbacks will be used
-// This function is designed to maintain backwards compatibility with previous xx messenger designs
-// and should not be used for other purposes
-func LoginE2eLegacy(cmixId int, callbacks AuthCallbacks, e2eParamsJSON []byte) (*E2e, error) {
-	if len(e2eParamsJSON) == 0 {
-		jww.WARN.Printf("e2e params not specified, using defaults...")
-		e2eParamsJSON = GetDefaultE2EParams()
-	}
-
-	cmix, err := cmixTrackerSingleton.get(cmixId)
-	if err != nil {
-		return nil, err
-	}
-
-	var authCallbacks xxdk.AuthCallbacks
-	if callbacks == nil {
-		authCallbacks = xxdk.DefaultAuthCallbacks{}
-	} else {
-		authCallbacks = &authCallback{bindingsCbs: callbacks}
-	}
-
-	params, err := parseE2EParams(e2eParamsJSON)
-	if err != nil {
-		return nil, err
-	}
-
-	newE2e, err := xxdk.LoginLegacy(cmix.api, params, authCallbacks)
-	if err != nil {
-		return nil, err
-	}
-	return e2eTrackerSingleton.make(newE2e), nil
-}
-
 // GetContact returns a marshalled contact.Contact object for the E2e ReceptionIdentity
 func (e *E2e) GetContact() []byte {
 	return e.api.GetReceptionIdentity().GetContact().Marshal()
diff --git a/bindings/identity.go b/bindings/identity.go
index b17e45d5eccbc5299e0b24374d87686312e53c5b..39665ca28bd5f90584f63ecf561733e7d886c106 100644
--- a/bindings/identity.go
+++ b/bindings/identity.go
@@ -42,6 +42,16 @@ func (c *Cmix) MakeIdentity() ([]byte, error) {
 	return ident.Marshal()
 }
 
+// MakeLegacyIdentity generates the legacy identity for receiving messages
+func (c *Cmix) MakeLegacyIdentity() ([]byte, error) {
+	ident, err := xxdk.MakeLegacyReceptionIdentity(c.api)
+	if err != nil {
+		return nil, err
+	}
+
+	return ident.Marshal()
+}
+
 // GetIDFromContact accepts a marshalled contact.Contact object & returns a marshalled id.ID object
 func GetIDFromContact(marshaled []byte) ([]byte, error) {
 	cnt, err := contact.Unmarshal(marshaled)
diff --git a/cmd/backup.go b/cmd/backup.go
index 5a2091a49c97a891eff87a6b6b959b4eb8d600eb..faabf16661b45b783a6c11a6ff8f9438b02b1ac5 100644
--- a/cmd/backup.go
+++ b/cmd/backup.go
@@ -8,6 +8,10 @@ package cmd
 
 import (
 	"encoding/json"
+	"io/fs"
+	"io/ioutil"
+	"os"
+
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
@@ -15,18 +19,16 @@ import (
 	"gitlab.com/elixxir/client/xxdk"
 	backupCrypto "gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/xx_network/primitives/utils"
-	"io/fs"
-	"io/ioutil"
-	"os"
 )
 
 // loadOrInitBackup will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitBackup(backupPath string, backupPass string, password []byte, storeDir string,
 	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	jww.INFO.Printf("Using Backup sender")
 
 	// create a new client if none exist
-	var baseClient *xxdk.Cmix
+	var net *xxdk.Cmix
 	var identity xxdk.ReceptionIdentity
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
 		// Initialize from scratch
@@ -72,39 +74,37 @@ func loadOrInitBackup(backupPath string, backupPass string, password []byte, sto
 			}
 		}
 
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		// TODO: Get proper identity
-		identity, err = xxdk.MakeReceptionIdentity(baseClient)
+		identity, err = xxdk.MakeLegacyReceptionIdentity(net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	} else {
 		// Initialize from storage
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
-		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
+		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
 
-	jww.INFO.Printf("Using LoginLegacy for precan sender")
-	client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs)
+	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	return client
+	return messenger
 }
 
 func loadBackup(backupPath, backupPass string) (backupCrypto.Backup, []byte) {
diff --git a/cmd/callbacks.go b/cmd/callbacks.go
index 4be99e0d0b6c7521d34cdd4cfa7e9ac90a763dbe..ec6bf4cd1760e009c9477b0d845d7a228c5f9e6f 100644
--- a/cmd/callbacks.go
+++ b/cmd/callbacks.go
@@ -40,7 +40,7 @@ func makeAuthCallbacks(autoConfirm bool, params xxdk.E2EParams) *authCallbacks {
 
 func (a *authCallbacks) Request(requestor contact.Contact,
 	receptionID receptionID.EphemeralIdentity,
-	round rounds.Round, client *xxdk.E2e) {
+	round rounds.Round, messenger *xxdk.E2e) {
 	msg := fmt.Sprintf("Authentication channel request from: %s\n",
 		requestor.ID)
 	jww.INFO.Printf(msg)
@@ -49,9 +49,9 @@ func (a *authCallbacks) Request(requestor contact.Contact,
 		jww.INFO.Printf("Channel Request: %s",
 			requestor.ID)
 		if viper.GetBool("verify-sends") { // Verify message sends were successful
-			acceptChannelVerified(client, requestor.ID, a.params)
+			acceptChannelVerified(messenger, requestor.ID, a.params)
 		} else {
-			acceptChannel(client, requestor.ID)
+			acceptChannel(messenger, requestor.ID)
 		}
 
 		a.confCh <- requestor.ID
@@ -60,15 +60,15 @@ func (a *authCallbacks) Request(requestor contact.Contact,
 }
 
 func (a *authCallbacks) Confirm(requestor contact.Contact,
-	receptionID receptionID.EphemeralIdentity,
-	round rounds.Round, client *xxdk.E2e) {
+	_ receptionID.EphemeralIdentity,
+	_ rounds.Round, _ *xxdk.E2e) {
 	jww.INFO.Printf("Channel Confirmed: %s", requestor.ID)
 	a.confCh <- requestor.ID
 }
 
 func (a *authCallbacks) Reset(requestor contact.Contact,
-	receptionID receptionID.EphemeralIdentity,
-	round rounds.Round, client *xxdk.E2e) {
+	_ receptionID.EphemeralIdentity,
+	_ rounds.Round, _ *xxdk.E2e) {
 	msg := fmt.Sprintf("Authentication channel reset from: %s\n",
 		requestor.ID)
 	jww.INFO.Printf(msg)
diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go
index eb9b7f34e441b078db012e114b3abc45f00154a3..20e8968bf9e4e2ef69556ad7cd1459984c07bee9 100644
--- a/cmd/fileTransfer.go
+++ b/cmd/fileTransfer.go
@@ -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 *xxdk.E2e, maxThroughput int) (
+func initFileTransferManager(messenger *xxdk.E2e, maxThroughput int) (
 	*ftE2e.Wrapper, chan receivedFtResults) {
 
 	// Create interfaces.ReceiveCallback that returns the results on a channel
@@ -152,24 +152,24 @@ func initFileTransferManager(client *xxdk.E2e, maxThroughput int) (
 
 	// Create new manager
 	manager, err := ft.NewManager(p,
-		client.GetReceptionIdentity().ID,
-		client.GetCmix(),
-		client.GetStorage(),
-		client.GetRng())
+		messenger.GetReceptionIdentity().ID,
+		messenger.GetCmix(),
+		messenger.GetStorage(),
+		messenger.GetRng())
 	if err != nil {
 		jww.FATAL.Panicf(
 			"[FT] Failed to create new file transfer manager: %+v", err)
 	}
 
 	// Start the file transfer sending and receiving threads
-	err = client.AddService(manager.StartProcesses)
+	err = messenger.AddService(manager.StartProcesses)
 	if err != nil {
 		jww.FATAL.Panicf("[FT] Failed to start file transfer threads: %+v", err)
 	}
 
 	e2eParams := ftE2e.DefaultParams()
 	e2eFt, err := ftE2e.NewWrapper(receiveCB, e2eParams, manager,
-		client.GetReceptionIdentity().ID, client.GetE2E(), client.GetCmix())
+		messenger.GetReceptionIdentity().ID, messenger.GetE2E(), messenger.GetCmix())
 	if err != nil {
 		jww.FATAL.Panicf(
 			"[FT] Failed to create new e2e file transfer wrapper: %+v", err)
diff --git a/cmd/group.go b/cmd/group.go
index 3045e71b328bc51dc71fd30364398e761c7170b3..8909d2214812729af586dd75e7a6f342e01d18f0 100644
--- a/cmd/group.go
+++ b/cmd/group.go
@@ -116,7 +116,7 @@ var groupCmd = &cobra.Command{
 
 // initGroupManager creates a new group chat manager and starts the process
 // service.
-func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat,
+func initGroupManager(messenger *xxdk.E2e) (groupChat.GroupChat,
 	chan groupChat.MessageReceive, chan groupStore.Group) {
 	recChan := make(chan groupChat.MessageReceive, 10)
 
@@ -126,10 +126,10 @@ func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat,
 	}
 
 	jww.INFO.Print("[GC] Creating new group manager.")
-	manager, err := groupChat.NewManager(client.GetCmix(),
-		client.GetE2E(), client.GetStorage().GetReceptionID(),
-		client.GetRng(), client.GetStorage().GetE2EGroup(),
-		client.GetStorage().GetKV(), requestCb, &receiveProcessor{recChan})
+	manager, err := groupChat.NewManager(messenger.GetCmix(),
+		messenger.GetE2E(), messenger.GetStorage().GetReceptionID(),
+		messenger.GetRng(), messenger.GetStorage().GetE2EGroup(),
+		messenger.GetStorage().GetKV(), requestCb, &receiveProcessor{recChan})
 	if err != nil {
 		jww.FATAL.Panicf("[GC] Failed to initialize group chat manager: %+v", err)
 	}
diff --git a/cmd/init.go b/cmd/init.go
index 9028bcff711a7c77738e42b39022b0ea122af0a8..a126e95e983a99de5693a525dc11b8a25405d8cb 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -9,14 +9,17 @@
 package cmd
 
 import (
+	"fmt"
+
+	"io/fs"
+	"io/ioutil"
+	"os"
+
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
 	"gitlab.com/elixxir/client/xxdk"
-	"io/fs"
-	"io/ioutil"
-	"os"
 )
 
 // initCmd creates a new user object with the given NDF
@@ -37,23 +40,26 @@ var initCmd = &cobra.Command{
 		}
 
 		err = xxdk.NewCmix(string(ndfJson), storeDir, storePassword, regCode)
-		baseClient, err := xxdk.OpenCmix(storeDir, storePassword)
+		net, err := xxdk.OpenCmix(storeDir, storePassword)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		identity, err := xxdk.MakeReceptionIdentity(baseClient)
+		identity, err := xxdk.MakeReceptionIdentity(net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
 		jww.INFO.Printf("User: %s", identity.ID)
 		writeContact(identity.GetContact())
+
+		// NOTE: DO NOT REMOVE THIS LINE. YOU WILL BREAK INTEGRATION
+		fmt.Printf("%s\n", identity.ID)
 	},
 }
 
@@ -65,13 +71,14 @@ func init() {
 	rootCmd.AddCommand(initCmd)
 }
 
-// loadOrInitClient will build a new xxdk.E2e from existing storage
+// loadOrInitMessenger will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
-func loadOrInitClient(password []byte, storeDir, regCode string,
+func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string,
 	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	jww.INFO.Printf("Using normal sender")
 
 	// create a new client if none exist
-	var baseClient *xxdk.Cmix
+	var net *xxdk.Cmix
 	var identity xxdk.ReceptionIdentity
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
 		// Initialize from scratch
@@ -81,50 +88,55 @@ func loadOrInitClient(password []byte, storeDir, regCode string,
 		}
 
 		err = xxdk.NewCmix(string(ndfJson), storeDir, password, regCode)
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		identity, err = xxdk.MakeReceptionIdentity(baseClient)
+		if forceLegacy {
+			jww.INFO.Printf("Forcing legacy sender")
+			identity, err = xxdk.MakeLegacyReceptionIdentity(net)
+		} else {
+			identity, err = xxdk.MakeReceptionIdentity(net)
+		}
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	} else {
 		// Initialize from storage
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
-		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
+		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
 
-	jww.INFO.Printf("Using Login for normal sender")
-	client, err := xxdk.Login(baseClient, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	return client
+	return messenger
 }
 
 // loadOrInitVanity will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
 	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	jww.INFO.Printf("Using Vanity sender")
 
 	// create a new client if none exist
-	var baseClient *xxdk.Cmix
+	var net *xxdk.Cmix
 	var identity xxdk.ReceptionIdentity
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
-		// Initialize precan from scratch
+		// Initialize from scratch
 		ndfJson, err := ioutil.ReadFile(viper.GetString("ndf"))
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
@@ -132,37 +144,35 @@ func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
 
 		err = xxdk.NewVanityClient(string(ndfJson), storeDir,
 			password, regCode, userIdPrefix)
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		// TODO: Get proper identity
-		identity, err = xxdk.MakeReceptionIdentity(baseClient)
+		identity, err = xxdk.MakeLegacyReceptionIdentity(net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	} else {
-		// Initialize precan from storage
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		// Initialize from storage
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
-		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
+		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
 
-	jww.INFO.Printf("Using LoginLegacy for vanity sender")
-	client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs)
+	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	return client
+	return messenger
 }
diff --git a/cmd/precan.go b/cmd/precan.go
index 9b3a35f2fcace0fd4367e654e4f5689a37839d32..dded07723871e34ba54065ab628a346b055603a0 100644
--- a/cmd/precan.go
+++ b/cmd/precan.go
@@ -25,9 +25,10 @@ import (
 // or from a new storage that it will create if none already exists
 func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
 	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	jww.INFO.Printf("Using Precanned sender")
 
 	// create a new client if none exist
-	var baseClient *xxdk.Cmix
+	var net *xxdk.Cmix
 	var identity xxdk.ReceptionIdentity
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
 		// Initialize from scratch
@@ -36,35 +37,38 @@ func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		// TODO: Separate identity from this call
-		identity, err = xxdk.NewPrecannedClient(precanId, string(ndfJson), storeDir, password)
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		err = xxdk.NewPrecannedClient(precanId, string(ndfJson), storeDir, password)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		identity, err = xxdk.MakeLegacyReceptionIdentity(net)
+		if err != nil {
+			return nil
+		}
+
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	} else {
 		// Initialize from storage
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
-		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
+		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
 
-	jww.INFO.Printf("Using LoginLegacy for precan sender")
-	client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs)
+	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	return client
+	return messenger
 }
 
 func isPrecanID(id *id.ID) bool {
@@ -85,10 +89,10 @@ func getPrecanID(recipientID *id.ID) uint {
 	return uint(recipientID.Bytes()[7])
 }
 
-func addPrecanAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
+func addPrecanAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact) {
 	jww.WARN.Printf("Precanned user id detected: %s", recipientID)
-	preUsr, err := client.MakePrecannedAuthenticatedChannel(
+	preUsr, err := messenger.MakePrecannedAuthenticatedChannel(
 		getPrecanID(recipientID))
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
diff --git a/cmd/proto.go b/cmd/proto.go
index 3d2568e16d567dd4b97195cc5314e54be46a61f9..bdb5b0855d764a077b1ac47d329bcffc29b2ff8b 100644
--- a/cmd/proto.go
+++ b/cmd/proto.go
@@ -23,9 +23,10 @@ import (
 // or from a new storage that it will create if none already exists
 func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
 	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	jww.INFO.Printf("Using Proto sender")
 
 	// create a new client if none exist
-	var baseClient *xxdk.Cmix
+	var net *xxdk.Cmix
 	var identity xxdk.ReceptionIdentity
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
 		// Initialize from scratch
@@ -45,34 +46,36 @@ func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
 			jww.FATAL.Panicf("%v", err)
 		}
 
-		// TODO: Separate identity from this call
-		identity, err = xxdk.NewProtoClient_Unsafe(string(ndfJson), storeDir,
+		err = xxdk.NewProtoClient_Unsafe(string(ndfJson), storeDir,
 			password, protoUser)
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
-		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
+		identity, err = xxdk.MakeLegacyReceptionIdentity(net)
+		if err != nil {
+			return nil
+		}
+
+		err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	} else {
 		// Initialize from storage
-		baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams)
+		net, err = xxdk.LoadCmix(storeDir, password, cmixParams)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
-		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
+		identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
-
-	jww.INFO.Printf("Using Login for proto sender")
-	client, err := xxdk.Login(baseClient, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	return client
+	return messenger
 }
diff --git a/cmd/root.go b/cmd/root.go
index 59c83e81871ab52418cd8d5703830df926768d03..4b360c8d188b767768548bf2d2904a46a1f0d5db 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -585,6 +585,7 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
 	storePassword := parsePassword(viper.GetString("password"))
 	storeDir := viper.GetString("session")
 	regCode := viper.GetString("regcode")
+	forceLegacy := viper.GetBool("force-legacy")
 	jww.DEBUG.Printf("sessionDir: %v", storeDir)
 
 	// TODO: This probably shouldn't be initialized globally.
@@ -592,22 +593,22 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
 		viper.GetBool("unsafe-channel-creation"), e2eParams)
 
 	// Initialize the client of the proper type
-	var client *xxdk.E2e
+	var messenger *xxdk.E2e
 	if precanId != 0 {
-		client = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams)
 	} else if protoUserPath != "" {
-		client = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams)
 	} else if userIdPrefix != "" {
-		client = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams)
+		messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams)
 	} else if backupPath != "" {
-		client = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams)
 	} else {
-		client = loadOrInitClient(storePassword, storeDir, regCode, cmixParams, e2eParams)
+		messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams)
 	}
 
 	// Handle protoUser output
 	if protoUser := viper.GetString("protoUserOut"); protoUser != "" {
-		jsonBytes, err := client.ConstructProtoUserFile()
+		jsonBytes, err := messenger.ConstructProtoUserFile()
 		if err != nil {
 			jww.FATAL.Panicf("cannot construct proto user file: %v",
 				err)
@@ -622,6 +623,9 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
 
 	// Handle backup output
 	if backupOut := viper.GetString("backupOut"); backupOut != "" {
+		if !forceLegacy {
+			jww.FATAL.Panicf("Unable to make backup for non-legacy sender!")
+		}
 		updateBackupCb := func(encryptedBackup []byte) {
 			jww.INFO.Printf("Backup update received, size %d",
 				len(encryptedBackup))
@@ -653,24 +657,24 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
 			}
 		}
 		_, err := backup.InitializeBackup(backupPass, updateBackupCb,
-			client.GetBackupContainer(), client.GetE2E(), client.GetStorage(),
-			nil, client.GetStorage().GetKV(), client.GetRng())
+			messenger.GetBackupContainer(), messenger.GetE2E(), messenger.GetStorage(),
+			nil, messenger.GetStorage().GetKV(), messenger.GetRng())
 		if err != nil {
 			jww.FATAL.Panicf("Failed to initialize backup with key %q: %+v",
 				backupPass, err)
 		}
 	}
 
-	return client
+	return messenger
 }
 
-func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round {
-	recipientContact, err := client.GetAuth().GetReceivedRequest(
+func acceptChannel(messenger *xxdk.E2e, recipientID *id.ID) id.Round {
+	recipientContact, err := messenger.GetAuth().GetReceivedRequest(
 		recipientID)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
-	rid, err := client.GetAuth().Confirm(
+	rid, err := messenger.GetAuth().Confirm(
 		recipientContact)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
@@ -679,14 +683,14 @@ func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round {
 	return rid
 }
 
-func deleteChannel(client *xxdk.E2e, partnerId *id.ID) {
-	err := client.DeleteContact(partnerId)
+func deleteChannel(messenger *xxdk.E2e, partnerId *id.ID) {
+	err := messenger.DeleteContact(partnerId)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
 }
 
-func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
+func addAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact, e2eParams xxdk.E2EParams) {
 	var allowed bool
 	if viper.GetBool("unsafe-channel-creation") {
@@ -709,17 +713,17 @@ func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	recipientContact := recipient
 
 	if recipientContact.ID != nil && recipientContact.DhPubKey != nil {
-		me := client.GetReceptionIdentity().GetContact()
+		me := messenger.GetReceptionIdentity().GetContact()
 		jww.INFO.Printf("Requesting auth channel from: %s",
 			recipientID)
 
 		// Verify that the auth request makes it to the recipient
 		// by monitoring the round result
 		if viper.GetBool("verify-sends") {
-			requestChannelVerified(client, recipientContact, me, e2eParams)
+			requestChannelVerified(messenger, recipientContact, me, e2eParams)
 		} else {
 			// Just call Request, agnostic of round result
-			_, err := client.GetAuth().Request(recipientContact,
+			_, err := messenger.GetAuth().Request(recipientContact,
 				me.Facts)
 			if err != nil {
 				jww.FATAL.Panicf("%+v", err)
@@ -732,7 +736,7 @@ func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	}
 }
 
-func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
+func resetAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID,
 	recipient contact.Contact, e2eParams xxdk.E2EParams) {
 	var allowed bool
 	if viper.GetBool("unsafe-channel-creation") {
@@ -760,10 +764,10 @@ func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 		// Verify that the auth request makes it to the recipient
 		// by monitoring the round result
 		if viper.GetBool("verify-sends") {
-			resetChannelVerified(client, recipientContact,
+			resetChannelVerified(messenger, recipientContact,
 				e2eParams)
 		} else {
-			_, err := client.GetAuth().Reset(recipientContact)
+			_, err := messenger.GetAuth().Reset(recipientContact)
 			if err != nil {
 				jww.FATAL.Panicf("%+v", err)
 			}
@@ -774,17 +778,17 @@ func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID,
 	}
 }
 
-func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID,
+func acceptChannelVerified(messenger *xxdk.E2e, recipientID *id.ID,
 	params xxdk.E2EParams) {
 	roundTimeout := params.Base.CMIXParams.SendTimeout
 
 	done := make(chan struct{}, 1)
 	retryChan := make(chan struct{}, 1)
 	for {
-		rid := acceptChannel(client, recipientID)
+		rid := acceptChannel(messenger, recipientID)
 
 		// Monitor rounds for results
-		err := client.GetCmix().GetRoundResults(roundTimeout,
+		err := messenger.GetCmix().GetRoundResults(roundTimeout,
 			makeVerifySendsCallback(retryChan, done), rid)
 		if err != nil {
 			jww.DEBUG.Printf("Could not verify "+
@@ -810,7 +814,7 @@ func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID,
 	}
 }
 
-func requestChannelVerified(client *xxdk.E2e,
+func requestChannelVerified(messenger *xxdk.E2e,
 	recipientContact, me contact.Contact,
 	params xxdk.E2EParams) {
 	roundTimeout := params.Base.CMIXParams.SendTimeout
@@ -818,14 +822,14 @@ func requestChannelVerified(client *xxdk.E2e,
 	retryChan := make(chan struct{}, 1)
 	done := make(chan struct{}, 1)
 	for {
-		rid, err := client.GetAuth().Request(recipientContact,
+		rid, err := messenger.GetAuth().Request(recipientContact,
 			me.Facts)
 		if err != nil {
 			continue
 		}
 
 		// Monitor rounds for results
-		err = client.GetCmix().GetRoundResults(roundTimeout,
+		err = messenger.GetCmix().GetRoundResults(roundTimeout,
 			makeVerifySendsCallback(retryChan, done),
 			rid)
 		if err != nil {
@@ -850,7 +854,7 @@ func requestChannelVerified(client *xxdk.E2e,
 	}
 }
 
-func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact,
+func resetChannelVerified(messenger *xxdk.E2e, recipientContact contact.Contact,
 	params xxdk.E2EParams) {
 	roundTimeout := params.Base.CMIXParams.SendTimeout
 
@@ -858,13 +862,13 @@ func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact,
 	done := make(chan struct{}, 1)
 	for {
 
-		rid, err := client.GetAuth().Reset(recipientContact)
+		rid, err := messenger.GetAuth().Reset(recipientContact)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
 		// Monitor rounds for results
-		err = client.GetCmix().GetRoundResults(roundTimeout,
+		err = messenger.GetCmix().GetRoundResults(roundTimeout,
 			makeVerifySendsCallback(retryChan, done),
 			rid)
 		if err != nil {
@@ -1131,6 +1135,9 @@ func init() {
 		"ID to send message to (if below 40, will be precanned. Use "+
 			"'0x' or 'b64:' for hex and base64 representations)")
 	viper.BindPFlag("destid", rootCmd.Flags().Lookup("destid"))
+	rootCmd.PersistentFlags().Bool("force-legacy", false,
+		"Force client to operate using legacy identities.")
+	viper.BindPFlag("force-legacy", rootCmd.PersistentFlags().Lookup("force-legacy"))
 
 	rootCmd.Flags().StringP("destfile", "",
 		"", "Read this contact file for the destination id")
diff --git a/cmd/single.go b/cmd/single.go
index 406374c939efacb4af6e0e5b55f5cf91581da5c0..6a7e99575ff163f03c82bb2cc9799fa884e8775e 100644
--- a/cmd/single.go
+++ b/cmd/single.go
@@ -157,7 +157,7 @@ func (r *Response) Callback(payload []byte, receptionID receptionID.EphemeralIde
 }
 
 // sendSingleUse sends a single use message.
-func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte,
+func sendSingleUse(net *xxdk.Cmix, partner contact.Contact, payload []byte,
 	maxMessages uint8, timeout time.Duration, tag string) {
 	// Construct callback
 	callback := &Response{
@@ -178,12 +178,12 @@ func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte,
 		partner.ID, payload)
 	params := single.GetDefaultRequestParams()
 	params.MaxResponseMessages = maxMessages
-	rng := m.GetRng().GetStream()
+	rng := net.GetRng().GetStream()
 	defer rng.Close()
 
-	e2eGrp := m.GetStorage().GetE2EGroup()
+	e2eGrp := net.GetStorage().GetE2EGroup()
 	rnd, ephID, err := single.TransmitRequest(partner, tag, payload, callback, params,
-		m.GetCmix(), rng, e2eGrp)
+		net.GetCmix(), rng, e2eGrp)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to transmit single-use message: %+v", err)
 	}
diff --git a/cmd/ud.go b/cmd/ud.go
index cf1a0df7be220da8ded2bc23bba9b0c1c6c01fa3..b016651f39e6e576d36e2cbf189aba94c696c445 100644
--- a/cmd/ud.go
+++ b/cmd/ud.go
@@ -39,38 +39,16 @@ var udCmd = &cobra.Command{
 
 		// get user and save contact to file
 		user := client.GetReceptionIdentity()
-		jww.INFO.Printf("User: %s", user.ID)
+		jww.INFO.Printf("[UD]User: %s", user.ID)
 		writeContact(user.GetContact())
 
-		// // Set up reception handler
-		// swBoard := client.GetSwitchboard()
-		// recvCh := make(chan message.Receive, 10000)
-		// listenerID := swBoard.RegisterChannel("DefaultCLIReceiver",
-		// 	switchboard.AnyUser(), message.XxMessage, recvCh)
-		// jww.INFO.Printf("Message ListenerID: %v", listenerID)
-
-		// // Set up auth request handler, which simply prints the user ID of the
-		// // requester
-		// authMgr := client.GetAuthRegistrar()
-		// authMgr.AddGeneralRequestCallback(printChanRequest)
-
-		// // If unsafe channels, add auto-acceptor
-		// if viper.GetBool("unsafe-channel-creation") {
-		// 	authMgr.AddGeneralRequestCallback(func(
-		// 		requester contact.Contact) {
-		// 		jww.INFO.Printf("Got Request: %s", requester.ID)
-		// 		_, err := client.ConfirmAuthenticatedChannel(requester)
-		// 		if err != nil {
-		// 			jww.FATAL.Panicf("%+v", err)
-		// 		}
-		// 	})
-		// }
-
 		err := client.StartNetworkFollower(50 * time.Millisecond)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
 		}
 
+		jww.TRACE.Printf("[UD] Waiting for connection...")
+
 		// Wait until connected or crash on timeout
 		connected := make(chan bool, 10)
 		client.GetCmix().AddHealthCallback(
@@ -79,9 +57,12 @@ var udCmd = &cobra.Command{
 			})
 		waitUntilConnected(connected)
 
+		jww.TRACE.Printf("[UD] Connected!")
+
 		// Make user discovery manager
 		rng := client.GetRng()
 		userToRegister := viper.GetString("register")
+		jww.TRACE.Printf("[UD] Registering user %v...", userToRegister)
 		userDiscoveryMgr, err := ud.NewManager(client, client.GetComms(),
 			client.NetworkFollowerStatus, userToRegister, nil)
 		if err != nil {
@@ -95,6 +76,7 @@ var udCmd = &cobra.Command{
 
 			}
 		}
+		jww.INFO.Printf("[UD] Registered user %v", userToRegister)
 
 		var newFacts fact.FactList
 		phone := viper.GetString("addphone")
@@ -116,24 +98,29 @@ var udCmd = &cobra.Command{
 		}
 
 		for i := 0; i < len(newFacts); i++ {
+			jww.INFO.Printf("[UD] Registering Fact: %v",
+				newFacts[i])
 			r, err := userDiscoveryMgr.SendRegisterFact(newFacts[i])
 			if err != nil {
 				fmt.Printf("Failed to register fact: %s\n",
 					newFacts[i])
-				jww.FATAL.Panicf("Failed to send register fact: %+v", err)
+				jww.FATAL.Panicf("[UD] Failed to send register fact: %+v", err)
 			}
 			// TODO Store the code?
-			jww.INFO.Printf("Fact Add Response: %+v", r)
+			jww.INFO.Printf("[UD] Fact Add Response: %+v", r)
 		}
 
 		confirmID := viper.GetString("confirm")
 		if confirmID != "" {
+			jww.INFO.Printf("[UD] Confirming fact: %v", confirmID)
 			err = userDiscoveryMgr.ConfirmFact(confirmID, confirmID)
 			if err != nil {
 				fmt.Printf("Couldn't confirm fact: %s\n",
 					err.Error())
 				jww.FATAL.Panicf("%+v", err)
 			}
+
+			jww.INFO.Printf("[UD] Confirmed %v", confirmID)
 		}
 
 		udContact, err := userDiscoveryMgr.GetContact()
@@ -147,9 +134,7 @@ var udCmd = &cobra.Command{
 		lookupIDStr := viper.GetString("lookup")
 		if lookupIDStr != "" {
 			lookupID := parseRecipient(lookupIDStr)
-			//if !ok {
-			//	jww.FATAL.Panicf("Could not parse recipient: %s", lookupIDStr)
-			//}
+			jww.INFO.Printf("[UD] Looking up %v", lookupID)
 
 			cb := func(newContact contact.Contact, err error) {
 				if err != nil {
@@ -177,6 +162,7 @@ var udCmd = &cobra.Command{
 					err.Error())
 				jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err)
 			}
+			jww.INFO.Printf("[UD] BATCHADD: Running")
 			restored, _, _, err := xxmutils.RestoreContactsFromBackup(
 				idListFile, client, userDiscoveryMgr, nil)
 			if err != nil {
@@ -187,7 +173,7 @@ var udCmd = &cobra.Command{
 				for !client.GetE2E().HasAuthenticatedChannel(uid) {
 					time.Sleep(time.Second)
 				}
-				jww.INFO.Printf("Authenticated channel established for %s", uid)
+				jww.INFO.Printf("[UD] Authenticated channel established for %s", uid)
 			}
 		}
 		usernameSearchStr := viper.GetString("searchusername")
@@ -232,7 +218,7 @@ var udCmd = &cobra.Command{
 					"Failed to remove user %s: %+v",
 					userToRemove, err)
 			}
-			fmt.Printf("Removed user from discovery: %s\n",
+			fmt.Printf("[UD] Removed user from discovery: %s\n",
 				userToRemove)
 		}
 
@@ -255,6 +241,7 @@ var udCmd = &cobra.Command{
 
 		stream := rng.GetStream()
 		defer stream.Close()
+		jww.INFO.Printf("[UD] Search: %v", facts)
 		_, _, err = ud.Search(client.GetCmix(),
 			client.GetEventReporter(),
 			stream, client.GetE2E().GetGroup(),
diff --git a/connect/authCallbacks.go b/connect/authCallbacks.go
index 227c47500e166155655ce96d0bdc0b9bfbfa2a94..01eb5e90ff994f83d79e68a11a0285104307a6f4 100644
--- a/connect/authCallbacks.go
+++ b/connect/authCallbacks.go
@@ -117,12 +117,12 @@ func (a serverAuthCallback) Confirm(contact.Contact,
 
 // Request will be called when an auth Request message is processed.
 func (a serverAuthCallback) Request(requestor contact.Contact,
-	_ receptionID.EphemeralIdentity, _ rounds.Round, e2e *xxdk.E2e) {
+	_ receptionID.EphemeralIdentity, _ rounds.Round, messenger *xxdk.E2e) {
 	if a.requestCallback == nil {
 		jww.ERROR.Printf("Received a request when requests are" +
 			"not enable, will not accept")
 	}
-	_, err := e2e.GetAuth().Confirm(requestor)
+	_, err := messenger.GetAuth().Confirm(requestor)
 	if err != nil {
 		jww.ERROR.Printf("Unable to build connection with "+
 			"partner %s: %+v", requestor.ID, err)
@@ -130,7 +130,7 @@ func (a serverAuthCallback) Request(requestor contact.Contact,
 		a.requestCallback(nil)
 	}
 	// After confirmation, get the new partner
-	newPartner, err := e2e.GetE2E().GetPartner(requestor.ID)
+	newPartner, err := messenger.GetE2E().GetPartner(requestor.ID)
 	if err != nil {
 		jww.ERROR.Printf("Unable to build connection with "+
 			"partner %s: %+v", requestor.ID, err)
@@ -142,7 +142,7 @@ func (a serverAuthCallback) Request(requestor contact.Contact,
 
 	// Return the new Connection object
 	c := BuildConnection(
-		newPartner, e2e.GetE2E(), e2e.GetAuth(), a.connectionParams)
+		newPartner, messenger.GetE2E(), messenger.GetAuth(), a.connectionParams)
 	a.cl.Add(c)
 	a.requestCallback(c)
 }
diff --git a/connect/authenticated.go b/connect/authenticated.go
index 4376a2ceec13c2588e2dd637ce742cff02a4b033..11f0d2de9d92cb2b42e34dab9618b61d48d77328 100644
--- a/connect/authenticated.go
+++ b/connect/authenticated.go
@@ -52,27 +52,27 @@ 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, e2eClient *xxdk.E2e,
+func ConnectWithAuthentication(recipient contact.Contact, messenger *xxdk.E2e,
 	p xxdk.E2EParams) (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, e2eClient, p)
+	conn, err := Connect(recipient, messenger, 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
-	identity := e2eClient.GetReceptionIdentity()
+	identity := messenger.GetReceptionIdentity()
 	privKey, err := identity.GetRSAPrivatePem()
 	if err != nil {
 		return nil, err
 	}
 	return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, privKey,
-		e2eClient.GetRng(), e2eClient.GetCmix(), p)
+		messenger.GetRng(), messenger.GetCmix(), p)
 }
 
 // connectWithAuthentication builds and sends an IdentityAuthentication to
diff --git a/connect/connect.go b/connect/connect.go
index 5e77868c43fb00970483a59b00350a6b5c082999..ea755c0b181cbace7c64f2bb8878dcfd612b022e 100644
--- a/connect/connect.go
+++ b/connect/connect.go
@@ -26,12 +26,6 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
-const (
-	// connectionTimeout is the time.Duration for a connection
-	// to be established before the requester times out.
-	connectionTimeout = 15 * time.Second
-)
-
 var alreadyClosedErr = errors.New("connection is closed")
 
 // Connection is a wrapper for the E2E and auth packages.
@@ -87,19 +81,19 @@ type Callback func(connection Connection)
 // 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, e2eClient *xxdk.E2e,
+func Connect(recipient contact.Contact, messenger *xxdk.E2e,
 	p xxdk.E2EParams) (Connection, error) {
 	// Build callback for E2E negotiation
 	signalChannel := make(chan Connection, 1)
 	cb := func(connection Connection) {
 		signalChannel <- connection
 	}
-	callback := getClientAuthCallback(cb, nil, e2eClient.GetE2E(),
-		e2eClient.GetAuth(), p)
-	e2eClient.GetAuth().AddPartnerCallback(recipient.ID, callback)
+	callback := getClientAuthCallback(cb, nil, messenger.GetE2E(),
+		messenger.GetAuth(), p)
+	messenger.GetAuth().AddPartnerCallback(recipient.ID, callback)
 
 	// Perform the auth request
-	_, err := e2eClient.GetAuth().Request(recipient, nil)
+	_, err := messenger.GetAuth().Request(recipient, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -157,8 +151,8 @@ func StartServer(identity xxdk.ReceptionIdentity, cb Callback, net *xxdk.Cmix,
 
 // ConnectionServer contains
 type ConnectionServer struct {
-	E2e *xxdk.E2e
-	Cl  *ConnectionList
+	Messenger *xxdk.E2e
+	Cl        *ConnectionList
 }
 
 // handler provides an implementation for the Connection interface.
diff --git a/dummy/manager.go b/dummy/manager.go
index 28ddd25e69c7e40bd2ee8a31a4b84d16ac9a7f5a..4832f3ef505ea37114c2f4d202c82604ddd7eab0 100644
--- a/dummy/manager.go
+++ b/dummy/manager.go
@@ -57,25 +57,25 @@ type Manager struct {
 	statusChan chan bool
 
 	// Cmix interfaces
-	client *xxdk.Cmix
-	store  *storage.Session
-	net    interfaces.NetworkManager
-	rng    *fastRNG.StreamGenerator
+	net            *xxdk.Cmix
+	store          *storage.Session
+	networkManager interfaces.NetworkManager
+	rng            *fastRNG.StreamGenerator
 }
 
 // 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 *xxdk.Cmix, manager interfaces.NetworkManager) *Manager {
-	clientStorage := client.GetStorage()
-	return newManager(maxNumMessages, avgSendDelta, randomRange, client,
-		&clientStorage, manager, client.GetRng())
+	net *xxdk.Cmix, manager interfaces.NetworkManager) *Manager {
+	clientStorage := net.GetStorage()
+	return newManager(maxNumMessages, avgSendDelta, randomRange, net,
+		&clientStorage, manager, net.GetRng())
 }
 
 // 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 *xxdk.Cmix, store *storage.Session, net interfaces.NetworkManager,
+	net *xxdk.Cmix, store *storage.Session, networkManager interfaces.NetworkManager,
 	rng *fastRNG.StreamGenerator) *Manager {
 	return &Manager{
 		maxNumMessages: maxNumMessages,
@@ -83,9 +83,9 @@ func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
 		randomRange:    randomRange,
 		status:         notStarted,
 		statusChan:     make(chan bool, statusChanLen),
-		client:         client,
-		store:          store,
 		net:            net,
+		store:          store,
+		networkManager: networkManager,
 		rng:            rng,
 	}
 }
diff --git a/dummy/manager_test.go b/dummy/manager_test.go
index 753b0fcb215855f960a5517305c430b0207e9776..6a49bcc6a597ebf476ee8bbfb8f45a79045a4488 100644
--- a/dummy/manager_test.go
+++ b/dummy/manager_test.go
@@ -59,7 +59,7 @@ func TestManager_StartDummyTraffic(t *testing.T) {
 
 	msgChan := make(chan bool)
 	go func() {
-		for m.net.(*testNetworkManager).GetMsgListLen() == 0 {
+		for m.networkManager.(*testNetworkManager).GetMsgListLen() == 0 {
 			time.Sleep(5 * time.Millisecond)
 		}
 		msgChan <- true
@@ -71,7 +71,7 @@ func TestManager_StartDummyTraffic(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		numReceived += m.net.(*testNetworkManager).GetMsgListLen()
+		numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen()
 	}
 
 	err = stop.Close()
@@ -86,7 +86,7 @@ func TestManager_StartDummyTraffic(t *testing.T) {
 
 	msgChan = make(chan bool)
 	go func() {
-		for m.net.(*testNetworkManager).GetMsgListLen() == numReceived {
+		for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived {
 			time.Sleep(5 * time.Millisecond)
 		}
 		msgChan <- true
@@ -118,10 +118,10 @@ func TestManager_SetStatus(t *testing.T) {
 	go func() {
 		var numReceived int
 		for i := 0; i < 2; i++ {
-			for m.net.(*testNetworkManager).GetMsgListLen() == numReceived {
+			for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived {
 				time.Sleep(5 * time.Millisecond)
 			}
-			numReceived = m.net.(*testNetworkManager).GetMsgListLen()
+			numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen()
 			msgChan <- true
 		}
 	}()
@@ -161,7 +161,7 @@ func TestManager_SetStatus(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		numReceived += m.net.(*testNetworkManager).GetMsgListLen()
+		numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen()
 	}
 
 	// Setting status to true multiple times does not interrupt sending
@@ -177,10 +177,10 @@ func TestManager_SetStatus(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived {
+		if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived {
 			t.Errorf("Failed to receive second send."+
 				"\nmessages on last receive: %d\nmessages on this receive: %d",
-				numReceived, m.net.(*testNetworkManager).GetMsgListLen())
+				numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen())
 		}
 	}
 
@@ -254,10 +254,10 @@ func TestManager_GetStatus(t *testing.T) {
 	go func() {
 		var numReceived int
 		for i := 0; i < 2; i++ {
-			for m.net.(*testNetworkManager).GetMsgListLen() == numReceived {
+			for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived {
 				time.Sleep(5 * time.Millisecond)
 			}
-			numReceived = m.net.(*testNetworkManager).GetMsgListLen()
+			numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen()
 			msgChan <- true
 		}
 	}()
@@ -292,7 +292,7 @@ func TestManager_GetStatus(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		numReceived += m.net.(*testNetworkManager).GetMsgListLen()
+		numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen()
 	}
 
 	// Setting status to true multiple times does not interrupt sending
@@ -311,10 +311,10 @@ func TestManager_GetStatus(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived {
+		if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived {
 			t.Errorf("Failed to receive second send."+
 				"\nmessages on last receive: %d\nmessages on this receive: %d",
-				numReceived, m.net.(*testNetworkManager).GetMsgListLen())
+				numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen())
 		}
 	}
 
diff --git a/dummy/send.go b/dummy/send.go
index f6f532c81557a3c440a1296a8c60f2f114146f73..84271b67ea4310bf91af057a58ffe2256520460a 100644
--- a/dummy/send.go
+++ b/dummy/send.go
@@ -106,7 +106,7 @@ func (m *Manager) sendMessages(msgs map[id.ID]format.Message) error {
 			// }
 			// rng.Close()
 			// p.DebugTag = "dummy"
-			_, _, err := m.net.SendCMIX(msg, &recipient, p)
+			_, _, err := m.networkManager.SendCMIX(msg, &recipient, p)
 			if err != nil {
 				jww.WARN.Printf("Failed to send dummy message %d/%d via "+
 					"Send: %+v", i, len(msgs), err)
diff --git a/dummy/send_test.go b/dummy/send_test.go
index 6a5a91feff0c152b70982e60e769aae53c37813e..9af8ee8796e4d76faa7d45188c60db271d772335 100644
--- a/dummy/send_test.go
+++ b/dummy/send_test.go
@@ -40,10 +40,10 @@ func TestManager_sendThread(t *testing.T) {
 	go func() {
 		var numReceived int
 		for i := 0; i < 2; i++ {
-			for m.net.(*testNetworkManager).GetMsgListLen() == numReceived {
+			for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived {
 				time.Sleep(5 * time.Millisecond)
 			}
-			numReceived = m.net.(*testNetworkManager).GetMsgListLen()
+			numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen()
 			msgChan <- true
 		}
 	}()
@@ -54,7 +54,7 @@ func TestManager_sendThread(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		numReceived += m.net.(*testNetworkManager).GetMsgListLen()
+		numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen()
 	}
 
 	select {
@@ -62,10 +62,10 @@ func TestManager_sendThread(t *testing.T) {
 		t.Errorf("Timed out after %s waiting for messages to be sent.",
 			3*m.avgSendDelta)
 	case <-msgChan:
-		if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived {
+		if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived {
 			t.Errorf("Failed to receive second send."+
 				"\nmessages on last receive: %d\nmessages on this receive: %d",
-				numReceived, m.net.(*testNetworkManager).GetMsgListLen())
+				numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen())
 		}
 	}
 
@@ -115,7 +115,7 @@ func TestManager_sendMessages(t *testing.T) {
 	}
 
 	// get sent messages
-	receivedMsgs := m.net.(*testNetworkManager).GetMsgList()
+	receivedMsgs := m.networkManager.(*testNetworkManager).GetMsgList()
 
 	// Test that all messages were received
 	if len(receivedMsgs) != len(msgs) {
diff --git a/dummy/utils_test.go b/dummy/utils_test.go
index cbc441c22d732469ecc77f145c8de9796c6adee7..bc838731f5f42b345c4fbdfd849750b4551c0ef5 100644
--- a/dummy/utils_test.go
+++ b/dummy/utils_test.go
@@ -59,7 +59,7 @@ func newTestManager(maxNumMessages int, avgSendDelta, randomRange time.Duration,
 		randomRange:    randomRange,
 		statusChan:     make(chan bool, statusChanLen),
 		store:          &store,
-		net:            newTestNetworkManager(sendErr, t),
+		networkManager: newTestNetworkManager(sendErr, t),
 		rng:            fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
 	}
 
diff --git a/e2e/ratchet/partner/relationshipFingerprint.go b/e2e/ratchet/partner/relationshipFingerprint.go
index e00f6aa69638830752b079332e63f0f6bb68755f..9380b9a5051e9d82f76d3043e880350600425d6b 100644
--- a/e2e/ratchet/partner/relationshipFingerprint.go
+++ b/e2e/ratchet/partner/relationshipFingerprint.go
@@ -12,6 +12,7 @@ import (
 	session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
@@ -20,7 +21,7 @@ import (
 func makeRelationshipFingerprint(t session2.RelationshipType, grp *cyclic.Group,
 	myPrivKey, partnerPubKey *cyclic.Int, me, partner *id.ID) []byte {
 
-	myPubKey := grp.ExpG(myPrivKey, grp.NewIntFromUInt(1))
+	myPubKey := diffieHellman.GeneratePublicKey(myPrivKey, grp)
 
 	switch t {
 	case session2.Send:
diff --git a/single/request.go b/single/request.go
index 1a49628653915c373fb6d7b59e632a7375eebfbc..08e78c6effd39046fada90042fd04efd8472855a 100644
--- a/single/request.go
+++ b/single/request.go
@@ -11,6 +11,7 @@ import (
 	"gitlab.com/elixxir/client/single/message"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/e2e/auth"
 	"gitlab.com/elixxir/crypto/e2e/singleUse"
 	"gitlab.com/xx_network/crypto/csprng"
@@ -271,7 +272,7 @@ func generateDhKeys(grp *cyclic.Group, dhPubKey *cyclic.Int, rng io.Reader) (
 	privKey := grp.NewIntFromBytes(privKeyBytes)
 
 	// Generate public key and DH key
-	publicKey = grp.ExpG(privKey, grp.NewInt(1))
+	publicKey = diffieHellman.GeneratePublicKey(privKey, grp)
 	dhKey = grp.Exp(dhPubKey, privKey, grp.NewInt(1))
 
 	return dhKey, publicKey, nil
diff --git a/storage/session.go b/storage/session.go
index 89836d53ebf70a88a006e007e76c940927f7c9b1..1925d453bf8066b22921958c35519842340b5eb9 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -10,6 +10,8 @@
 package storage
 
 import (
+	"gitlab.com/elixxir/crypto/diffieHellman"
+	"math/rand"
 	"sync"
 	"testing"
 	"time"
@@ -30,13 +32,11 @@ import (
 	"gitlab.com/xx_network/primitives/ndf"
 )
 
-// Number of rounds to store in the CheckedRound buffer
-const CheckRoundsMaxSize = 1000000 / 64
 const currentSessionVersion = 0
 const cmixGroupKey = "cmixGroup"
 const e2eGroupKey = "e2eGroup"
 
-// Session object, backed by encrypted filestore
+// Session object, backed by encrypted versioned.KVc
 type Session interface {
 	GetClientVersion() version.Version
 	Get(key string) (*versioned.Object, error)
@@ -86,7 +86,7 @@ type session struct {
 	clientVersion *clientVersion.Store
 }
 
-// Initialize a new Session object
+// initStore initializes a new Session object
 func initStore(baseDir, password string) (*session, error) {
 	fs, err := ekv.NewFilestore(baseDir, password)
 	var s *session
@@ -102,7 +102,7 @@ func initStore(baseDir, password string) (*session, error) {
 	return s, nil
 }
 
-// Creates new UserData in the session
+// New UserData in the session
 func New(baseDir, password string, u user.Info,
 	currentVersion version.Version,
 	cmixGrp, e2eGrp *cyclic.Group) (Session, error) {
@@ -119,7 +119,7 @@ func New(baseDir, password string, u user.Info,
 	}
 
 	s.User, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt,
-		u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned)
+		u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned, u.E2eDhPrivateKey, u.E2eDhPublicKey)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to create user")
 	}
@@ -139,7 +139,7 @@ func New(baseDir, password string, u user.Info,
 	return s, nil
 }
 
-// Loads existing user data into the session
+// Load existing user data into the session
 func Load(baseDir, password string, currentVersion version.Version) (Session, error) {
 
 	s, err := initStore(baseDir, password)
@@ -196,7 +196,7 @@ func (s *session) Set(key string, object *versioned.Object) error {
 	return s.kv.Set(key, currentSessionVersion, object)
 }
 
-// delete a value in the session
+// Delete a value in the session
 func (s *session) Delete(key string) error {
 	return s.kv.Delete(key, currentSessionVersion)
 }
@@ -206,17 +206,17 @@ func (s *session) GetKV() *versioned.KV {
 	return s.kv
 }
 
-// GetCmixGrouo returns cMix Group
+// GetCmixGroup returns cMix Group
 func (s *session) GetCmixGroup() *cyclic.Group {
 	return s.cmixGroup
 }
 
-// GetE2EGrouo returns cMix Group
+// GetE2EGroup returns cMix Group
 func (s *session) GetE2EGroup() *cyclic.Group {
 	return s.e2eGroup
 }
 
-// Initializes a Session object wrapped around a MemStore object.
+// InitTestingSession object wrapped around a MemStore object.
 // FOR TESTING ONLY
 func InitTestingSession(i interface{}) Session {
 	switch i.(type) {
@@ -230,7 +230,14 @@ func InitTestingSession(i interface{}) Session {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	s := &session{kv: kv}
 	uid := id.NewIdFromString("zezima", id.User, i)
-	u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false, dhPrivKey, dhPubKey)
 	if err != nil {
 		jww.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err)
 	}
diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go
index fd4b73047008f6f0f78ad9a2f1b067372932aae6..8c245fc70ac257dc9eef14d9848be007c7831343 100644
--- a/storage/user/cryptographic.go
+++ b/storage/user/cryptographic.go
@@ -10,15 +10,19 @@ package user
 import (
 	"bytes"
 	"encoding/gob"
+	"encoding/json"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/storage/utility"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
 )
 
-const currentCryptographicIdentityVersion = 0
+const originalCryptographicIdentityVersion = 0
+const currentCryptographicIdentityVersion = 1
 const cryptographicIdentityKey = "cryptographicIdentity"
 
 type CryptographicIdentity struct {
@@ -29,6 +33,8 @@ type CryptographicIdentity struct {
 	receptionSalt      []byte
 	receptionRsaKey    *rsa.PrivateKey
 	isPrecanned        bool
+	e2eDhPrivateKey    *cyclic.Int
+	e2eDhPublicKey     *cyclic.Int
 }
 
 type ciDisk struct {
@@ -41,10 +47,23 @@ type ciDisk struct {
 	IsPrecanned        bool
 }
 
+type ciDiskV1 struct {
+	TransmissionID     *id.ID
+	TransmissionSalt   []byte
+	TransmissionRsaKey *rsa.PrivateKey
+	ReceptionID        *id.ID
+	ReceptionSalt      []byte
+	ReceptionRsaKey    *rsa.PrivateKey
+	IsPrecanned        bool
+	E2eDhPrivateKey    []byte
+	E2eDhPublicKey     []byte
+}
+
 func newCryptographicIdentity(transmissionID, receptionID *id.ID,
 	transmissionSalt, receptionSalt []byte,
 	transmissionRsa, receptionRsa *rsa.PrivateKey,
-	isPrecanned bool, kv *versioned.KV) *CryptographicIdentity {
+	isPrecanned bool, e2eDhPrivateKey, e2eDhPublicKey *cyclic.Int,
+	kv *versioned.KV) *CryptographicIdentity {
 
 	ci := &CryptographicIdentity{
 		transmissionID:     transmissionID,
@@ -54,6 +73,8 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID,
 		receptionSalt:      receptionSalt,
 		receptionRsaKey:    receptionRsa,
 		isPrecanned:        isPrecanned,
+		e2eDhPrivateKey:    e2eDhPrivateKey,
+		e2eDhPublicKey:     e2eDhPublicKey,
 	}
 
 	if err := ci.save(kv); err != nil {
@@ -64,39 +85,115 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID,
 	return ci
 }
 
-func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
-	obj, err := kv.Get(cryptographicIdentityKey,
-		currentCryptographicIdentityVersion)
+// loadOriginalCryptographicIdentity attempts to load the originalCryptographicIdentityVersion CryptographicIdentity
+func loadOriginalCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
+	result := &CryptographicIdentity{}
+	obj, err := kv.Get(cryptographicIdentityKey, originalCryptographicIdentityVersion)
 	if err != nil {
-		return nil, errors.WithMessage(err, "Failed to get user "+
-			"cryptographic identity from EKV")
+		return nil, errors.WithMessagef(err, "Failed to get version %d user "+
+			"cryptographic identity from EKV", originalCryptographicIdentityVersion)
 	}
-
 	var resultBuffer bytes.Buffer
-	result := &CryptographicIdentity{}
 	decodable := &ciDisk{}
 
 	resultBuffer.Write(obj.Data)
 	dec := gob.NewDecoder(&resultBuffer)
 	err = dec.Decode(decodable)
+	if err != nil {
+		return nil, err
+	}
 
-	if decodable != nil {
-		result.isPrecanned = decodable.IsPrecanned
-		result.receptionRsaKey = decodable.ReceptionRsaKey
-		result.transmissionRsaKey = decodable.TransmissionRsaKey
-		result.transmissionSalt = decodable.TransmissionSalt
-		result.transmissionID = decodable.TransmissionID
-		result.receptionID = decodable.ReceptionID
-		result.receptionSalt = decodable.ReceptionSalt
+	result.isPrecanned = decodable.IsPrecanned
+	result.receptionRsaKey = decodable.ReceptionRsaKey
+	result.transmissionRsaKey = decodable.TransmissionRsaKey
+	result.transmissionSalt = decodable.TransmissionSalt
+	result.transmissionID = decodable.TransmissionID
+	result.receptionID = decodable.ReceptionID
+	result.receptionSalt = decodable.ReceptionSalt
+	return result, nil
+}
+
+func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
+	result := &CryptographicIdentity{}
+	obj, err := kv.Get(cryptographicIdentityKey,
+		currentCryptographicIdentityVersion)
+	if err != nil {
+		result, err = loadOriginalCryptographicIdentity(kv)
+		if err != nil {
+			return nil, err
+		}
+		jww.WARN.Printf("Attempting to migrate cryptographic identity to new version...")
+		// Populate E2E keys from legacy storage
+		result.e2eDhPublicKey, result.e2eDhPrivateKey = loadLegacyDHKeys(kv)
+		// Migrate to the new version in storage
+		return result, result.save(kv)
+	}
+
+	decodable := &ciDiskV1{}
+	err = json.Unmarshal(obj.Data, decodable)
+	if err != nil {
+		return nil, err
 	}
 
-	return result, err
+	result.isPrecanned = decodable.IsPrecanned
+	result.receptionRsaKey = decodable.ReceptionRsaKey
+	result.transmissionRsaKey = decodable.TransmissionRsaKey
+	result.transmissionSalt = decodable.TransmissionSalt
+	result.transmissionID = decodable.TransmissionID
+	result.receptionID = decodable.ReceptionID
+	result.receptionSalt = decodable.ReceptionSalt
+
+	result.e2eDhPrivateKey = &cyclic.Int{}
+	err = result.e2eDhPrivateKey.UnmarshalJSON(decodable.E2eDhPrivateKey)
+	if err != nil {
+		return nil, err
+	}
+	result.e2eDhPublicKey = &cyclic.Int{}
+	err = result.e2eDhPublicKey.UnmarshalJSON(decodable.E2eDhPublicKey)
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+// loadLegacyDHKeys attempts to load DH Keys from legacy storage. It
+// prints a warning to the log as users should be using ReceptionIdentity
+// instead of PortableUserInfo
+func loadLegacyDHKeys(kv *versioned.KV) (pub, priv *cyclic.Int) {
+	// Legacy package prefixes and keys, see e2e/ratchet/storage.go
+	packagePrefix := "e2eSession"
+	pubKeyKey := "DhPubKey"
+	privKeyKey := "DhPrivKey"
+
+	kvPrefix := kv.Prefix(packagePrefix)
+
+	privKey, err := utility.LoadCyclicKey(kvPrefix, privKeyKey)
+	if err != nil {
+		jww.ERROR.Printf("Failed to load e2e DH private key: %v", err)
+		return nil, nil
+	}
+
+	pubKey, err := utility.LoadCyclicKey(kvPrefix, pubKeyKey)
+	if err != nil {
+		jww.ERROR.Printf("Failed to load e2e DH public key: %v", err)
+		return nil, nil
+	}
+
+	return pubKey, privKey
 }
 
 func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
-	var userDataBuffer bytes.Buffer
+	dhPriv, err := ci.e2eDhPrivateKey.MarshalJSON()
+	if err != nil {
+		return err
+	}
+	dhPub, err := ci.e2eDhPublicKey.MarshalJSON()
+	if err != nil {
+		return err
+	}
 
-	encodable := &ciDisk{
+	encodable := &ciDiskV1{
 		TransmissionID:     ci.transmissionID,
 		TransmissionSalt:   ci.transmissionSalt,
 		TransmissionRsaKey: ci.transmissionRsaKey,
@@ -104,10 +201,11 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
 		ReceptionSalt:      ci.receptionSalt,
 		ReceptionRsaKey:    ci.receptionRsaKey,
 		IsPrecanned:        ci.isPrecanned,
+		E2eDhPrivateKey:    dhPriv,
+		E2eDhPublicKey:     dhPub,
 	}
 
-	enc := gob.NewEncoder(&userDataBuffer)
-	err := enc.Encode(encodable)
+	enc, err := json.Marshal(&encodable)
 	if err != nil {
 		return err
 	}
@@ -115,7 +213,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
 	obj := &versioned.Object{
 		Version:   currentCryptographicIdentityVersion,
 		Timestamp: netTime.Now(),
-		Data:      userDataBuffer.Bytes(),
+		Data:      enc,
 	}
 
 	return kv.Set(cryptographicIdentityKey,
@@ -149,3 +247,11 @@ func (ci *CryptographicIdentity) GetTransmissionRSA() *rsa.PrivateKey {
 func (ci *CryptographicIdentity) IsPrecanned() bool {
 	return ci.isPrecanned
 }
+
+func (ci *CryptographicIdentity) GetE2eDhPublicKey() *cyclic.Int {
+	return ci.e2eDhPublicKey.DeepCopy()
+}
+
+func (ci *CryptographicIdentity) GetE2eDhPrivateKey() *cyclic.Int {
+	return ci.e2eDhPrivateKey.DeepCopy()
+}
diff --git a/storage/user/cryptographic_test.go b/storage/user/cryptographic_test.go
index 1096ccf683e288ae99577bc14989ab3fd71af599..0b9f92d9525600ad66c7746dbda12fa06fc6a318 100644
--- a/storage/user/cryptographic_test.go
+++ b/storage/user/cryptographic_test.go
@@ -11,7 +11,10 @@ import (
 	"bytes"
 	"crypto/rand"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"testing"
@@ -22,11 +25,19 @@ func TestNewCryptographicIdentity(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("zezima", id.User, t)
 	salt := []byte("salt")
-	_ = newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
 
-	_, err := kv.Get(cryptographicIdentityKey, 0)
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	_ = newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
+
+	_, err := kv.Get(cryptographicIdentityKey, currentCryptographicIdentityVersion)
 	if err != nil {
-		t.Errorf("Did not store cryptographic identity")
+		t.Errorf("Did not store cryptographic identity: %+v", err)
 	}
 }
 
@@ -35,7 +46,15 @@ func TestLoadCryptographicIdentity(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("zezima", id.User, t)
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 
 	err := ci.save(kv)
 	if err != nil {
@@ -64,7 +83,15 @@ func TestCryptographicIdentity_GetReceptionRSA(t *testing.T) {
 		t.Errorf("Failed to generate pk2")
 	}
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(
+		uid, uid, salt, salt, pk1, pk2, false, dhPrivKey, dhPubKey, kv)
 	if ci.GetReceptionRSA().D != pk2.D {
 		t.Errorf("Did not receive expected RSA key.  Expected: %+v, Received: %+v", pk2, ci.GetReceptionRSA())
 	}
@@ -83,7 +110,15 @@ func TestCryptographicIdentity_GetTransmissionRSA(t *testing.T) {
 		t.Errorf("Failed to generate pk2")
 	}
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(
+		uid, uid, salt, salt, pk1, pk2, false, dhPrivKey, dhPubKey, kv)
 	if ci.GetTransmissionRSA().D != pk1.D {
 		t.Errorf("Did not receive expected RSA key.  Expected: %+v, Received: %+v", pk1, ci.GetTransmissionRSA())
 	}
@@ -95,7 +130,15 @@ func TestCryptographicIdentity_GetTransmissionSalt(t *testing.T) {
 	uid := id.NewIdFromString("zezima", id.User, t)
 	ts := []byte("transmission salt")
 	rs := []byte("reception salt")
-	ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 	if bytes.Compare(ci.GetTransmissionSalt(), ts) != 0 {
 		t.Errorf("Did not get expected salt.  Expected: %+v, Received: %+v", ts, ci.GetTransmissionSalt())
 	}
@@ -107,7 +150,15 @@ func TestCryptographicIdentity_GetReceptionSalt(t *testing.T) {
 	uid := id.NewIdFromString("zezima", id.User, t)
 	ts := []byte("transmission salt")
 	rs := []byte("reception salt")
-	ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 	if bytes.Compare(ci.GetReceptionSalt(), rs) != 0 {
 		t.Errorf("Did not get expected salt.  Expected: %+v, Received: %+v", rs, ci.GetReceptionSalt())
 	}
@@ -119,7 +170,14 @@ func TestCryptographicIdentity_GetTransmissionID(t *testing.T) {
 	rid := id.NewIdFromString("zezima", id.User, t)
 	tid := id.NewIdFromString("jakexx360", id.User, t)
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 	if !ci.GetTransmissionID().Cmp(tid) {
 		t.Errorf("Did not receive expected user ID.  Expected: %+v, Received: %+v", tid, ci.GetTransmissionID())
 	}
@@ -131,7 +189,14 @@ func TestCryptographicIdentity_GetReceptionID(t *testing.T) {
 	rid := id.NewIdFromString("zezima", id.User, t)
 	tid := id.NewIdFromString("jakexx360", id.User, t)
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 	if !ci.GetReceptionID().Cmp(rid) {
 		t.Errorf("Did not receive expected user ID.  Expected: %+v, Received: %+v", rid, ci.GetReceptionID())
 	}
@@ -142,7 +207,14 @@ func TestCryptographicIdentity_IsPrecanned(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("zezima", id.User, t)
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, true, kv)
+
+	prng := rand.Reader
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, true, dhPrivKey, dhPubKey, kv)
 	if !ci.IsPrecanned() {
 		t.Error("I really don't know how this could happen")
 	}
diff --git a/storage/user/info.go b/storage/user/info.go
index 3da77bb13935d863e382e26ad55aa529f1b63b6b..fc272cb0fe134b767e399b4bb9fca2a8cd3411e4 100644
--- a/storage/user/info.go
+++ b/storage/user/info.go
@@ -94,10 +94,8 @@ func (u *User) PortableUserInfo() Info {
 		ReceptionSalt:         copySlice(ci.GetReceptionSalt()),
 		ReceptionRSA:          ci.GetReceptionRSA(),
 		Precanned:             ci.IsPrecanned(),
-		//fixme: set these in the e2e layer, the command line layer
-		//needs more logical separation so this can be removed
-		E2eDhPrivateKey: nil,
-		E2eDhPublicKey:  nil,
+		E2eDhPrivateKey:       ci.GetE2eDhPrivateKey(),
+		E2eDhPublicKey:        ci.GetE2eDhPublicKey(),
 	}
 
 }
diff --git a/storage/user/registation_test.go b/storage/user/registation_test.go
index cec369ea41ca74c63ea972e3455a4b577ebcd464..346e662758223a755e13c5e19186002ae6b9ec6f 100644
--- a/storage/user/registation_test.go
+++ b/storage/user/registation_test.go
@@ -11,10 +11,14 @@ import (
 	"bytes"
 	"encoding/binary"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
+	"math/rand"
 	"testing"
 	"time"
 )
@@ -24,7 +28,15 @@ func TestUser_GetRegistrationValidationSignature(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -59,7 +71,15 @@ func TestUser_SetRegistrationValidationSignature(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -102,7 +122,15 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -145,7 +173,15 @@ func TestUser_GetRegistrationTimestamp(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -194,7 +230,15 @@ func TestUser_loadRegistrationTimestamp(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
diff --git a/storage/user/user.go b/storage/user/user.go
index e79abf3300c039ab8f097672bc6e62ca8a47f286..5b84321a97cc169df474ab2ebd602bfb2769c0b1 100644
--- a/storage/user/user.go
+++ b/storage/user/user.go
@@ -10,6 +10,7 @@ package user
 import (
 	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
@@ -33,9 +34,11 @@ type User struct {
 
 // builds a new user.
 func NewUser(kv *versioned.KV, transmissionID, receptionID *id.ID, transmissionSalt,
-	receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool) (*User, error) {
+	receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool,
+	e2eDhPrivateKey, e2eDhPublicKey *cyclic.Int) (*User, error) {
 
-	ci := newCryptographicIdentity(transmissionID, receptionID, transmissionSalt, receptionSalt, transmissionRsa, receptionRsa, isPrecanned, kv)
+	ci := newCryptographicIdentity(transmissionID, receptionID, transmissionSalt,
+		receptionSalt, transmissionRsa, receptionRsa, isPrecanned, e2eDhPrivateKey, e2eDhPublicKey, kv)
 
 	return &User{CryptographicIdentity: ci, kv: kv}, nil
 }
diff --git a/storage/user/user_test.go b/storage/user/user_test.go
index 01a93088c1e54c7d2b6d03a6d5a6a1cb0cfb8803..9198e48f607e3c25d79d74242f7607819a83efd1 100644
--- a/storage/user/user_test.go
+++ b/storage/user/user_test.go
@@ -9,9 +9,13 @@ package user
 
 import (
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
+	"math/rand"
 	"testing"
 )
 
@@ -26,7 +30,15 @@ func TestLoadUser(t *testing.T) {
 
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv)
 	err = ci.save(kv)
 	if err != nil {
 		t.Errorf("Failed to save ci to kv: %+v", err)
@@ -43,7 +55,15 @@ func TestNewUser(t *testing.T) {
 	kv := versioned.NewKV(ekv.MakeMemstore())
 	uid := id.NewIdFromString("test", id.User, t)
 	salt := []byte("salt")
-	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
diff --git a/storage/user/username_test.go b/storage/user/username_test.go
index f4a851145b8296bdab49b07bb6996d51344dc2ae..a52b20ac003d692c38ba632299354bb8ce698faf 100644
--- a/storage/user/username_test.go
+++ b/storage/user/username_test.go
@@ -9,10 +9,14 @@ package user
 
 import (
 	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
+	"math/rand"
 	"testing"
 )
 
@@ -23,7 +27,15 @@ func TestUser_SetUsername(t *testing.T) {
 	rid := id.NewIdFromString("recv", id.User, t)
 	tsalt := []byte("tsalt")
 	rsalt := []byte("rsalt")
-	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -57,7 +69,15 @@ func TestUser_GetUsername(t *testing.T) {
 	rid := id.NewIdFromString("recv", id.User, t)
 	tsalt := []byte("tsalt")
 	rsalt := []byte("rsalt")
-	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
@@ -85,7 +105,15 @@ func TestUser_loadUsername(t *testing.T) {
 	rid := id.NewIdFromString("recv", id.User, t)
 	tsalt := []byte("tsalt")
 	rsalt := []byte("rsalt")
-	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false)
+
+	prng := rand.New(rand.NewSource(42))
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(
+		diffieHellman.DefaultPrivateKeyLength, grp, prng)
+	dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp)
+
+	u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{},
+		&rsa.PrivateKey{}, false, dhPrivKey, dhPubKey)
 	if err != nil || u == nil {
 		t.Errorf("Failed to create new user: %+v", err)
 	}
diff --git a/ud/register.go b/ud/register.go
index 591a1cf1fd218c9afc9b84af5d53c4300505914e..07c7fcdb942b2f96726af26a5e1deeac92fc2278 100644
--- a/ud/register.go
+++ b/ud/register.go
@@ -3,6 +3,7 @@ package ud
 import (
 	"github.com/pkg/errors"
 	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/factID"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/primitives/fact"
@@ -30,7 +31,7 @@ func (m *Manager) register(username string, rng csprng.Source,
 	if err != nil {
 		return err
 	}
-	dhKeyPub := grp.ExpG(dhKeyPriv, grp.NewInt(1))
+	dhKeyPub := diffieHellman.GeneratePublicKey(dhKeyPriv, grp)
 
 	// Construct the user registration message
 	msg := &pb.UDBUserRegistration{
diff --git a/xxdk/cmix.go b/xxdk/cmix.go
index f2904335b283f5fd5327c7e69bc0bd34120d7502..64f08e03ab2ae6bffbc6e45c8418681a17fc3b17 100644
--- a/xxdk/cmix.go
+++ b/xxdk/cmix.go
@@ -78,12 +78,12 @@ func NewCmix(ndfJSON, storageDir string, password []byte,
 
 	cmixGrp, e2eGrp := DecodeGroups(def)
 	start := netTime.Now()
-	protoUser := createNewUser(rngStreamGen)
+	userInfo := createNewUser(rngStreamGen, e2eGrp)
 	jww.DEBUG.Printf("PortableUserInfo generation took: %s",
 		netTime.Now().Sub(start))
 
 	_, err = CheckVersionAndSetupStorage(def, storageDir, password,
-		protoUser, cmixGrp, e2eGrp, registrationCode)
+		userInfo, cmixGrp, e2eGrp, registrationCode)
 	return err
 }
 
@@ -106,8 +106,7 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte,
 	}
 	cmixGrp, e2eGrp := DecodeGroups(def)
 
-	userInfo := createNewVanityUser(rngStream, cmixGrp, e2eGrp,
-		userIdPrefix)
+	userInfo := createNewVanityUser(rngStream, e2eGrp, userIdPrefix)
 
 	_, err = CheckVersionAndSetupStorage(def, storageDir, password,
 		userInfo, cmixGrp, e2eGrp, registrationCode)
@@ -162,28 +161,21 @@ func OpenCmix(storageDir string, password []byte) (*Cmix, error) {
 // predefined cryptographic which defines a user. This is designed for some
 // specific deployment procedures and is generally unsafe.
 func NewProtoClient_Unsafe(ndfJSON, storageDir string, password []byte,
-	protoUser *user.Proto) (ReceptionIdentity, error) {
+	protoUser *user.Proto) error {
 	jww.INFO.Printf("NewProtoClient_Unsafe")
 
 	usr := user.NewUserFromProto(protoUser)
 
 	def, err := ParseNDF(ndfJSON)
 	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 
 	cmixGrp, e2eGrp := DecodeGroups(def)
-
 	storageSess, err := CheckVersionAndSetupStorage(def, storageDir,
 		password, usr, cmixGrp, e2eGrp, protoUser.RegCode)
 	if err != nil {
-		return ReceptionIdentity{}, err
-	}
-
-	identity, err := buildReceptionIdentity(protoUser.ReceptionID, protoUser.ReceptionSalt,
-		protoUser.ReceptionRSA, e2eGrp, protoUser.E2eDhPrivateKey)
-	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 
 	storageSess.SetReceptionRegistrationValidationSignature(
@@ -197,10 +189,10 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password []byte,
 	err = storageSess.ForwardRegistrationStatus(
 		storage.PermissioningComplete)
 	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 
-	return identity, nil
+	return nil
 }
 
 // LoadCmix initializes a Cmix object from existing storage and starts the network
@@ -569,7 +561,7 @@ func DecodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) {
 // NewPrecannedClient and NewVanityClient it checks client version and
 // creates a new storage for user data
 func CheckVersionAndSetupStorage(def *ndf.NetworkDefinition,
-	storageDir string, password []byte, protoUser user.Info,
+	storageDir string, password []byte, userInfo user.Info,
 	cmixGrp, e2eGrp *cyclic.Group, registrationCode string) (
 	storage.Session, error) {
 	// get current client version
@@ -581,7 +573,7 @@ func CheckVersionAndSetupStorage(def *ndf.NetworkDefinition,
 
 	// Create Storage
 	passwordStr := string(password)
-	storageSess, err := storage.New(storageDir, passwordStr, protoUser,
+	storageSess, err := storage.New(storageDir, passwordStr, userInfo,
 		currentVersion, cmixGrp, e2eGrp)
 	if err != nil {
 		return nil, err
diff --git a/xxdk/e2e.go b/xxdk/e2e.go
index 098657f9c4e2e0ad4c15e3ce797c4457d1888540..2fe5fdf87ed43b2b90be8dc7b1286cb19262e067 100644
--- a/xxdk/e2e.go
+++ b/xxdk/e2e.go
@@ -7,7 +7,6 @@
 package xxdk
 
 import (
-	"encoding/binary"
 	"encoding/json"
 	"time"
 
@@ -21,8 +20,6 @@ import (
 	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/crypto/xx"
 	"gitlab.com/xx_network/primitives/id"
@@ -42,143 +39,80 @@ type E2e struct {
 // that allows for initializing an E2e object without an E2e-dependant auth.Callbacks
 type AuthCallbacks interface {
 	Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
-		round rounds.Round, e2e *E2e)
+		round rounds.Round, messenger *E2e)
 	Confirm(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
-		round rounds.Round, e2e *E2e)
+		round rounds.Round, messenger *E2e)
 	Reset(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
-		round rounds.Round, e2e *E2e)
+		round rounds.Round, messenger *E2e)
 }
 
 // Login creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
 // It bundles a Cmix object with a ReceptionIdentity object
 // and initializes the auth.State and e2e.Handler objects
-func Login(client *Cmix, callbacks AuthCallbacks,
+func Login(net *Cmix, callbacks AuthCallbacks,
 	identity ReceptionIdentity, params E2EParams) (m *E2e, err error) {
-	return login(client, callbacks, identity, client.GetStorage().GetKV(),
-		params)
+
+	// If the given identity matches the stored ReceptionID,
+	// then we are using a legacy ReceptionIdentity
+	defaultReceptionId := net.GetStorage().PortableUserInfo().ReceptionID
+	if identity.ID.Cmp(defaultReceptionId) {
+		return loginLegacy(net, callbacks, identity, params)
+	}
+
+	// Otherwise, we are using a modern ReceptionIdentity
+	return login(net, callbacks, identity, net.GetStorage().GetKV(), params)
 }
 
 // LoginEphemeral creates a new E2e backed by a totally ephemeral versioned.KV
-func LoginEphemeral(client *Cmix, callbacks AuthCallbacks,
+func LoginEphemeral(net *Cmix, callbacks AuthCallbacks,
 	identity ReceptionIdentity, params E2EParams) (m *E2e, err error) {
-	return login(client, callbacks, identity,
+	return login(net, callbacks, identity,
 		versioned.NewKV(ekv.MakeMemstore()), params)
 }
 
-// LoginLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
+// 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, params E2EParams, callbacks AuthCallbacks) (
+func loginLegacy(net *Cmix, callbacks AuthCallbacks,
+	identity ReceptionIdentity, params E2EParams) (
 	m *E2e, err error) {
 	m = &E2e{
-		Cmix:   client,
+		Cmix:   net,
 		backup: &Container{},
 	}
 
-	m.e2e, err = loadOrInitE2eLegacy(client)
+	m.e2e, err = loadOrInitE2eLegacy(identity, net)
 	if err != nil {
 		return nil, err
 	}
+	net.GetCmix().AddIdentity(identity.ID, time.Time{}, true)
 
-	userInfo := client.GetStorage().PortableUserInfo()
-	client.GetCmix().AddIdentity(userInfo.ReceptionID, time.Time{}, true)
-
-	err = client.AddService(m.e2e.StartProcesses)
+	err = net.AddService(m.e2e.StartProcesses)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to add "+
 			"the e2e processies")
 	}
 
-	m.auth, err = auth.NewState(client.GetStorage().GetKV(), client.GetCmix(),
-		m.e2e, client.GetRng(), client.GetEventReporter(), params.Auth,
+	m.auth, err = auth.NewState(net.GetStorage().GetKV(), net.GetCmix(),
+		m.e2e, net.GetRng(), net.GetEventReporter(), params.Auth,
 		params.Session, MakeAuthCallbacksAdapter(callbacks, m),
 		m.backup.TriggerBackup)
 	if err != nil {
 		return nil, err
 	}
 
-	m.e2eIdentity, err = buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt,
-		userInfo.ReceptionRSA, m.e2e.GetGroup(), m.e2e.GetHistoricalDHPrivkey())
-	return m, err
-}
-
-// LoginWithNewBaseNDF_UNSAFE initializes a client object from existing storage
-// 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, e2eParams E2EParams, cmixParams CMIXParams) (*E2e,
-	error) {
-	jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()")
-
-	def, err := ParseNDF(newBaseNdf)
-	if err != nil {
-		return nil, err
-	}
-
-	c, err := LoadCmix(storageDir, password, cmixParams)
-	if err != nil {
-		return nil, err
-	}
-
-	//store the updated base NDF
-	c.storage.SetNDF(def)
-
-	if def.Registration.Address != "" {
-		err = c.initPermissioning(def)
-		if err != nil {
-			return nil, err
-		}
-	} else {
-		jww.WARN.Printf("Registration with permissioning skipped due " +
-			"to blank permissionign address. Cmix will not be " +
-			"able to register or track network.")
-	}
-
-	return LoginLegacy(c, e2eParams, nil)
-}
-
-// LoginWithProtoClient creates a client object with a protoclient
-// JSON containing the cryptographic primitives. This is designed for
-// some specific deployment procedures and is generally unsafe.
-func LoginWithProtoClient(storageDir string, password []byte,
-	protoClientJSON []byte, newBaseNdf string, callbacks AuthCallbacks,
-	cmixParams CMIXParams, e2eParams E2EParams) (*E2e, error) {
-	jww.INFO.Printf("LoginWithProtoClient()")
-
-	def, err := ParseNDF(newBaseNdf)
-	if err != nil {
-		return nil, err
-	}
-
-	protoUser := &user.Proto{}
-	err = json.Unmarshal(protoClientJSON, protoUser)
-	if err != nil {
-		return nil, err
-	}
-
-	receptionIdentity, err := NewProtoClient_Unsafe(newBaseNdf, storageDir, password,
-		protoUser)
-	if err != nil {
-		return nil, err
-	}
-
-	c, err := LoadCmix(storageDir, password, cmixParams)
-	if err != nil {
-		return nil, err
-	}
-
-	c.storage.SetNDF(def)
-
-	err = c.initPermissioning(def)
+	rsaKey, err := identity.GetRSAPrivatePem()
 	if err != nil {
 		return nil, err
 	}
-	return Login(c, callbacks, receptionIdentity, e2eParams)
+	m.e2eIdentity, err = buildReceptionIdentity(identity.ID, identity.Salt,
+		rsaKey, m.e2e.GetGroup(), m.e2e.GetHistoricalDHPrivkey())
+	return m, err
 }
 
 // login creates a new xxdk.E2e backed by the given versioned.KV
-func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
+func login(net *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
 	kv *versioned.KV, params E2EParams) (m *E2e, err error) {
 
 	// Verify the passed-in ReceptionIdentity matches its properties
@@ -196,7 +130,7 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
 	}
 
 	m = &E2e{
-		Cmix:        client,
+		Cmix:        net,
 		backup:      &Container{},
 		e2eIdentity: identity,
 	}
@@ -206,10 +140,10 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
 	}
 
 	// load or init the new e2e storage
-	e2eGrp := client.GetStorage().GetE2EGroup()
+	e2eGrp := net.GetStorage().GetE2EGroup()
 	m.e2e, err = e2e.Load(kv,
-		client.GetCmix(), identity.ID, e2eGrp, client.GetRng(),
-		client.GetEventReporter())
+		net.GetCmix(), identity.ID, e2eGrp, net.GetRng(),
+		net.GetEventReporter())
 	if err != nil {
 		//initialize the e2e storage
 		err = e2e.Init(kv, identity.ID, dhPrivKey, e2eGrp,
@@ -220,29 +154,29 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
 
 		//load the new e2e storage
 		m.e2e, err = e2e.Load(kv,
-			client.GetCmix(), identity.ID, e2eGrp, client.GetRng(),
-			client.GetEventReporter())
+			net.GetCmix(), identity.ID, e2eGrp, net.GetRng(),
+			net.GetEventReporter())
 		if err != nil {
 			return nil, errors.WithMessage(err, "Failed to load a "+
 				"newly created e2e store")
 		}
 	}
 
-	err = client.AddService(m.e2e.StartProcesses)
+	err = net.AddService(m.e2e.StartProcesses)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to add "+
 			"the e2e processies")
 	}
 
-	m.auth, err = auth.NewState(kv, client.GetCmix(),
-		m.e2e, client.GetRng(), client.GetEventReporter(),
+	m.auth, err = auth.NewState(kv, net.GetCmix(),
+		m.e2e, net.GetRng(), net.GetEventReporter(),
 		params.Auth, params.Session,
 		MakeAuthCallbacksAdapter(callbacks, m), m.backup.TriggerBackup)
 	if err != nil {
 		return nil, err
 	}
 
-	client.network.AddIdentity(identity.ID, time.Time{}, true)
+	net.network.AddIdentity(identity.ID, time.Time{}, true)
 	jww.INFO.Printf("Client logged in: \n\tReceptionID: %s",
 		identity.ID)
 	return m, err
@@ -251,47 +185,29 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity,
 // loadOrInitE2eLegacy 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 loadOrInitE2eLegacy(client *Cmix) (e2e.Handler, error) {
-	usr := client.GetStorage().PortableUserInfo()
-	e2eGrp := client.GetStorage().GetE2EGroup()
-	kv := client.GetStorage().GetKV()
+func loadOrInitE2eLegacy(identity ReceptionIdentity, net *Cmix) (e2e.Handler, error) {
+	e2eGrp := net.GetStorage().GetE2EGroup()
+	kv := net.GetStorage().GetKV()
 
 	//try to load a legacy e2e handler
 	e2eHandler, err := e2e.LoadLegacy(kv,
-		client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
-		client.GetEventReporter(), rekey.GetDefaultParams())
+		net.GetCmix(), identity.ID, e2eGrp, net.GetRng(),
+		net.GetEventReporter(), rekey.GetDefaultParams())
 	if err != nil {
 		//if no legacy e2e handler exists, try to load a new one
 		e2eHandler, err = e2e.Load(kv,
-			client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
-			client.GetEventReporter())
+			net.GetCmix(), identity.ID, e2eGrp, net.GetRng(),
+			net.GetEventReporter())
 		if err != nil {
 			jww.WARN.Printf("Failed to load e2e instance for %s, "+
-				"creating a new one", usr.ReceptionID)
-
-			//generate the key
-			var privkey *cyclic.Int
-			if client.GetStorage().IsPrecanned() {
-				jww.WARN.Printf("Using Precanned DH key")
-				precannedID := binary.BigEndian.Uint64(
-					client.GetStorage().GetReceptionID()[:])
-				privkey = generatePrecanDHKeypair(
-					uint(precannedID),
-					client.GetStorage().GetE2EGroup())
-			} else if usr.E2eDhPrivateKey != nil {
-				jww.INFO.Printf("Using pre-existing DH key")
-				privkey = usr.E2eDhPrivateKey
-			} else {
-				jww.INFO.Printf("Generating new DH key")
-				rngStream := client.GetRng().GetStream()
-				privkey = diffieHellman.GeneratePrivateKey(
-					len(e2eGrp.GetPBytes()),
-					e2eGrp, rngStream)
-				rngStream.Close()
-			}
+				"creating a new one", identity.ID)
 
 			//initialize the e2e storage
-			err = e2e.Init(kv, usr.ReceptionID, privkey, e2eGrp,
+			privKey, err := identity.GetDHKeyPrivate()
+			if err != nil {
+				return nil, err
+			}
+			err = e2e.Init(kv, identity.ID, privKey, e2eGrp,
 				rekey.GetDefaultParams())
 			if err != nil {
 				return nil, err
@@ -299,19 +215,19 @@ func loadOrInitE2eLegacy(client *Cmix) (e2e.Handler, error) {
 
 			//load the new e2e storage
 			e2eHandler, err = e2e.Load(kv,
-				client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
-				client.GetEventReporter())
+				net.GetCmix(), identity.ID, e2eGrp, net.GetRng(),
+				net.GetEventReporter())
 			if err != nil {
 				return nil, errors.WithMessage(err, "Failed to load a "+
 					"newly created e2e store")
 			}
 		} else {
 			jww.INFO.Printf("Loaded a modern e2e instance for %s",
-				usr.ReceptionID)
+				identity.ID)
 		}
 	} else {
 		jww.INFO.Printf("Loaded a legacy e2e instance for %s",
-			usr.ReceptionID)
+			identity.ID)
 	}
 	return e2eHandler, nil
 }
diff --git a/xxdk/identity.go b/xxdk/identity.go
index ba4706b3489a20a09919c33b4808b59d34ed1d9b..8d4b392d8c79ea47fb39afa03f877542c8c2e0d0 100644
--- a/xxdk/identity.go
+++ b/xxdk/identity.go
@@ -8,6 +8,8 @@ package xxdk
 
 import (
 	"encoding/json"
+	"gitlab.com/elixxir/primitives/fact"
+
 	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/contact"
@@ -34,13 +36,13 @@ type ReceptionIdentity struct {
 // StoreReceptionIdentity stores the given identity in Cmix storage with the given key
 // This is the ideal way to securely store identities, as the caller of this function
 // is only required to store the given key separately rather than the keying material
-func StoreReceptionIdentity(key string, identity ReceptionIdentity, client *Cmix) error {
+func StoreReceptionIdentity(key string, identity ReceptionIdentity, net *Cmix) error {
 	marshalledIdentity, err := identity.Marshal()
 	if err != nil {
 		return err
 	}
 
-	return client.GetStorage().Set(key, &versioned.Object{
+	return net.GetStorage().Set(key, &versioned.Object{
 		Version:   idVersion,
 		Timestamp: netTime.Now(),
 		Data:      marshalledIdentity,
@@ -48,8 +50,8 @@ func StoreReceptionIdentity(key string, identity ReceptionIdentity, client *Cmix
 }
 
 // LoadReceptionIdentity loads the given identity in Cmix storage with the given key
-func LoadReceptionIdentity(key string, client *Cmix) (ReceptionIdentity, error) {
-	storageObj, err := client.GetStorage().Get(key)
+func LoadReceptionIdentity(key string, net *Cmix) (ReceptionIdentity, error) {
+	storageObj, err := net.GetStorage().Get(key)
 	if err != nil {
 		return ReceptionIdentity{}, err
 	}
@@ -89,10 +91,10 @@ func (r ReceptionIdentity) GetGroup() (*cyclic.Group, error) {
 
 // MakeReceptionIdentity generates a new cryptographic identity
 // for receiving messages.
-func MakeReceptionIdentity(client *Cmix) (ReceptionIdentity, error) {
-	rng := client.GetRng().GetStream()
+func MakeReceptionIdentity(net *Cmix) (ReceptionIdentity, error) {
+	rng := net.GetRng().GetStream()
 	defer rng.Close()
-	grp := client.GetStorage().GetE2EGroup()
+	grp := net.GetStorage().GetE2EGroup()
 
 	//make RSA Key
 	rsaKey, err := rsa.GenerateKey(rng,
@@ -140,6 +142,14 @@ func MakeReceptionIdentity(client *Cmix) (ReceptionIdentity, error) {
 	return I, nil
 }
 
+// MakeLegacyReceptionIdentity generates the cryptographic identity
+// for receiving messages based on the extant stored user.Info
+func MakeLegacyReceptionIdentity(net *Cmix) (ReceptionIdentity, error) {
+	userInfo := net.GetStorage().PortableUserInfo()
+	return buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt,
+		userInfo.ReceptionRSA, net.GetStorage().GetE2EGroup(), userInfo.E2eDhPrivateKey)
+}
+
 // DeepCopy produces a safe copy of a ReceptionIdentity
 func (r ReceptionIdentity) DeepCopy() ReceptionIdentity {
 	saltCopy := make([]byte, len(r.Salt))
@@ -164,12 +174,11 @@ func (r ReceptionIdentity) GetContact() contact.Contact {
 	grp, _ := r.GetGroup()
 	dhKeyPriv, _ := r.GetDHKeyPrivate()
 
-	dhPub := grp.ExpG(dhKeyPriv, grp.NewInt(1))
 	ct := contact.Contact{
 		ID:             r.ID,
-		DhPubKey:       dhPub,
+		DhPubKey:       diffieHellman.GeneratePublicKey(dhKeyPriv, grp),
 		OwnershipProof: nil,
-		Facts:          nil,
+		Facts:          make([]fact.Fact, 0),
 	}
 	return ct
 }
diff --git a/xxdk/precan.go b/xxdk/precan.go
index e0e008e85863ce52ee53926eac8e8f8c69518ac4..98edf51028937e17a0e555c7de1d91b60a3ff35b 100644
--- a/xxdk/precan.go
+++ b/xxdk/precan.go
@@ -9,60 +9,26 @@ package xxdk
 
 import (
 	"encoding/binary"
+	"math/rand"
+
 	"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) (ReceptionIdentity, error) {
+	password []byte) error {
 	jww.INFO.Printf("NewPrecannedClient()")
 	rngStreamGen := fastRNG.NewStreamGenerator(12, 1024,
 		csprng.NewSystemRNG)
@@ -70,51 +36,43 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string,
 
 	def, err := ParseNDF(defJSON)
 	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 	cmixGrp, e2eGrp := DecodeGroups(def)
 
-	dhPrivKey := generatePrecanDHKeypair(precannedID, e2eGrp)
-
-	userInfo := CreatePrecannedUser(precannedID, rngStream)
-	identity, err := buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt,
-		userInfo.ReceptionRSA, e2eGrp, dhPrivKey)
-	if err != nil {
-		return ReceptionIdentity{}, err
-	}
-
+	userInfo := createPrecannedUser(precannedID, rngStream, e2eGrp)
 	store, err := CheckVersionAndSetupStorage(def, storageDir, password,
 		userInfo, cmixGrp, e2eGrp, "")
 	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 
 	// Mark the precanned user as finished with permissioning and registered
 	// with the network.
 	err = store.ForwardRegistrationStatus(storage.PermissioningComplete)
 	if err != nil {
-		return ReceptionIdentity{}, err
+		return err
 	}
 
-	return identity, err
-}
-
-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
+	return err
 }
 
-// Create an insecure e2e relationship with a precanned user
+// MakePrecannedAuthenticatedChannel creates an insecure e2e relationship with a precanned user
 func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) (
 	contact.Contact, error) {
 
-	precan := m.MakePrecannedContact(precannedID)
+	rng := m.GetRng().GetStream()
+	precanUserInfo := createPrecannedUser(precannedID, rng, m.GetStorage().GetE2EGroup())
+	rng.Close()
+	precanRecipient, err := buildReceptionIdentity(precanUserInfo.ReceptionID,
+		precanUserInfo.ReceptionSalt, precanUserInfo.ReceptionRSA,
+		m.GetStorage().GetE2EGroup(), precanUserInfo.E2eDhPrivateKey)
+	if err != nil {
+		return contact.Contact{}, err
+	}
+	precanContact := precanRecipient.GetContact()
 
-	myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:])
+	myID := binary.BigEndian.Uint64(m.GetReceptionIdentity().ID[:])
 	// Pick a variant based on if their ID is bigger than mine.
 	myVariant := sidh.KeyVariantSidhA
 	theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB)
@@ -125,19 +83,25 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) (
 	prng1 := rand.New(rand.NewSource(int64(precannedID)))
 	theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant)
 	theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant)
-	theirSIDHPrivKey.Generate(prng1)
+	err = theirSIDHPrivKey.Generate(prng1)
+	if err != nil {
+		return contact.Contact{}, err
+	}
 	theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey)
 
 	prng2 := rand.New(rand.NewSource(int64(myID)))
 	mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant)
 	mySIDHPubKey := util.NewSIDHPublicKey(myVariant)
-	mySIDHPrivKey.Generate(prng2)
+	err = mySIDHPrivKey.Generate(prng2)
+	if err != nil {
+		return contact.Contact{}, err
+	}
 	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,
+	_, err = m.e2e.AddPartner(precanContact.ID, precanContact.DhPubKey,
 		m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey,
 		mySIDHPrivKey, sesParam, sesParam)
 
@@ -145,29 +109,5 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) (
 	// 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),
-	}
+	return precanContact, err
 }
diff --git a/xxdk/user.go b/xxdk/user.go
index 4eb421050ed68c242dff2b1f509d01b41c05cdc8..747fb3dbef16f64e0bb47cece6896b51477218da 100644
--- a/xxdk/user.go
+++ b/xxdk/user.go
@@ -8,6 +8,8 @@
 package xxdk
 
 import (
+	"encoding/binary"
+	"math/rand"
 	"regexp"
 	"runtime"
 	"strings"
@@ -31,13 +33,13 @@ const (
 )
 
 // createNewUser generates an identity for cMix
-func createNewUser(rng *fastRNG.StreamGenerator) user.Info {
+func createNewUser(rng *fastRNG.StreamGenerator, e2eGroup *cyclic.Group) user.Info {
 	// CMIX Keygen
 	var transmissionRsaKey, receptionRsaKey *rsa.PrivateKey
 	var transmissionSalt, receptionSalt []byte
 
-	transmissionSalt, receptionSalt,
-		transmissionRsaKey, receptionRsaKey = createKeys(rng)
+	e2eKeyBytes, transmissionSalt, receptionSalt,
+		transmissionRsaKey, receptionRsaKey := createKeys(rng, e2eGroup)
 
 	transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(),
 		transmissionSalt, id.User)
@@ -51,6 +53,7 @@ func createNewUser(rng *fastRNG.StreamGenerator) user.Info {
 		jww.FATAL.Panicf(err.Error())
 	}
 
+	dhPrivKey := e2eGroup.NewIntFromBytes(e2eKeyBytes)
 	return user.Info{
 		TransmissionID:   transmissionID.DeepCopy(),
 		TransmissionSalt: transmissionSalt,
@@ -59,29 +62,44 @@ func createNewUser(rng *fastRNG.StreamGenerator) user.Info {
 		ReceptionSalt:    receptionSalt,
 		ReceptionRSA:     receptionRsaKey,
 		Precanned:        false,
-		E2eDhPrivateKey:  nil,
-		E2eDhPublicKey:   nil,
+		E2eDhPrivateKey:  dhPrivKey,
+		E2eDhPublicKey:   diffieHellman.GeneratePublicKey(dhPrivKey, e2eGroup),
 	}
 }
 
-func createKeys(rng *fastRNG.StreamGenerator) (
+func createKeys(rng *fastRNG.StreamGenerator,
+	e2e *cyclic.Group) (e2eKeyBytes,
 	transmissionSalt, receptionSalt []byte,
 	transmissionRsaKey, receptionRsaKey *rsa.PrivateKey) {
 	wg := sync.WaitGroup{}
 
-	wg.Add(2)
+	wg.Add(3)
+
+	go func() {
+		defer wg.Done()
+		var err error
+		// DH Keygen
+		// FIXME: Why 256 bits? -- this is spec but not explained, it has
+		// to do with optimizing operations on one side and still preserves
+		// decent security -- cite this. Why valid for BOTH e2e and cmix?
+		stream := rng.GetStream()
+		e2eKeyBytes, err = csprng.GenerateInGroup(e2e.GetPBytes(), 256, stream)
+		stream.Close()
+		if err != nil {
+			jww.FATAL.Panicf(err.Error())
+		}
+	}()
 
 	// RSA Keygen (4096 bit defaults)
 	go func() {
 		defer wg.Done()
 		var err error
 		stream := rng.GetStream()
-		transmissionRsaKey, err = rsa.GenerateKey(stream,
-			rsa.DefaultRSABitLen)
+		transmissionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen)
 		if err != nil {
 			jww.FATAL.Panicf(err.Error())
 		}
-		transmissionSalt = make([]byte, 32)
+		transmissionSalt = make([]byte, SaltSize)
 		_, err = stream.Read(transmissionSalt)
 		stream.Close()
 		if err != nil {
@@ -93,12 +111,11 @@ func createKeys(rng *fastRNG.StreamGenerator) (
 		defer wg.Done()
 		var err error
 		stream := rng.GetStream()
-		receptionRsaKey, err = rsa.GenerateKey(stream,
-			rsa.DefaultRSABitLen)
+		receptionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen)
 		if err != nil {
 			jww.FATAL.Panicf(err.Error())
 		}
-		receptionSalt = make([]byte, 32)
+		receptionSalt = make([]byte, SaltSize)
 		_, err = stream.Read(receptionSalt)
 		stream.Close()
 		if err != nil {
@@ -107,28 +124,13 @@ func createKeys(rng *fastRNG.StreamGenerator) (
 	}()
 	wg.Wait()
 
-	isZero := func(data []byte) bool {
-		if len(data) == 0 {
-			return true
-		}
-		for i := len(data) - 1; i != 0; i-- {
-			if data[i] != 0 {
-				return false
-			}
-		}
-		return true
-	}
-
-	if isZero(receptionSalt) || isZero(transmissionSalt) {
-		jww.FATAL.Panicf("empty salt generation detected")
-	}
 	return
 
 }
 
 // createNewVanityUser generates an identity for cMix
 // The identity's ReceptionID is not random but starts with the supplied prefix
-func createNewVanityUser(rng csprng.Source, cmix,
+func createNewVanityUser(rng csprng.Source,
 	e2e *cyclic.Group, prefix string) user.Info {
 	// DH Keygen
 	prime := e2e.GetPBytes()
@@ -194,7 +196,7 @@ func createNewVanityUser(rng csprng.Source, cmix,
 			for {
 				select {
 				case <-done:
-					defer wg.Done()
+					wg.Done()
 					return
 				default:
 					n, err = csprng.NewSystemRNG().Read(
@@ -214,17 +216,17 @@ func createNewVanityUser(rng csprng.Source, cmix,
 					if err != nil {
 						jww.FATAL.Panicf(err.Error())
 					}
-					id := rID.String()
+					rid := rID.String()
 					if ignoreCase {
-						id = strings.ToLower(id)
+						rid = strings.ToLower(rid)
 					}
-					if strings.HasPrefix(id, pref) {
+					if strings.HasPrefix(rid, pref) {
 						mu.Lock()
 						receptionID = rID
 						receptionSalt = rSalt
 						mu.Unlock()
 						found <- true
-						defer wg.Done()
+						wg.Done()
 						return
 					}
 				}
@@ -248,3 +250,35 @@ func createNewVanityUser(rng csprng.Source, cmix,
 		E2eDhPublicKey:   diffieHellman.GeneratePublicKey(e2eKey, e2e),
 	}
 }
+
+// createPrecannedUser
+func createPrecannedUser(precannedID uint, rng csprng.Source, grp *cyclic.Group) 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())
+	}
+
+	prime := grp.GetPBytes()
+	keyLen := len(prime)
+	prng := rand.New(rand.NewSource(int64(precannedID)))
+	dhPrivKey := diffieHellman.GeneratePrivateKey(keyLen, grp, prng)
+	return user.Info{
+		TransmissionID:   &userID,
+		TransmissionSalt: salt,
+		ReceptionID:      &userID,
+		ReceptionSalt:    salt,
+		Precanned:        true,
+		E2eDhPrivateKey:  dhPrivKey,
+		E2eDhPublicKey:   diffieHellman.GeneratePublicKey(dhPrivKey, grp),
+		TransmissionRSA:  rsaKey,
+		ReceptionRSA:     rsaKey,
+	}
+}
diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go
index 0f8b6a565b0903fd8ea98b279610a0e307902383..0ec8e38c00b8b2a7693921f88651c633ad643525 100644
--- a/xxmutils/restoreContacts.go
+++ b/xxmutils/restoreContacts.go
@@ -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 *xxdk.E2e,
+func RestoreContactsFromBackup(backupPartnerIDs []byte, messenger *xxdk.E2e,
 	udManager *ud.Manager,
 	updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID,
 	[]error, error) {
@@ -63,7 +63,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e,
 	}
 
 	store := stateStore{
-		apiStore: client.GetStorage(),
+		apiStore: messenger.GetStorage(),
 	}
 
 	// Unmarshal IDs and then check restore state
@@ -99,8 +99,8 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e,
 	rsWg := &sync.WaitGroup{}
 	rsWg.Add(numRoutines)
 	for i := 0; i < numRoutines; i++ {
-		go LookupContacts(lookupCh, foundCh, failCh, client, udContact, lcWg)
-		go ResetSessions(resetContactCh, restoredCh, failCh, client,
+		go LookupContacts(lookupCh, foundCh, failCh, messenger, udContact, lcWg)
+		go ResetSessions(resetContactCh, restoredCh, failCh, messenger,
 			rsWg)
 	}
 
@@ -178,13 +178,13 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e,
 // 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 *xxdk.E2e, udContact contact.Contact,
+	failCh chan failure, messenger *xxdk.E2e, udContact contact.Contact,
 	wg *sync.WaitGroup) {
 	defer wg.Done()
 	// Start looking up contacts with user discovery and feed this
 	// contacts channel.
 	for lookupID := range in {
-		c, err := LookupContact(lookupID, client, udContact)
+		c, err := LookupContact(lookupID, messenger, udContact)
 		if err == nil {
 			out <- c
 			continue
@@ -205,10 +205,10 @@ 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 *xxdk.E2e, wg *sync.WaitGroup) {
+	messenger *xxdk.E2e, wg *sync.WaitGroup) {
 	defer wg.Done()
 	for c := range in {
-		_, err := client.GetAuth().Reset(*c)
+		_, err := messenger.GetAuth().Reset(*c)
 		if err == nil {
 			out <- c
 			continue
@@ -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 *xxdk.E2e, udContact contact.Contact) (
+func LookupContact(userID *id.ID, messenger *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
@@ -243,9 +243,9 @@ func LookupContact(userID *id.ID, client *xxdk.E2e, udContact contact.Contact) (
 	waiter.Lock()
 
 	// in MS, so 90 seconds
-	stream := client.GetRng().GetStream()
+	stream := messenger.GetRng().GetStream()
 	defer stream.Close()
-	_, _, err = ud.Lookup(client.GetCmix(), stream, client.GetE2E().GetGroup(),
+	_, _, err = ud.Lookup(messenger.GetCmix(), stream, messenger.GetE2E().GetGroup(),
 		udContact, lookupCB, userID, single.GetDefaultRequestParams())
 
 	// Now force a wait for callback to exit