diff --git a/api/client_test.go b/api/client_test.go
index 77045f9df4690366e527e9c84f31577ea66a1578..01dff2c7cc9aec25427124273f00a2f7f7706e4a 100644
--- a/api/client_test.go
+++ b/api/client_test.go
@@ -14,6 +14,7 @@ import (
 	"gitlab.com/elixxir/client/keyStore"
 	"gitlab.com/elixxir/client/parse"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/crypto/csprng"
 	"gitlab.com/elixxir/crypto/cyclic"
@@ -170,10 +171,10 @@ func TestRegisterUserE2E(t *testing.T) {
 	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
 	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
 
-	myUser := &storage.User{User: userID, Username: "test"}
+	myUser := &user2.User{User: userID, Username: "test"}
 	session := user.NewSession(testClient.storage, "password")
 
-	userData := &storage.UserData{
+	userData := &user2.UserData{
 		ThisUser:         myUser,
 		RSAPrivateKey:    privateKeyRSA,
 		RSAPublicKey:     &publicKeyRSA,
@@ -280,10 +281,10 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) {
 	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
 	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
 
-	myUser := &storage.User{User: userID, Username: "test"}
+	myUser := &user2.User{User: userID, Username: "test"}
 	session := user.NewSession(testClient.storage, "password")
 
-	userData := &storage.UserData{
+	userData := &user2.UserData{
 		ThisUser:         myUser,
 		RSAPrivateKey:    privateKeyRSA,
 		RSAPublicKey:     &publicKeyRSA,
diff --git a/api/mockserver_test.go b/api/mockserver_test.go
index 870c01c7c4d55a5a2dbac571b5b00a842df5f854..89cad54aee31423c4715015000a53cb0e91bafb5 100644
--- a/api/mockserver_test.go
+++ b/api/mockserver_test.go
@@ -12,6 +12,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/io"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/client/userRegistry"
 	"gitlab.com/elixxir/comms/gateway"
@@ -237,7 +238,7 @@ func TestRegister_InvalidRegState(t *testing.T) {
 	client.session = user.NewSession(nil, "password")
 	client.sessionV2, _ = storage.Init(".ekv-invalidregstate", "password")
 
-	userData := &storage.UserData{
+	userData := &user2.UserData{
 		ThisUser:         usr,
 		RSAPrivateKey:    privKey,
 		RSAPublicKey:     pubKey,
diff --git a/api/private.go b/api/private.go
index 6ce7a05264e324d1522ebf9083ea6778983957d9..78903ceff8f3e16bd4c9489a939e6160d9bbfb47 100644
--- a/api/private.go
+++ b/api/private.go
@@ -14,6 +14,7 @@ import (
 	"gitlab.com/elixxir/client/io"
 	"gitlab.com/elixxir/client/keyStore"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/client/userRegistry"
 	pb "gitlab.com/elixxir/comms/mixmessages"
@@ -33,10 +34,10 @@ const PermissioningAddrID = "Permissioning"
 
 // precannedRegister is a helper function for Register
 // It handles the precanned registration case
-func (cl *Client) precannedRegister(registrationCode string) (*storage.User, *id.ID, map[id.ID]user.NodeKeys, error) {
+func (cl *Client) precannedRegister(registrationCode string) (*user2.User, *id.ID, map[id.ID]user.NodeKeys, error) {
 	var successLook bool
 	var UID *id.ID
-	var u *storage.User
+	var u *user2.User
 	var err error
 
 	nk := make(map[id.ID]user.NodeKeys)
@@ -314,8 +315,8 @@ func (cl *Client) GenerateKeys(rsaPrivKey *rsa.PrivateKey,
 		return err
 	}
 
-	userData := &storage.UserData{
-		ThisUser: &storage.User{
+	userData := &user2.UserData{
+		ThisUser: &user2.User{
 			User:     usr.User,
 			Username: usr.Username,
 			Precan:   usr.Precan,
@@ -436,7 +437,7 @@ func generateE2eKeys(cmixGrp, e2eGrp *cyclic.Group) (e2ePrivateKey, e2ePublicKey
 //generateUserInformation serves as a helper function for RegisterUser.
 // It generates a salt s.t. it can create a user and their ID
 func generateUserInformation(publicKeyRSA *rsa.PublicKey) ([]byte, *id.ID,
-	*storage.User, error) {
+	*user2.User, error) {
 	//Generate salt for UserID
 	salt := make([]byte, SaltSize)
 	_, err := csprng.NewSystemRNG().Read(salt)
diff --git a/api/register_test.go b/api/register_test.go
index 34cabf70b5554532b12ca961561246775e1ad6eb..6fa3bddf001fdb8a520b208b28f5674587a158e7 100644
--- a/api/register_test.go
+++ b/api/register_test.go
@@ -7,7 +7,7 @@ package api
 
 import (
 	"gitlab.com/elixxir/client/io"
-	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/xx_network/primitives/id"
 	"testing"
@@ -87,7 +87,7 @@ func TestClient_Register(t *testing.T) {
 }
 
 //Verify the user from the session make in the registration above matches expected user
-func VerifyRegisterGobUser(curUser *storage.User, t *testing.T) {
+func VerifyRegisterGobUser(curUser *user2.User, t *testing.T) {
 
 	expectedUser := id.NewIdFromUInt(5, id.User, t)
 
diff --git a/bots/bots_test.go b/bots/bots_test.go
index 7318d309c6f8c555594cf0ecb4bbe296521a9373..6dd35b682e9450248d9466a5f47b87e890daaa75 100644
--- a/bots/bots_test.go
+++ b/bots/bots_test.go
@@ -17,6 +17,7 @@ import (
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/client/parse"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/large"
@@ -72,7 +73,7 @@ var keyFingerprint string
 var pubKey []byte
 
 func TestMain(m *testing.M) {
-	u := &storage.User{
+	u := &user2.User{
 		User:     new(id.ID),
 		Username: "Bernie",
 	}
@@ -83,8 +84,8 @@ func TestMain(m *testing.M) {
 
 	fakeSession := user.NewSession(&globals.RamStorage{}, "password")
 	fakeSession2 := storage.InitTestingSession(m)
-	fakeSession2.CommitUserData(&storage.UserData{
-		ThisUser: &storage.User{
+	fakeSession2.CommitUserData(&user2.UserData{
+		ThisUser: &user2.User{
 			User:     u.User,
 			Username: u.Username,
 		},
diff --git a/crypto/encryptdecrypt_test.go b/crypto/encryptdecrypt_test.go
index 247748d72a6167feb8fbaa08ce94ecd283bb577b..0ed8c376f6be5e2b9d8171e72fa4661c551ab380 100644
--- a/crypto/encryptdecrypt_test.go
+++ b/crypto/encryptdecrypt_test.go
@@ -11,6 +11,7 @@ import (
 	"encoding/binary"
 	"fmt"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/client/userRegistry"
 	pb "gitlab.com/elixxir/comms/mixmessages"
@@ -74,7 +75,7 @@ func setup() {
 
 	SessionV2, _ = storage.Init(".ekvcryptotest", "password")
 
-	userData := &storage.UserData{
+	userData := &user2.UserData{
 		ThisUser: u,
 		CmixGrp:  cmixGrp,
 		E2EGrp:   e2eGrp,
diff --git a/storage/processingrounds.go b/io/processingrounds.go
similarity index 97%
rename from storage/processingrounds.go
rename to io/processingrounds.go
index 59a2f598d1d36319d758d4346ba614b2992c3ef8..3c7d09201651b98c2af9e8a27f6c2fc38b218fb7 100644
--- a/storage/processingrounds.go
+++ b/io/processingrounds.go
@@ -1,4 +1,4 @@
-package storage
+package io
 
 // File for storing info about which rounds are processing
 
diff --git a/storage/processingrounds_test.go b/io/processingrounds_test.go
similarity index 98%
rename from storage/processingrounds_test.go
rename to io/processingrounds_test.go
index 7cd6f56788774842ae521e8a48bec7de0c2a4b15..2b86976aff6a0ac12a8adb1e5ca34cc7aab9876e 100644
--- a/storage/processingrounds_test.go
+++ b/io/processingrounds_test.go
@@ -1,4 +1,4 @@
-package storage
+package io
 
 // Testing functions for Processing Round structure
 
diff --git a/rekey/rekey_test.go b/rekey/rekey_test.go
index b45c75338114847d2ff0a29553edfd0783266d3c..6ed7ffc7515941af7817041bb613e95b9781f221 100644
--- a/rekey/rekey_test.go
+++ b/rekey/rekey_test.go
@@ -9,6 +9,7 @@ import (
 	"gitlab.com/elixxir/client/keyStore"
 	"gitlab.com/elixxir/client/parse"
 	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/client/userRegistry"
 	"gitlab.com/elixxir/crypto/csprng"
@@ -68,7 +69,7 @@ func TestMain(m *testing.M) {
 	grp, e2eGrp := getGroups()
 	userRegistry.InitUserRegistry(grp)
 	rng := csprng.NewSystemRNG()
-	u := &storage.User{
+	u := &user2.User{
 		User:     new(id.ID),
 		Username: "Bernie",
 	}
@@ -96,7 +97,7 @@ func TestMain(m *testing.M) {
 
 	sessionV2 := storage.InitTestingSession(m)
 
-	userData := &storage.UserData{
+	userData := &user2.UserData{
 		ThisUser:         u,
 		RSAPrivateKey:    privateKeyRSA,
 		RSAPublicKey:     &publicKeyRSA,
diff --git a/storage/cmix/key.go b/storage/cmix/key.go
index b0f9bcf2d0f6e1e9bd9f0302e53c2128e6693045..f2078b678e1d78902337663ce4cede06b5fddeff 100644
--- a/storage/cmix/key.go
+++ b/storage/cmix/key.go
@@ -26,6 +26,11 @@ func NewKey(kv *versioned.KV, k *cyclic.Int, id *id.ID) (*key, error) {
 	return newKey, newKey.save()
 }
 
+// returns the cyclic key
+func (k *key) Get() *cyclic.Int {
+	return k.k
+}
+
 // loads the key for the given node id from the versioned keystore
 func loadKey(kv *versioned.KV, id *id.ID) (*key, error) {
 	k := &key{}
diff --git a/storage/cmix/roundKeys.go b/storage/cmix/roundKeys.go
index 96bfeccd1c8f375ca8743e59f8fd26b49fb058fc..6e04e5d5c502341f8b9093639da45ab4fd7d6131 100644
--- a/storage/cmix/roundKeys.go
+++ b/storage/cmix/roundKeys.go
@@ -2,33 +2,41 @@ package cmix
 
 import (
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/crypto/cmix"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/primitives/format"
 )
 
-type RoundKeys []*cyclic.Int
+type RoundKeys struct {
+	keys []*key
+	g    *cyclic.Group
+}
 
 // Encrypts the given message for CMIX
 // Panics if the passed message is not sized correctly for the group
-func (rk RoundKeys) Encrypt(grp *cyclic.Group, msg format.Message,
+func (rk *RoundKeys) Encrypt(msg format.Message,
 	salt []byte) (format.Message, [][]byte) {
 
-	if msg.GetPrimeByteLen() != grp.GetP().ByteLen() {
+	if msg.GetPrimeByteLen() != rk.g.GetP().ByteLen() {
 		jww.FATAL.Panicf("Cannot encrypt message whose size does not " +
 			"align with the size of the prime")
 	}
 
-	ecrMsg := cmix.ClientEncrypt(grp, msg, salt, rk)
+	keys := make([]*cyclic.Int, len(rk.keys))
+
+	for i, k := range rk.keys {
+		keys[i] = k.Get()
+	}
+
+	ecrMsg := cmix.ClientEncrypt(rk.g, msg, salt, keys)
 
 	h, err := hash.NewCMixHash()
 	if err != nil {
-		globals.Log.ERROR.Printf("Cound not get hash for KMAC generation: %+v", h)
+		jww.FATAL.Panicf("Cound not get hash for KMAC generation: %+v", h)
 	}
 
-	KMAC := cmix.GenerateKMACs(salt, rk, h)
+	KMAC := cmix.GenerateKMACs(salt, keys, h)
 
 	return ecrMsg, KMAC
 }
diff --git a/storage/cmix/roundKeys_test.go b/storage/cmix/roundKeys_test.go
index d64044e97168aabf8140a566b6512a4f46324ff2..be9dcaef05d4c2d39557855b9ccd7d0a5e7cdf16 100644
--- a/storage/cmix/roundKeys_test.go
+++ b/storage/cmix/roundKeys_test.go
@@ -83,11 +83,13 @@ func TestRoundKeys_Encrypt_Consistency(t *testing.T) {
 
 	prng := rand.New(rand.NewSource(42))
 
-	rk := RoundKeys(make([]*cyclic.Int, numKeys))
+	keys := make([]*key, numKeys)
 
 	for i := 0; i < numKeys; i++ {
 		keyBytes, _ := csprng.GenerateInGroup(cmixGrp.GetPBytes(), cmixGrp.GetP().ByteLen(), prng)
-		rk[i] = cmixGrp.NewIntFromBytes(keyBytes)
+		keys[i] = &key{
+			k: cmixGrp.NewIntFromBytes(keyBytes),
+		}
 	}
 
 	salt := make([]byte, 32)
@@ -98,7 +100,12 @@ func TestRoundKeys_Encrypt_Consistency(t *testing.T) {
 	prng.Read(contents)
 	msg.SetContents(contents)
 
-	encMsg, kmacs := rk.Encrypt(cmixGrp, msg, salt)
+	rk := RoundKeys{
+		keys: keys,
+		g:    cmixGrp,
+	}
+
+	encMsg, kmacs := rk.Encrypt(msg, salt)
 
 	if !bytes.Equal(encMsg.GetData(), expectedPayload) {
 		t.Errorf("Encrypted messages do not match")
diff --git a/storage/cmix/store.go b/storage/cmix/store.go
index 043f0dbdd9682d1c5902ebba9d9de795f9c4fa4d..3ff308f25033883455870a5e40e4cc8bdea3c41e 100644
--- a/storage/cmix/store.go
+++ b/storage/cmix/store.go
@@ -3,8 +3,10 @@ package cmix
 import (
 	"encoding/json"
 	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/utility"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
@@ -12,39 +14,53 @@ import (
 )
 
 const currentStoreVersion = 0
-const currentKeyStoreVersion = 0
 const storeKey = "cmixKeyStore"
 const pubKeyKey = "cmixDhPubKey"
 const privKeyKey = "cmixDhPrivKey"
+const grpKey = "cmixGroupKey"
 
 type Store struct {
 	nodes        map[id.ID]*key
 	dhPrivateKey *cyclic.Int
 	dhPublicKey  *cyclic.Int
 
+	grp *cyclic.Group
+
 	kv *versioned.KV
 
 	mux sync.RWMutex
 }
 
 // returns a new cmix storage object
-func NewStore(kv *versioned.KV, pub, priv *cyclic.Int) (*Store, error) {
+func NewStore(grp *cyclic.Group, kv *versioned.KV, priv *cyclic.Int) (*Store, error) {
+	//generate public key
+	pub := diffieHellman.GeneratePublicKey(priv, grp)
+
 	s := &Store{
 		nodes:        make(map[id.ID]*key),
 		dhPrivateKey: priv,
 		dhPublicKey:  priv,
+		grp:          grp,
 		kv:           kv,
 	}
 
-	err := storeDhKey(kv, pub, pubKeyKey)
+	err := utility.StoreCyclicKey(kv, pub, pubKeyKey)
 	if err != nil {
 		return nil,
-			errors.WithMessage(err, "Failed to store cmix DH public key")
+			errors.WithMessage(err,
+				"Failed to store cmix DH public key")
+	}
+
+	err = utility.StoreCyclicKey(kv, priv, privKeyKey)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to store cmix DH private key")
 	}
 
-	err = storeDhKey(kv, priv, privKeyKey)
+	err = utility.StoreGroup(kv, grp, grpKey)
 	if err != nil {
-		return nil, errors.WithMessage(err, "Failed to store cmix DH private key")
+		return nil, errors.WithMessage(err,
+			"Failed to store cmix group")
 	}
 
 	return s, s.save()
@@ -108,13 +124,13 @@ func (s *Store) Remove(nid *id.ID, k *cyclic.Int) error {
 }
 
 //Returns a RoundKeys for the topology and a list of nodes it did not have a key for
-func (s *Store) GetRoundKeys(topology *connect.Circuit) (RoundKeys, []*id.ID) {
+func (s *Store) GetRoundKeys(topology *connect.Circuit) (*RoundKeys, []*id.ID) {
 	s.mux.RLock()
 	defer s.mux.RUnlock()
 
 	var missingNodes []*id.ID
 
-	rk := RoundKeys(make([]*cyclic.Int, topology.Len()))
+	keys := make([]*key, topology.Len())
 
 	for i := 0; i < topology.Len(); i++ {
 		nid := topology.GetNodeAtIndex(i)
@@ -122,13 +138,33 @@ func (s *Store) GetRoundKeys(topology *connect.Circuit) (RoundKeys, []*id.ID) {
 		if !ok {
 			missingNodes = append(missingNodes, nid)
 		} else {
-			rk[i] = k.k
+			keys[i] = k
 		}
 	}
 
+	rk := &RoundKeys{
+		keys: keys,
+		g:    s.grp,
+	}
+
 	return rk, missingNodes
 }
 
+//Returns the diffie hellman private key
+func (s *Store) GetDHPrivateKey() *cyclic.Int {
+	return s.dhPrivateKey
+}
+
+//Returns the diffie hellman public key
+func (s *Store) GetDHPublicKey() *cyclic.Int {
+	return s.dhPublicKey
+}
+
+//Returns the cyclic group used for cmix
+func (s *Store) GetGroup() *cyclic.Group {
+	return s.grp
+}
+
 // stores the cmix store
 func (s *Store) save() error {
 	now := time.Now()
@@ -176,45 +212,23 @@ func (s *Store) unmarshal(b []byte) error {
 		s.nodes[nid] = k
 	}
 
-	s.dhPrivateKey, err = loadDhKey(s.kv, privKeyKey)
+	s.dhPrivateKey, err = utility.LoadCyclicKey(s.kv, privKeyKey)
 	if err != nil {
 		return errors.WithMessage(err,
 			"Failed to load cmix DH private key")
 	}
 
-	s.dhPublicKey, err = loadDhKey(s.kv, pubKeyKey)
+	s.dhPublicKey, err = utility.LoadCyclicKey(s.kv, pubKeyKey)
 	if err != nil {
 		return errors.WithMessage(err,
 			"Failed to load cmix DH public key")
 	}
 
-	return nil
-}
-
-func storeDhKey(kv *versioned.KV, dh *cyclic.Int, key string) error {
-	now := time.Now()
-
-	data, err := dh.GobEncode()
-	if err != nil {
-		return err
-	}
-
-	obj := versioned.Object{
-		Version:   currentKeyVersion,
-		Timestamp: now,
-		Data:      data,
-	}
-
-	return kv.Set(key, &obj)
-}
-
-func loadDhKey(kv *versioned.KV, key string) (*cyclic.Int, error) {
-	vo, err := kv.Get(key)
+	s.grp, err = utility.LoadGroup(s.kv, grpKey)
 	if err != nil {
-		return nil, err
+		return errors.WithMessage(err,
+			"Failed to load cmix group")
 	}
 
-	dhKey := &cyclic.Int{}
-
-	return dhKey, dhKey.GobDecode(vo.Data)
+	return nil
 }
\ No newline at end of file
diff --git a/storage/contact.go b/storage/contact.go
deleted file mode 100644
index 4eb415dd264f2e4eae89c8825642ccdbbd6c837d..0000000000000000000000000000000000000000
--- a/storage/contact.go
+++ /dev/null
@@ -1,128 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
-package storage
-
-import (
-	"encoding/json"
-	"gitlab.com/elixxir/client/globals"
-	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/xx_network/primitives/id"
-	"time"
-)
-
-const currentContactVersion = 0
-
-// Contact holds the public key and ID of a given contact.
-type Contact struct {
-	Id        *id.ID
-	PublicKey []byte
-	Email     string
-}
-
-// loadAllContacts populates the "contacts" variable for the session
-func (s *Session) loadAllContacts() {
-	s.contactsLck.Lock()
-	defer s.contactsLck.Unlock()
-	obj, err := s.Get("AllContacts")
-	if err != nil {
-		s.contacts = make(map[string]*Contact)
-		return
-	}
-	err = json.Unmarshal(obj.Data, s.contacts)
-	if err != nil {
-		s.contacts = make(map[string]*Contact)
-	}
-}
-
-func (s *Session) saveContacts() error {
-	data, err := json.Marshal(s.contacts)
-	if err != nil {
-		return err
-	}
-	obj := versioned.Object{
-		Version:   currentContactVersion,
-		Timestamp: time.Now(),
-		Data:      data,
-	}
-	return s.Set("AllContacts", &obj)
-}
-
-func (s *Session) updateContact(record *Contact) error {
-	s.contactsLck.Lock()
-	defer s.contactsLck.Unlock()
-	s.contacts[record.Id.String()] = record
-	return s.saveContacts()
-}
-
-// GetContactByEmail reads contact information from disk
-func (s *Session) GetContactByEmail(email string) (*Contact, error) {
-	key := versioned.MakeKeyWithPrefix("Contact", email)
-
-	obj, err := s.Get(key)
-	if err != nil {
-		return nil, err
-	}
-	// Correctly implemented upgrade should always change the version number to what's current
-	if obj.Version != currentContactVersion {
-		globals.Log.WARN.Printf("Session.GetContact: got unexpected "+
-			"version %v, expected version %v", obj.Version,
-			currentContactVersion)
-	}
-
-	// deserialize
-	var contact Contact
-	err = json.Unmarshal(obj.Data, &contact)
-	return &contact, err
-}
-
-// SetContactByEmail saves contact information to disk.
-func (s *Session) SetContactByEmail(email string, record *Contact) error {
-	err := s.updateContact(record)
-	if err != nil {
-		return err
-	}
-
-	key := versioned.MakeKeyWithPrefix("Contact", email)
-	data, err := json.Marshal(record)
-	if err != nil {
-		return err
-	}
-	obj := versioned.Object{
-		Version:   currentContactVersion,
-		Timestamp: time.Now(),
-		Data:      data,
-	}
-	return s.Set(key, &obj)
-}
-
-func (s *Session) GetContactByID(ID *id.ID) *Contact {
-	s.contactsLck.Lock()
-	defer s.contactsLck.Unlock()
-	c, ok := s.contacts[ID.String()]
-	if !ok {
-		return nil
-	}
-	return c
-}
-
-// DeleteContactByID removes the contact from disk
-func (s *Session) DeleteContactByID(ID *id.ID) error {
-	s.contactsLck.Lock()
-	defer s.contactsLck.Unlock()
-	record, ok := s.contacts[ID.String()]
-	if !ok {
-		return nil
-	}
-	delete(s.contacts, record.Id.String())
-	err := s.saveContacts()
-	if err != nil {
-		return err
-	}
-
-	key := versioned.MakeKeyWithPrefix("Contact", record.Email)
-	return s.Delete(key)
-}
diff --git a/storage/contact_test.go b/storage/contact_test.go
deleted file mode 100644
index 1787252e0022149595dba2181ef86b75695c0dca..0000000000000000000000000000000000000000
--- a/storage/contact_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
-package storage
-
-import (
-	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/elixxir/ekv"
-	"gitlab.com/xx_network/primitives/id"
-	"reflect"
-	"testing"
-)
-
-// Show that all fields of a searched user record get stored
-func TestSession_Contact(t *testing.T) {
-	store := make(ekv.Memstore)
-	session := &Session{kv: versioned.NewKV(store)}
-	session.loadAllContacts()
-
-	expectedRecord := &Contact{
-		Id:        id.NewIdFromUInt(24601, id.User, t),
-		PublicKey: []byte("not a real public key"),
-	}
-
-	name := "niamh@elixxir.io"
-	err := session.SetContactByEmail(name, expectedRecord)
-	if err != nil {
-		t.Fatal(err)
-	}
-	retrievedRecord, err := session.GetContactByEmail(name)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if !reflect.DeepEqual(expectedRecord, retrievedRecord) {
-		t.Error("Expected and retrieved records were different")
-	}
-}
diff --git a/storage/e2e/session.go b/storage/e2e/session.go
index ce9fa1bb49018fd6de540623b2fe20247ec0abd9..a9943ddb78016cdfdf6c7e6555300f73e45a692c 100644
--- a/storage/e2e/session.go
+++ b/storage/e2e/session.go
@@ -2,7 +2,7 @@ package e2e
 
 import (
 	"encoding/json"
-	"errors"
+	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/csprng"
 	"gitlab.com/elixxir/crypto/cyclic"
@@ -76,9 +76,12 @@ func newSession(manager *Manager, myPrivKey *cyclic.Int, partnerPubKey *cyclic.I
 		confirmed:     t == Receive,
 	}
 
-	session.generate()
+	err := session.generate()
+	if err != nil {
+		return nil, err
+	}
 
-	err := session.save()
+	err = session.save()
 	if err != nil {
 		return nil, err
 	}
@@ -280,7 +283,7 @@ func (s *Session) useKey(keynum uint32) error {
 
 // generates keys from the base data stored in the session object.
 // myPrivKey will be generated if not present
-func (s *Session) generate() {
+func (s *Session) generate() error {
 	grp := s.manager.ctx.grp
 
 	//generate public key if it is not present
@@ -304,13 +307,19 @@ func (s *Session) generate() {
 	s.ttl = uint32(keysTTL)
 
 	//create the new state vectors. This will cause disk operations storing them
-	s.keyState = newStateVector(s.manager.ctx, keyEKVPrefix, numKeys)
+	var err error
+	s.keyState, err = newStateVector(s.manager.ctx, keyEKVPrefix, numKeys)
+	if err != nil {
+		return errors.WithMessage(err, "Failed key generation")
+	}
 
 	//register keys for reception if this is a reception session
 	if s.t == Receive {
 		//register keys
 		s.manager.ctx.fa.add(s.getUnusedKeys())
 	}
+
+	return nil
 }
 
 //returns key objects for all unused keys
diff --git a/storage/e2e/store.go b/storage/e2e/store.go
index b2cef1c8b8d33abc1fda97fe37ecb4a47420cef0..964f88e251c72d89b4f3ecfb08788bf0a74680b0 100644
--- a/storage/e2e/store.go
+++ b/storage/e2e/store.go
@@ -4,31 +4,49 @@ import (
 	"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/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
 	"time"
 )
 
-const storeKey = "e2eKeyStore"
+
 const currentStoreVersion = 0
+const storeKey = "e2eKeyStore"
+const pubKeyKey = "e2eDhPubKey"
+const privKeyKey = "e2eDhPrivKey"
+const grpKey = "e2eGroupKey"
 
 type Store struct {
 	managers map[id.ID]*Manager
 	mux      sync.RWMutex
 
+	dhPrivateKey *cyclic.Int
+	dhPublicKey  *cyclic.Int
+	grp          *cyclic.Group
+
 	fingerprints
 
 	context
 }
 
-func NewStore(grp *cyclic.Group, kv *versioned.KV) *Store {
+func NewStore(grp *cyclic.Group, kv *versioned.KV, priv *cyclic.Int) (*Store, error) {
+	//generate public key
+	pub := diffieHellman.GeneratePublicKey(priv, grp)
+
 	fingerprints := newFingerprints()
-	return &Store{
+	s := &Store{
 		managers:     make(map[id.ID]*Manager),
 		fingerprints: fingerprints,
+
+		dhPrivateKey: priv,
+		dhPublicKey:  pub,
+		grp:          grp,
+
 		context: context{
 			fa:  &fingerprints,
 			grp: grp,
@@ -36,10 +54,39 @@ func NewStore(grp *cyclic.Group, kv *versioned.KV) *Store {
 		},
 	}
 
+	err := utility.StoreCyclicKey(kv, pub, pubKeyKey)
+	if err != nil {
+		return nil,
+			errors.WithMessage(err,
+				"Failed to store e2e DH public key")
+	}
+
+	err = utility.StoreCyclicKey(kv, priv, privKeyKey)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to store e2e DH private key")
+	}
+
+	err = utility.StoreGroup(kv, grp, grpKey)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to store e2e group")
+	}
+
+	return s, s.save()
 }
 
-func LoadStore(grp *cyclic.Group, kv *versioned.KV) (*Store, error) {
-	s := NewStore(grp, kv)
+func LoadStore(kv *versioned.KV) (*Store, error) {
+	fingerprints := newFingerprints()
+	s := &Store{
+		managers:     make(map[id.ID]*Manager),
+		fingerprints: fingerprints,
+
+		context: context{
+			fa: &fingerprints,
+			kv: kv,
+		},
+	}
 
 	obj, err := kv.Get(storeKey)
 	if err != nil {
@@ -52,6 +99,8 @@ func LoadStore(grp *cyclic.Group, kv *versioned.KV) (*Store, error) {
 		return nil, err
 	}
 
+	s.context.grp = s.grp
+
 	return s, nil
 }
 
@@ -101,6 +150,26 @@ func (s *Store) GetPartner(partnerID *id.ID) (*Manager, error) {
 	return m, nil
 }
 
+//Pops a key for use based upon its fingerprint
+func (s *Store) PopKey(f format.Fingerprint) (*Key, error) {
+	return s.fingerprints.Pop(f)
+}
+
+//Returns the diffie hellman private key
+func (s *Store) GetDHPrivateKey() *cyclic.Int {
+	return s.dhPrivateKey
+}
+
+//Returns the diffie hellman public key
+func (s *Store) GetDHPublicKey() *cyclic.Int {
+	return s.dhPublicKey
+}
+
+//Returns the cyclic group used for cmix
+func (s *Store) GetGroup() *cyclic.Group {
+	return s.grp
+}
+
 //ekv functions
 func (s *Store) marshal() ([]byte, error) {
 
@@ -134,6 +203,25 @@ func (s *Store) unmarshal(b []byte) error {
 
 		s.managers[partnerID] = manager
 	}
+
+	s.dhPrivateKey, err = utility.LoadCyclicKey(s.kv, privKeyKey)
+	if err != nil {
+		return errors.WithMessage(err,
+			"Failed to load e2e DH private key")
+	}
+
+	s.dhPublicKey, err = utility.LoadCyclicKey(s.kv, pubKeyKey)
+	if err != nil {
+		return errors.WithMessage(err,
+			"Failed to load e2e DH public key")
+	}
+
+	s.grp, err = utility.LoadGroup(s.kv, grpKey)
+	if err != nil {
+		return errors.WithMessage(err,
+			"Failed to load e2e group")
+	}
+
 	return nil
 }
 
diff --git a/storage/regStatus.go b/storage/regStatus.go
index 00b89539bfc56a3acdbe5ff1c547a6bbe81796f1..28f55a99e15919ea755bf1319204aa402b3e651b 100644
--- a/storage/regStatus.go
+++ b/storage/regStatus.go
@@ -1,5 +1,17 @@
 package storage
 
+import (
+	"encoding/binary"
+	"fmt"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"os"
+	"time"
+)
+
+const currentRegistrationStatusVersion = 0
+const registrationStatusKey = "regStatusKey"
+
 type RegistrationStatus uint32
 
 const (
@@ -8,3 +20,85 @@ const (
 	PermissioningComplete RegistrationStatus = 20000 // Set upon completion of RegisterWithPermissioning
 	UDBComplete           RegistrationStatus = 30000 // Set upon completion of RegisterWithUdb
 )
+
+// stringer for Registration Status
+func (rs RegistrationStatus) String() string {
+	switch rs {
+	case NotStarted:
+		return "Not Started"
+	case KeyGenComplete:
+		return "Key Generation Complete"
+	case PermissioningComplete:
+		return "Permissioning Registration Complete"
+	case UDBComplete:
+		return "User Discovery Registration Complete"
+	default:
+		return fmt.Sprintf("Unknown registration state %v", uint32(rs))
+	}
+}
+
+// creates a registration status from binary data
+func regStatusUnmarshalBinary(b []byte) RegistrationStatus {
+	return RegistrationStatus(binary.BigEndian.Uint32(b))
+}
+
+// returns the binary representation of the registration status
+func (rs RegistrationStatus) marshalBinary() []byte {
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint32(b, uint32(rs))
+	return b
+}
+
+// loads the registration status from disk. If the status cannot be found, it
+// defaults to Not Started
+func (s *Session) loadOrCreateRegStatus() error {
+	obj, err := s.Get(registrationStatusKey)
+	if err != nil {
+		if os.IsNotExist(err) {
+			// set at not started but do not save until it is updated
+			s.regStatus = NotStarted
+			return nil
+		} else {
+			return errors.WithMessagef(err, "Failed to load registration status")
+		}
+	}
+	s.regStatus = regStatusUnmarshalBinary(obj.Data)
+	return nil
+}
+
+// sets the registration status to the passed status if it is greater than the
+// current stats, otherwise returns an error
+func (s *Session) ForwardRegistrationStatus(regStatus RegistrationStatus) error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	if regStatus <= s.regStatus {
+		return errors.Errorf("Cannot set registration status to a "+
+			"status before the current stats: Current: %s, New: %s",
+			s.regStatus, regStatus)
+	}
+
+	now := time.Now()
+
+	obj := versioned.Object{
+		Version:   currentRegistrationStatusVersion,
+		Timestamp: now,
+		Data:      regStatus.marshalBinary(),
+	}
+
+	err := s.Set(registrationStatusKey, &obj)
+	if err != nil {
+		return errors.WithMessagef(err, "Failed to store registration status")
+	}
+
+	s.regStatus = regStatus
+	return nil
+}
+
+// sets the registration status to the passed status if it is greater than the
+// current stats, otherwise returns an error
+func (s *Session) GetRegistrationStatus() RegistrationStatus {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.regStatus
+}
\ No newline at end of file
diff --git a/storage/registration.go b/storage/registration.go
deleted file mode 100644
index 5ffd0b8fcb9503c37e14223f96be1819b4baa155..0000000000000000000000000000000000000000
--- a/storage/registration.go
+++ /dev/null
@@ -1,98 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-package storage
-
-import (
-	"encoding/json"
-	"gitlab.com/elixxir/client/globals"
-	"gitlab.com/elixxir/client/storage/versioned"
-	"time"
-)
-
-var currentRegistrationVersion = uint64(0)
-
-// SetRegValidationSig builds the versioned object and sets it in the
-// key-value store
-func (s *Session) SetRegValidationSig(newVal []byte) error {
-	// Construct the versioned object
-	vo := &versioned.Object{
-		Version:   currentRegistrationVersion,
-		Timestamp: time.Now(),
-		Data:      newVal,
-	}
-
-	// Construct the key and place in the key-value store
-	key := "RegValidationSig"
-
-	return s.kv.Set(key, vo)
-}
-
-// GetRegValidationSig pulls the versioned object by the key and parses
-// it into the requested registration signature
-func (s *Session) GetRegValidationSig() ([]byte, error) {
-	key := "RegValidationSig"
-
-	// Pull the object from the key-value store
-	voData, err := s.kv.Get(key)
-	if err != nil {
-		return nil, err
-	}
-
-	if voData.Version != currentRegistrationVersion {
-		globals.Log.WARN.Printf("Session.GetRegValidationSig: got "+
-			"unexpected version %v, expected version %v",
-			voData.Version, currentRegistrationVersion)
-	}
-
-	return voData.Data, nil
-}
-
-// SetRegState uses the SetInterface method to place the regstate into
-// the key-value store
-func (s *Session) SetRegState(newVal int64) error {
-	key := "RegState"
-
-	data, err := json.Marshal(newVal)
-	if err != nil {
-		return err
-	}
-
-	obj := versioned.Object{
-		Version:   currentRegistrationVersion,
-		Timestamp: time.Now(),
-		Data:      data,
-	}
-
-	return s.kv.Set(key, &obj)
-}
-
-// GetRegValidationSig pulls the versioned object by the key and parses
-// it into the requested registration signature
-func (s *Session) GetRegState() (int64, error) {
-	// Construct the key from the
-	key := "RegState"
-
-	// Pull the object from the key-value store
-	voData, err := s.kv.Get(key)
-	if err != nil {
-		return 0, err
-	}
-
-	if voData.Version != currentRegistrationVersion {
-		globals.Log.WARN.Printf("Session.GetRegState: got unexpected "+
-			"version %v, expected version %v",
-			voData.Version, currentRegistrationVersion)
-	}
-
-	var data int64
-	err = json.Unmarshal(voData.Data, &data)
-	if err != nil {
-		return 0, err
-	}
-
-	return data, nil
-
-}
diff --git a/storage/registration_test.go b/storage/registration_test.go
deleted file mode 100644
index db6fdc447b645bf77092ae80aaa58364fb999d9e..0000000000000000000000000000000000000000
--- a/storage/registration_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-package storage
-
-import (
-	"bytes"
-	"testing"
-)
-
-func TestSession_RegState(t *testing.T) {
-	testSession := InitTestingSession(t)
-
-	expectedVal := int64(42)
-	err := testSession.SetRegState(expectedVal)
-	if err != nil {
-		t.Errorf("Failed to place value in session: %v", err)
-	}
-
-	retrievedVal, err := testSession.GetRegState()
-	if err != nil {
-		t.Errorf("Faield to get value from session: %v", err)
-	}
-
-	if retrievedVal != expectedVal {
-		t.Errorf("Expected value not retrieved from file store!"+
-			"\n\tExpected: %v"+
-			"\n\tRecieved: %v", expectedVal, retrievedVal)
-	}
-
-}
-
-func TestSession_RegValidation(t *testing.T) {
-	testSession := InitTestingSession(t)
-
-	expectedVal := []byte("testData")
-
-	err := testSession.SetRegValidationSig(expectedVal)
-	if err != nil {
-		t.Errorf("Failed to place value in session: %v", err)
-	}
-
-	retrievedVal, err := testSession.GetRegValidationSig()
-	if err != nil {
-		t.Errorf("Faield to get value from session: %v", err)
-	}
-
-	if !bytes.Equal(retrievedVal, expectedVal) {
-		t.Errorf("Expected value not retrieved from file store!"+
-			"\n\tExpected: %v"+
-			"\n\tRecieved: %v", expectedVal, retrievedVal)
-	}
-}
diff --git a/storage/session.go b/storage/session.go
index a541b5a8c8e47e5eeb92031d33b011c8902b36ed..ad4569f35975e7d45af6484db6b59c822f9bd778 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -9,180 +9,156 @@
 package storage
 
 import (
-	"bytes"
-	"encoding/gob"
+	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/client/storage/cmix"
+	"gitlab.com/elixxir/client/storage/e2e"
+	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/elixxir/client/user"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/ekv"
-	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
 	"testing"
-	"time"
 )
 
 // Session object, backed by encrypted filestore
 type Session struct {
-	kv       *versioned.KV
-	userData *UserData
-	mux      sync.Mutex
+	kv  *versioned.KV
+	mux sync.RWMutex
 
-	// Contacts controls
-	contacts    map[string]*Contact
-	contactsLck sync.Mutex
+	regStatus RegistrationStatus
+
+	//sub-stores
+	e2e  *e2e.Store
+	cmix *cmix.Store
+	user *user.User
+
+	loaded bool
 
-	//keystores
-	cmixKeys cmix.Store
 }
 
 // Initialize a new Session object
 func Init(baseDir, password string) (*Session, error) {
 	fs, err := ekv.NewFilestore(baseDir, password)
 	var s *Session
-	if err == nil {
-		s = &Session{
-			kv: versioned.NewKV(fs),
-		}
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to create storage session")
 	}
 
-	s.loadAllContacts()
-
-	return s, err
-}
+	s = &Session{
+		kv:     versioned.NewKV(fs),
+		loaded: false,
+	}
 
-// a storage session with a memory backed for testing
-func InitMem(t *testing.T) *Session {
-	if t == nil {
-		panic("cannot use a memstore not for testing")
+	err = s.loadOrCreateRegStatus()
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to load or create registration status")
 	}
-	store := make(ekv.Memstore)
-	return &Session{kv: versioned.NewKV(store)}
-}
 
-// Get an object from the session
-func (s *Session) Get(key string) (*versioned.Object, error) {
-	return s.kv.Get(key)
+	return s, nil
 }
 
-// Set a value in the session
-func (s *Session) Set(key string, object *versioned.Object) error {
-	return s.kv.Set(key, object)
-}
+// Creates new UserData in the session
+func (s *Session) Create(uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey,
+	isPrecanned bool, cmixDHPrivKey, e2eDHPrivKey *cyclic.Int, cmixGrp,
+	e2eGrp *cyclic.Group) error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+	if s.loaded {
+		return errors.New("Cannot create a session which already has one loaded")
+	}
 
-// Delete a value in the session
-func (s *Session) Delete(key string) error {
-	return s.kv.Delete(key)
-}
+	var err error
 
-// Obtain the LastMessageID from the Session
-func (s *Session) GetLastMessageId() (string, error) {
-	v, err := s.Get("LastMessageID")
-	if v == nil || err != nil {
-		return "", nil
+	s.user, err = user.NewUser(s.kv, uid, salt, rsaKey, isPrecanned)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to create Session due "+
+			"to failed user creation")
 	}
-	return string(v.Data), nil
-}
 
-// Set the LastMessageID in the Session
-func (s *Session) SetLastMessageId(id string) error {
-	vo := &versioned.Object{
-		Timestamp: time.Now(),
-		Data:      []byte(id),
+	s.cmix, err = cmix.NewStore(cmixGrp, s.kv, cmixDHPrivKey)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to create Session due "+
+			"to failed cmix keystore creation")
 	}
-	return s.Set("LastMessageID", vo)
-}
 
-// GetNodeKeys returns all keys
-func (s *Session) GetNodeKeys() (map[string]user.NodeKeys, error) {
-	key := "NodeKeys"
-	var nodeKeys map[string]user.NodeKeys
+	s.e2e, err = e2e.NewStore(e2eGrp, s.kv, e2eDHPrivKey)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to create Session due "+
+			"to failed e2e keystore creation")
+	}
 
-	// Attempt to locate the keys map
-	v, err := s.Get(key)
+	s.loaded = true
+	return nil
+}
 
-	// If the map doesn't exist, initialize it
-	if err != nil {
-		// Encode the new map
-		nodeKeys = make(map[string]user.NodeKeys)
-		var nodeKeysBuffer bytes.Buffer
-		enc := gob.NewEncoder(&nodeKeysBuffer)
-		err = enc.Encode(nodeKeys)
-		if err != nil {
-			return nil, err
-		}
-
-		// Store the new map
-		vo := &versioned.Object{
-			Timestamp: time.Now(),
-			Data:      nodeKeysBuffer.Bytes(),
-		}
-		err = s.Set(key, vo)
-		if err != nil {
-			return nil, err
-		}
-
-		// Return newly-initialized map
-		return nodeKeys, nil
+// Loads existing user data into the session
+func (s *Session) Load() error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+	if s.loaded {
+		return errors.New("Cannot load a session which already has one loaded")
 	}
 
-	// If the map exists, decode and return it
-	var nodeKeyBuffer bytes.Buffer
-	nodeKeyBuffer.Write(v.Data)
-	dec := gob.NewDecoder(&nodeKeyBuffer)
-	err = dec.Decode(&nodeKeys)
+	var err error
 
-	return nodeKeys, err
-}
+	s.user, err = user.LoadUser(s.kv)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to load Session due "+
+			"to failure to load user")
+	}
 
-// GetNodeKeysFromCircuit obtains NodeKeys for a given circuit
-func (s *Session) GetNodeKeysFromCircuit(topology *connect.Circuit) (
-	[]user.NodeKeys, error) {
-	nodeKeys, err := s.GetNodeKeys()
+	s.cmix, err = cmix.LoadStore(s.kv)
 	if err != nil {
-		return nil, err
+		return errors.WithMessage(err, "Failed to load Session due "+
+			"to failure to load cmix keystore")
 	}
 
-	// Build a list of NodeKeys from the map
-	keys := make([]user.NodeKeys, topology.Len())
-	for i := 0; i < topology.Len(); i++ {
-		nid := topology.GetNodeAtIndex(i)
-		keys[i] = nodeKeys[nid.String()]
-		globals.Log.INFO.Printf("Read NodeKey: %s: %v", nid, keys[i])
+	s.e2e, err = e2e.LoadStore(s.kv)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to load Session due "+
+			"to failure to load e2e keystore")
 	}
 
-	return keys, nil
+	s.loaded = true
+	return nil
 }
 
-// Set NodeKeys in the Session
-func (s *Session) PushNodeKey(id *id.ID, key user.NodeKeys) error {
-	// Thread-safety
-	s.mux.Lock()
-	defer s.mux.Unlock()
+func (s *Session) User() *user.User {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.user
+}
 
-	// Obtain NodeKeys map
-	nodeKeys, err := s.GetNodeKeys()
-	if err != nil {
-		return err
-	}
+func (s *Session) Cmix() *cmix.Store {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.cmix
+}
 
-	// Set new value inside of map
-	nodeKeys[id.String()] = key
+func (s *Session) E2e() *e2e.Store {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.e2e
+}
 
-	globals.Log.INFO.Printf("Adding NodeKey: %s: %v", id.String(), key)
+// Get an object from the session
+func (s *Session) Get(key string) (*versioned.Object, error) {
+	return s.kv.Get(key)
+}
 
-	// Encode the map
-	var nodeKeysBuffer bytes.Buffer
-	enc := gob.NewEncoder(&nodeKeysBuffer)
-	err = enc.Encode(nodeKeys)
+// Set a value in the session
+func (s *Session) Set(key string, object *versioned.Object) error {
+	return s.kv.Set(key, object)
+}
 
-	// Insert the map back into the Session
-	vo := &versioned.Object{
-		Timestamp: time.Now(),
-		Data:      nodeKeysBuffer.Bytes(),
-	}
-	return s.Set("NodeKeys", vo)
+// Delete a value in the session
+func (s *Session) Delete(key string) error {
+	return s.kv.Delete(key)
 }
 
 // Initializes a Session object wrapped around a MemStore object.
diff --git a/storage/session_test.go b/storage/session_test.go
index 048fa870c126ac51bc44c27494f2054c8397c0a1..5101075bffc1bb05100c8683b0f9493ee597a916 100644
--- a/storage/session_test.go
+++ b/storage/session_test.go
@@ -9,11 +9,6 @@ package storage
 import (
 	"bytes"
 	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/elixxir/client/user"
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/large"
-	"gitlab.com/xx_network/comms/connect"
-	"gitlab.com/xx_network/primitives/id"
 	"os"
 	"testing"
 	"time"
@@ -55,62 +50,4 @@ func TestSession_Smoke(t *testing.T) {
 	if bytes.Compare(o.Data, []byte("test")) != 0 {
 		t.Errorf("Failed to get data")
 	}
-}
-
-// Happy path for getting/setting LastMessageID
-func TestSession_GetSetLastMessageId(t *testing.T) {
-	testId := "testLastMessageId"
-
-	s := initTest(t)
-
-	err := s.SetLastMessageId(testId)
-	if err != nil {
-		t.Errorf("Failed to set LastMessageId: %+v", err)
-	}
-	o, err := s.GetLastMessageId()
-	if err != nil {
-		t.Errorf("Failed to get LastMessageId")
-	}
-
-	if testId != o {
-		t.Errorf("Failed to get LastMessageID, Got %s Expected %s", o, testId)
-	}
-}
-
-// Happy path for getting/setting node keys
-func TestSession_GetPushNodeKeys(t *testing.T) {
-	s := initTest(t)
-
-	testId := id.NewIdFromString("test", id.Node, t)
-	testId2 := id.NewIdFromString("test2", id.Node, t)
-	testInt := cyclic.NewGroup(large.NewIntFromUInt(6), large.NewIntFromUInt(6)).NewInt(1)
-	testNodeKey := user.NodeKeys{
-		TransmissionKey: testInt,
-		ReceptionKey:    testInt,
-	}
-
-	err := s.PushNodeKey(testId, testNodeKey)
-	if err != nil {
-		t.Errorf("Unable to push node key: %+v", err)
-	}
-	err = s.PushNodeKey(testId2, testNodeKey)
-	if err != nil {
-		t.Errorf("Unable to push node key: %+v", err)
-	}
-
-	circ := connect.NewCircuit([]*id.ID{testId, testId2})
-	results, err := s.GetNodeKeysFromCircuit(circ)
-
-	if len(results) != 2 {
-		t.Errorf("Returned unexpected number of node keys: %d", len(results))
-		return
-	}
-	if results[0].TransmissionKey.Cmp(testInt) != 0 {
-		t.Errorf("Returned invalid transmission key: %s, Expected: %s", results[0].TransmissionKey.Text(10),
-			testInt.Text(10))
-	}
-	if results[0].ReceptionKey.Cmp(testInt) != 0 {
-		t.Errorf("Returned invalid reception key: %s, Expected: %s", results[0].TransmissionKey.Text(10),
-			testInt.Text(10))
-	}
-}
+}
\ No newline at end of file
diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go
new file mode 100644
index 0000000000000000000000000000000000000000..bc7eb730a3789295bdf661e1e44564e41fbb6f68
--- /dev/null
+++ b/storage/user/cryptographic.go
@@ -0,0 +1,89 @@
+package user
+
+import (
+	"bytes"
+	"encoding/gob"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"time"
+)
+
+const currentCryptographicIdentityVersion = 0
+const cryptographicIdentityKey = "cryptographicIdentity"
+
+type CryptographicIdentity struct {
+	userID      *id.ID
+	salt        []byte
+	rsaKey      *rsa.PrivateKey
+	isPrecanned bool
+}
+
+func newCryptographicIdentity(uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey,
+	isPrecanned bool, kv *versioned.KV) (*CryptographicIdentity, error) {
+
+	_, err := kv.Get(cryptographicIdentityKey)
+	if err == nil {
+		return nil, errors.New("cannot create cryptographic identity " +
+			"when one already exists")
+	}
+
+	ci := &CryptographicIdentity{
+		userID:      uid,
+		salt:        salt,
+		rsaKey:      rsaKey,
+		isPrecanned: isPrecanned,
+	}
+
+	return ci, ci.save(kv)
+}
+
+func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
+	obj, err := kv.Get(cryptographicIdentityKey)
+	if err != nil {
+		return nil, errors.WithMessage(err, "Failed to get user "+
+			"cryptographic identity from EKV")
+	}
+
+	var resultBuffer bytes.Buffer
+	var result *CryptographicIdentity
+	resultBuffer.Write(obj.Data)
+	dec := gob.NewDecoder(&resultBuffer)
+	err = dec.Decode(result)
+
+	return result, err
+}
+
+func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
+	var userDataBuffer bytes.Buffer
+	enc := gob.NewEncoder(&userDataBuffer)
+	err := enc.Encode(ci)
+	if err != nil {
+		return err
+	}
+
+	obj := &versioned.Object{
+		Version:   currentCryptographicIdentityVersion,
+		Timestamp: time.Now(),
+		Data:      userDataBuffer.Bytes(),
+	}
+
+	return kv.Set(cryptographicIdentityKey, obj)
+}
+
+func (ci *CryptographicIdentity) GetUserID() *id.ID {
+	return ci.userID.DeepCopy()
+}
+
+func (ci *CryptographicIdentity) GetSalt() []byte {
+	return ci.salt
+}
+
+func (ci *CryptographicIdentity) GetRSA() *rsa.PrivateKey {
+	return ci.rsaKey
+}
+
+func (ci *CryptographicIdentity) IsPrecanned() bool {
+	return ci.isPrecanned
+}
diff --git a/storage/user/regValidationSig.go b/storage/user/regValidationSig.go
new file mode 100644
index 0000000000000000000000000000000000000000..89593f40391c2a2d00f002c2b06071f2d7c9b5e4
--- /dev/null
+++ b/storage/user/regValidationSig.go
@@ -0,0 +1,56 @@
+package user
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"time"
+)
+
+const currentRegValidationSigVersion = 0
+const regValidationSigKey = "registrationValidationSignature"
+
+// Returns the Registration Validation Signature stored in RAM. May return
+// nil of no signature is stored
+func (u *User) GetRegistrationValidationSignature() []byte {
+	u.rvsMux.RLock()
+	defer u.rvsMux.RUnlock()
+	return u.regValidationSig
+}
+
+// Loads the Registration Validation Signature if it exists in the ekv
+func (u *User) loadRegistrationValidationSignature() {
+	u.rvsMux.Lock()
+	obj, err := u.kv.Get(regValidationSigKey)
+	if err == nil {
+		u.regValidationSig = obj.Data
+	}
+	u.rvsMux.Unlock()
+}
+
+// Sets the Registration Validation Signature if it is not set and stores it in
+// the ekv
+func (u *User) SetRegistrationValidationSignature(b []byte) error {
+	u.rvsMux.Lock()
+	defer u.rvsMux.Unlock()
+
+	//check if the signature already exists
+	if u.regValidationSig != nil {
+		return errors.New("cannot overwrite existing Registration Validation Signature")
+	}
+
+	obj := &versioned.Object{
+		Version:   currentRegValidationSigVersion,
+		Timestamp: time.Now(),
+		Data:      b,
+	}
+
+	err := u.kv.Set(regValidationSigKey, obj)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to store the "+
+			"Registration Validation Signature")
+	}
+
+	u.regValidationSig = b
+
+	return nil
+}
diff --git a/storage/user/user.go b/storage/user/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..34e6f2e96b20a363b94db77700fb0dd26db1da67
--- /dev/null
+++ b/storage/user/user.go
@@ -0,0 +1,52 @@
+package user
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"sync"
+)
+
+type User struct {
+	ci *CryptographicIdentity
+
+	regValidationSig []byte
+	rvsMux           sync.RWMutex
+
+	username    string
+	usernameMux sync.RWMutex
+
+	kv *versioned.KV
+}
+
+// builds a new user.
+func NewUser(kv *versioned.KV, uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey,
+	isPrecanned bool) (*User, error) {
+
+	ci, err := newCryptographicIdentity(uid, salt, rsaKey, isPrecanned, kv)
+	if err != nil {
+		return nil, errors.WithMessage(err, "Failed to create user "+
+			"due to failure to create cryptographic identity")
+	}
+
+	return &User{ci: ci, kv: kv}, nil
+}
+
+func LoadUser(kv *versioned.KV) (*User, error) {
+	ci, err := loadCryptographicIdentity(kv)
+	if err != nil {
+		return nil, errors.WithMessage(err, "Failed to load user "+
+			"due to failure to load cryptographic identity")
+	}
+
+	u := &User{ci: ci, kv: kv}
+	u.loadRegistrationValidationSignature()
+	u.loadUsername()
+
+	return u, nil
+}
+
+func (u *User) GetCryptographicIdentity() *CryptographicIdentity {
+	return u.ci
+}
diff --git a/storage/user/username.go b/storage/user/username.go
new file mode 100644
index 0000000000000000000000000000000000000000..242f794f64b0674d46da91c3cf63427bdfe9761a
--- /dev/null
+++ b/storage/user/username.go
@@ -0,0 +1,49 @@
+package user
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"time"
+)
+
+const currentUsernameVersion = 0
+const usernameKey = "username"
+
+func (u *User) loadUsername() {
+	u.usernameMux.Lock()
+	obj, err := u.kv.Get(usernameKey)
+	if err == nil {
+		u.username = string(obj.Data)
+	}
+	u.usernameMux.Unlock()
+}
+
+func (u *User) SetUsername(username string) error {
+	u.usernameMux.Lock()
+	defer u.usernameMux.Unlock()
+	if u.username != "" {
+		return errors.New("Cannot set username when already set")
+	}
+
+	obj := &versioned.Object{
+		Version:   currentUsernameVersion,
+		Timestamp: time.Now(),
+		Data:      []byte(username),
+	}
+
+	err := u.kv.Set(usernameKey, obj)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to store the username")
+	}
+
+	return nil
+}
+
+func (u *User) GetUsername() (string, error) {
+	u.usernameMux.RLock()
+	defer u.usernameMux.RUnlock()
+	if u.username == "" {
+		return "", errors.New("no username set")
+	}
+	return u.username, nil
+}
diff --git a/storage/userdata.go b/storage/userdata.go
deleted file mode 100644
index f942a7a60aa1247292dc194533c18f4e095b057c..0000000000000000000000000000000000000000
--- a/storage/userdata.go
+++ /dev/null
@@ -1,101 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
-package storage
-
-import (
-	"bytes"
-	"encoding/gob"
-	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/primitives/id"
-	"time"
-)
-
-// Struct representing a User in the system
-type User struct {
-	User     *id.ID
-	Username string
-	Precan   bool
-}
-
-// DeepCopy performs a deep copy of a user and returns a pointer to the new copy
-func (u *User) DeepCopy() *User {
-	if u == nil {
-		return nil
-	}
-	nu := new(User)
-	nu.User = u.User
-	nu.Username = u.Username
-	nu.Precan = u.Precan
-	return nu
-}
-
-// This whole struct is serialized/deserialized all together
-type UserData struct {
-	// Fields
-	ThisUser         *User
-	RSAPrivateKey    *rsa.PrivateKey
-	RSAPublicKey     *rsa.PublicKey
-	CMIXDHPrivateKey *cyclic.Int
-	CMIXDHPublicKey  *cyclic.Int
-	E2EDHPrivateKey  *cyclic.Int
-	E2EDHPublicKey   *cyclic.Int
-	CmixGrp          *cyclic.Group
-	E2EGrp           *cyclic.Group
-	Salt             []byte
-}
-
-const currentUserDataVersion = 0
-
-func makeUserDataKey() string {
-	return "UserData"
-}
-
-func (s *Session) GetUserData() (*UserData, error) {
-	if s.userData != nil {
-		// We already got this and don't need to get it again
-		return s.userData, nil
-	}
-	obj, err := s.Get(makeUserDataKey())
-	if err != nil {
-		return nil, err
-	}
-
-	var resultBuffer bytes.Buffer
-	var result UserData
-	resultBuffer.Write(obj.Data)
-	dec := gob.NewDecoder(&resultBuffer)
-	err = dec.Decode(&result)
-	if err != nil {
-		return nil, err
-	}
-	s.userData = &result
-	return &result, nil
-}
-
-// Make changes to the user data after getting it, then
-// commit those changes to the ekv store using this
-// I haven't added a mutex to the user data because it's only
-// created once. If you add modification to the user data structure,
-// please
-func (s *Session) CommitUserData(data *UserData) error {
-	// Serialize the data
-	var userDataBuffer bytes.Buffer
-	enc := gob.NewEncoder(&userDataBuffer)
-	err := enc.Encode(data)
-	if err != nil {
-		return err
-	}
-
-	obj := &versioned.Object{
-		Version:   currentUserDataVersion,
-		Timestamp: time.Now(),
-		Data:      userDataBuffer.Bytes(),
-	}
-	return s.Set(makeUserDataKey(), obj)
-}
diff --git a/storage/userdata_test.go b/storage/userdata_test.go
deleted file mode 100644
index 34741c6ab087eb89ac901ab3e46a74d549034a40..0000000000000000000000000000000000000000
--- a/storage/userdata_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package storage
-
-import (
-	"bytes"
-	"gitlab.com/elixxir/client/storage/versioned"
-	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/large"
-	"gitlab.com/elixxir/ekv"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/primitives/id"
-	"math/rand"
-	"reflect"
-	"testing"
-)
-
-// Test committing/retrieving userdata struct
-func TestSession_CommitUserData(t *testing.T) {
-	rsaPrivateKey, err := rsa.GenerateKey(rand.New(rand.NewSource(0)), 64)
-	if err != nil {
-		t.Fatal(err)
-	}
-	// These don't have to represent actual data because they're just stored and retrieved
-	cmixGrp := cyclic.NewGroup(large.NewInt(53), large.NewInt(2))
-	e2eGrp := cyclic.NewGroup(large.NewInt(53), large.NewInt(2))
-	expectedData := &UserData{
-		ThisUser: &User{
-			User:     id.NewIdFromUInt(5, id.User, t),
-			Username: "ted",
-			Precan:   true,
-		},
-		RSAPrivateKey:    rsaPrivateKey,
-		RSAPublicKey:     rsaPrivateKey.GetPublic(),
-		CMIXDHPrivateKey: cmixGrp.NewInt(3),
-		CMIXDHPublicKey:  cmixGrp.NewInt(4),
-		E2EDHPrivateKey:  e2eGrp.NewInt(5),
-		E2EDHPublicKey:   e2eGrp.NewInt(6),
-		CmixGrp:          cmixGrp,
-		E2EGrp:           e2eGrp,
-		Salt:             []byte("potassium permanganate"),
-	}
-
-	// Create a session backed by memory
-	store := make(ekv.Memstore)
-	vkv := versioned.NewKV(store)
-	session := Session{kv: vkv}
-	err = session.CommitUserData(expectedData)
-	if err != nil {
-		t.Fatal(err)
-	}
-	retrievedData, err := session.GetUserData()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	// Field by field comparison
-	if !retrievedData.ThisUser.User.Cmp(expectedData.ThisUser.User) {
-		t.Error("User IDs didn't match")
-	}
-	if retrievedData.ThisUser.Precan != expectedData.ThisUser.Precan {
-		t.Error("User precan didn't match")
-	}
-	if retrievedData.ThisUser.Username != expectedData.ThisUser.Username {
-		t.Error("User names didn't match")
-	}
-	if retrievedData.CMIXDHPublicKey.Cmp(expectedData.CMIXDHPublicKey) != 0 {
-		t.Error("cmix DH public key didn't match")
-	}
-	if retrievedData.CMIXDHPrivateKey.Cmp(expectedData.CMIXDHPrivateKey) != 0 {
-		t.Error("cmix DH private key didn't match")
-	}
-	if retrievedData.E2EDHPrivateKey.Cmp(expectedData.E2EDHPrivateKey) != 0 {
-		t.Error("e2e DH private key didn't match")
-	}
-	if retrievedData.E2EDHPublicKey.Cmp(expectedData.E2EDHPublicKey) != 0 {
-		t.Error("e2e DH public key didn't match")
-	}
-	if !reflect.DeepEqual(retrievedData.CmixGrp, expectedData.CmixGrp) {
-		t.Error("cmix groups didn't match")
-	}
-	if !reflect.DeepEqual(retrievedData.E2EGrp, expectedData.E2EGrp) {
-		t.Error("e2e groups didn't match")
-	}
-	if retrievedData.RSAPrivateKey.D.Cmp(expectedData.RSAPrivateKey.D) != 0 {
-		t.Error("rsa D doesn't match")
-	}
-	if !bytes.Equal(retrievedData.Salt, expectedData.Salt) {
-		t.Error("salts don't match")
-	}
-}
diff --git a/storage/utility/dh.go b/storage/utility/dh.go
new file mode 100644
index 0000000000000000000000000000000000000000..0a892020c29bc991e72081cbf2ea9d68a06a8d28
--- /dev/null
+++ b/storage/utility/dh.go
@@ -0,0 +1,37 @@
+package utility
+
+import (
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"time"
+)
+
+const currentCyclicVersion = 0
+
+func StoreCyclicKey(kv *versioned.KV, cy *cyclic.Int, key string) error {
+	now := time.Now()
+
+	data, err := cy.GobEncode()
+	if err != nil {
+		return err
+	}
+
+	obj := versioned.Object{
+		Version:   currentCyclicVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return kv.Set(key, &obj)
+}
+
+func LoadCyclicKey(kv *versioned.KV, key string) (*cyclic.Int, error) {
+	vo, err := kv.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	cy := &cyclic.Int{}
+
+	return cy, cy.GobDecode(vo.Data)
+}
diff --git a/storage/utility/group.go b/storage/utility/group.go
new file mode 100644
index 0000000000000000000000000000000000000000..60cce18318f8114d42393c9ee4a2e65a8128bf00
--- /dev/null
+++ b/storage/utility/group.go
@@ -0,0 +1,37 @@
+package utility
+
+import (
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"time"
+)
+
+const currentGroupVersion = 0
+
+func StoreGroup(kv *versioned.KV, grp *cyclic.Group, key string) error {
+	now := time.Now()
+
+	data, err := grp.GobEncode()
+	if err != nil {
+		return err
+	}
+
+	obj := versioned.Object{
+		Version:   currentGroupVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return kv.Set(key, &obj)
+}
+
+func LoadGroup(kv *versioned.KV, key string) (*cyclic.Group, error) {
+	vo, err := kv.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	grp := &cyclic.Group{}
+
+	return grp, grp.GobDecode(vo.Data)
+}
diff --git a/userRegistry/user.go b/userRegistry/user.go
index 88185809eae2a8eb455afeb26c85d73636247fbc..25c5330552ca64ad28a0256833541d9755ddc0bd 100644
--- a/userRegistry/user.go
+++ b/userRegistry/user.go
@@ -10,7 +10,7 @@ import (
 	"crypto/sha256"
 	"encoding/binary"
 	"gitlab.com/elixxir/client/globals"
-	"gitlab.com/elixxir/client/storage"
+	user2 "gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/user"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
@@ -34,10 +34,10 @@ func InitUserRegistry(grp *cyclic.Group) {
 
 // Interface for User Registry operations
 type Registry interface {
-	NewUser(id *id.ID, nickname string) *storage.User
+	NewUser(id *id.ID, nickname string) *user2.User
 	DeleteUser(id *id.ID)
-	GetUser(id *id.ID) (user *storage.User, ok bool)
-	UpsertUser(user *storage.User)
+	GetUser(id *id.ID) (user *user2.User, ok bool)
+	UpsertUser(user *user2.User)
 	CountUsers() int
 	LookupUser(hid string) (uid *id.ID, ok bool)
 	LookupKeys(uid *id.ID) (*user.NodeKeys, bool)
@@ -45,7 +45,7 @@ type Registry interface {
 
 type UserMap struct {
 	// Map acting as the User Registry containing User -> ID mapping
-	userCollection map[id.ID]*storage.User
+	userCollection map[id.ID]*user2.User
 	// Increments sequentially for User.ID values
 	idCounter uint64
 	// Temporary map acting as a lookup table for demo user registration codes
@@ -60,7 +60,7 @@ func newRegistry(grp *cyclic.Group) Registry {
 	if len(DemoChannelNames) > 10 || len(DemoUserNicks) > 30 {
 		globals.Log.ERROR.Print("Not enough demo users have been hardcoded.")
 	}
-	userUserIdMap := make(map[id.ID]*storage.User)
+	userUserIdMap := make(map[id.ID]*user2.User)
 	userRegCodeMap := make(map[string]*id.ID)
 	nk := make(map[id.ID]*user.NodeKeys)
 
@@ -70,7 +70,7 @@ func newRegistry(grp *cyclic.Group) Registry {
 		currentID := new(id.ID)
 		binary.BigEndian.PutUint64(currentID[:], i)
 		currentID.SetType(id.User)
-		newUsr := new(storage.User)
+		newUsr := new(user2.User)
 		nodeKey := new(user.NodeKeys)
 
 		// Generate user parameters
@@ -119,13 +119,13 @@ func newRegistry(grp *cyclic.Group) Registry {
 }
 
 // NewUser creates a new User object with default fields and given address.
-func (m *UserMap) NewUser(id *id.ID, username string) *storage.User {
-	return &storage.User{User: id, Username: username}
+func (m *UserMap) NewUser(id *id.ID, username string) *user2.User {
+	return &user2.User{User: id, Username: username}
 }
 
 // GetUser returns a user with the given ID from userCollection
 // and a boolean for whether the user exists
-func (m *UserMap) GetUser(id *id.ID) (user *storage.User, ok bool) {
+func (m *UserMap) GetUser(id *id.ID) (user *user2.User, ok bool) {
 	user, ok = m.userCollection[*id]
 	user = user.DeepCopy()
 	return
@@ -139,7 +139,7 @@ func (m *UserMap) DeleteUser(id *id.ID) {
 
 // UpsertUser inserts given user into userCollection or update the user if it
 // already exists (Upsert operation).
-func (m *UserMap) UpsertUser(user *storage.User) {
+func (m *UserMap) UpsertUser(user *user2.User) {
 	m.userCollection[*user.User] = user
 }