diff --git a/auth/confirm.go b/auth/confirm.go
index e523715c74a421773354216c9e335a5d9157b2fa..ee89b8f1827546c740f8aa23634940e30d26deea 100644
--- a/auth/confirm.go
+++ b/auth/confirm.go
@@ -126,7 +126,7 @@ func (s *state) confirm(partner contact.Contact, serviceTag string) (
 			s.event.Report(10, "Auth", "SendConfirmError", em)
 		}
 
-		//todo: s.backupTrigger("confirmed authenticated channel")
+		s.backupTrigger("confirmed authenticated channel")
 
 		jww.INFO.Printf("Confirming Auth from %s to %s, msgDigest: %s",
 			partner.ID, s.e2e.GetReceptionID(),
diff --git a/auth/receivedConfirm.go b/auth/receivedConfirm.go
index 1990fd5bdca5eeb826573b6c06c9151ce96ce25c..07e12df9beae5cb55889d9eadd29a3361b68b2b3 100644
--- a/auth/receivedConfirm.go
+++ b/auth/receivedConfirm.go
@@ -5,9 +5,9 @@ import (
 	"fmt"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/auth/store"
-	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
 	"gitlab.com/elixxir/client/cmix/message"
+	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 	"gitlab.com/elixxir/crypto/contact"
 	cAuth "gitlab.com/elixxir/crypto/e2e/auth"
@@ -95,7 +95,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
 			"%s : %+v", rcs.GetPartner(), receptionID.Source, err)
 	}
 
-	//todo: trigger backup
+	rcs.s.backupTrigger("received confirmation from request")
 
 	// remove the service used for notifications of the confirm
 	state.net.DeleteService(receptionID.Source, rcs.notificationsService, nil)
diff --git a/auth/state.go b/auth/state.go
index 7ced7eb8d69ca96ef321fd5b3ac5faa625c6dab7..dfb6cb03ce7a7c8060800e7c233e5a7bcdf6a094 100644
--- a/auth/state.go
+++ b/auth/state.go
@@ -33,9 +33,7 @@ import (
 type state struct {
 	callbacks Callbacks
 
-	// net cmix.Client
 	net cmixClient
-	// e2e e2e.Handler
 	e2e e2eHandler
 	rng *fastRNG.StreamGenerator
 
@@ -43,6 +41,8 @@ type state struct {
 	event event.Manager
 
 	params Param
+
+	backupTrigger func(reason string)
 }
 
 type cmixClient interface {
@@ -101,9 +101,10 @@ type Callbacks interface {
 //   NewState and use GetDefaultTemporaryParams() for the parameters
 func NewState(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 	rng *fastRNG.StreamGenerator, event event.Manager, params Param,
-	callbacks Callbacks) (State, error) {
+	callbacks Callbacks, backupTrigger func(reason string)) (State, error) {
 	kv = kv.Prefix(makeStorePrefix(e2e.GetReceptionID()))
-	return NewStateLegacy(kv, net, e2e, rng, event, params, callbacks)
+	return NewStateLegacy(
+		kv, net, e2e, rng, event, params, callbacks, backupTrigger)
 }
 
 // NewStateLegacy loads the auth state or creates new auth state if one cannot be
@@ -113,17 +114,16 @@ func NewState(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 // Otherwise, acts the same as NewState
 func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 	rng *fastRNG.StreamGenerator, event event.Manager, params Param,
-	callbacks Callbacks) (State, error) {
+	callbacks Callbacks, backupTrigger func(reason string)) (State, error) {
 
 	s := &state{
-		callbacks: callbacks,
-
-		net: net,
-		e2e: e2e,
-		rng: rng,
-
-		params: params,
-		event:  event,
+		callbacks:     callbacks,
+		net:           net,
+		e2e:           e2e,
+		rng:           rng,
+		event:         event,
+		params:        params,
+		backupTrigger: backupTrigger,
 	}
 
 	// create the store
@@ -131,7 +131,7 @@ func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 	s.store, err = store.NewOrLoadStore(kv, e2e.GetGroup(),
 		&sentRequestHandler{s: s})
 
-	//register services
+	// register services
 	net.AddService(e2e.GetReceptionID(), message.Service{
 		Identifier: e2e.GetReceptionID()[:],
 		Tag:        params.RequestTag,
diff --git a/backup/backup.go b/backup/backup.go
index ea9667c0391b495b6c1c814cf5cf27f19341002e..291348fa6aa3bbbee8b49e6937013c4ea77b51f6 100644
--- a/backup/backup.go
+++ b/backup/backup.go
@@ -5,34 +5,30 @@
 // LICENSE file                                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                           //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file                                                               //
-////////////////////////////////////////////////////////////////////////////////
-
 package backup
 
 import (
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/primitives/fact"
+	"gitlab.com/xx_network/primitives/id"
 	"sync"
+	"time"
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/api"
-	"gitlab.com/elixxir/client/interfaces"
-	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/xx_network/crypto/signature/rsa"
 )
 
 // Error messages.
 const (
-	// initializeBackup
+	// InitializeBackup
 	errSavePassword      = "failed to save password: %+v"
 	errSaveKeySaltParams = "failed to save key, salt, and params: %+v"
 
-	// resumeBackup
+	// ResumeBackup
 	errLoadPassword = "backup not initialized: load user password failed: %+v"
 
 	// Backup.StopBackup
@@ -46,15 +42,43 @@ type Backup struct {
 	// Callback that is called with the encrypted backup when triggered
 	updateBackupCb UpdateBackupFn
 
-	mux sync.RWMutex
+	container *Container
+
+	jsonParams string
 
 	// Client structures
-	client          *api.Client
-	store           *storage.Session
-	backupContainer *interfaces.BackupContainer
-	rng             *fastRNG.StreamGenerator
+	e2e     E2e
+	session Session
+	ud      UserDiscovery
+	kv      *versioned.KV
+	rng     *fastRNG.StreamGenerator
 
-	jsonParams string
+	mux sync.RWMutex
+}
+
+// E2e is a subset of functions from the interface e2e.Handler.
+type E2e interface {
+	GetAllPartnerIDs() []*id.ID
+	GetHistoricalDHPubkey() *cyclic.Int
+	GetHistoricalDHPrivkey() *cyclic.Int
+}
+
+// Session is a subset of functions from the interface storage.Session.
+type Session interface {
+	GetRegCode() (string, error)
+	GetTransmissionID() *id.ID
+	GetTransmissionSalt() []byte
+	GetReceptionID() *id.ID
+	GetReceptionSalt() []byte
+	GetReceptionRSA() *rsa.PrivateKey
+	GetTransmissionRSA() *rsa.PrivateKey
+	GetTransmissionRegistrationValidationSignature() []byte
+	GetReceptionRegistrationValidationSignature() []byte
+	GetRegistrationTimestamp() time.Time
+}
+
+type UserDiscovery interface {
+	GetFacts() fact.FactList
 }
 
 // UpdateBackupFn is the callback that encrypted backup data is returned on
@@ -68,27 +92,20 @@ type UpdateBackupFn func(encryptedBackup []byte)
 // Call this to turn on backups for the first time or to replace the user's
 // password.
 func InitializeBackup(password string, updateBackupCb UpdateBackupFn,
-	c *api.Client) (*Backup, error) {
-	return initializeBackup(
-		password, updateBackupCb, c, c.GetStorage(), c.GetBackup(), c.GetRng())
-}
-
-// initializeBackup is a helper function that takes in all the fields for Backup
-// as parameters for easier testing.
-func initializeBackup(password string, updateBackupCb UpdateBackupFn,
-	c *api.Client, store *storage.Session,
-	backupContainer *interfaces.BackupContainer, rng *fastRNG.StreamGenerator) (
-	*Backup, error) {
+	container *Container, e2e E2e, session Session, ud UserDiscovery,
+	kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) {
 	b := &Backup{
-		updateBackupCb:  updateBackupCb,
-		client:          c,
-		store:           store,
-		backupContainer: backupContainer,
-		rng:             rng,
+		updateBackupCb: updateBackupCb,
+		container:      container,
+		e2e:            e2e,
+		session:        session,
+		ud:             ud,
+		kv:             kv,
+		rng:            rng,
 	}
 
 	// Save password to storage
-	err := savePassword(password, b.store.GetKV())
+	err := savePassword(password, b.kv)
 	if err != nil {
 		return nil, errors.Errorf(errSavePassword, err)
 	}
@@ -105,15 +122,15 @@ func initializeBackup(password string, updateBackupCb UpdateBackupFn,
 	key := backup.DeriveKey(password, salt, params)
 
 	// Save key, salt, and parameters to storage
-	err = saveBackup(key, salt, params, b.store.GetKV())
+	err = saveBackup(key, salt, params, b.kv)
 	if err != nil {
 		return nil, errors.Errorf(errSaveKeySaltParams, err)
 	}
 
 	// Setting backup trigger in client
-	b.backupContainer.SetBackup(b.TriggerBackup)
+	b.container.SetBackup(b.TriggerBackup)
 
-	b.TriggerBackup("initializeBackup")
+	b.TriggerBackup("InitializeBackup")
 	jww.INFO.Print("Initialized backup with new user key.")
 
 	return b, nil
@@ -122,32 +139,27 @@ func initializeBackup(password string, updateBackupCb UpdateBackupFn,
 // ResumeBackup resumes a backup by restoring the Backup object and registering
 // a new callback. Call this to resume backups that have already been
 // initialized. Returns an error if backups have not already been initialized.
-func ResumeBackup(updateBackupCb UpdateBackupFn, c *api.Client) (*Backup, error) {
-	return resumeBackup(
-		updateBackupCb, c, c.GetStorage(), c.GetBackup(), c.GetRng())
-}
-
-// resumeBackup is a helper function that takes in all the fields for Backup as
-// parameters for easier testing.
-func resumeBackup(updateBackupCb UpdateBackupFn, c *api.Client,
-	store *storage.Session, backupContainer *interfaces.BackupContainer,
+func ResumeBackup(updateBackupCb UpdateBackupFn, container *Container,
+	e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV,
 	rng *fastRNG.StreamGenerator) (*Backup, error) {
-	_, err := loadPassword(store.GetKV())
+	_, err := loadPassword(kv)
 	if err != nil {
 		return nil, errors.Errorf(errLoadPassword, err)
 	}
 
 	b := &Backup{
-		updateBackupCb:  updateBackupCb,
-		client:          c,
-		store:           store,
-		backupContainer: backupContainer,
-		rng:             rng,
-		jsonParams:      loadJson(store.GetKV()),
+		updateBackupCb: updateBackupCb,
+		container:      container,
+		jsonParams:     loadJson(kv),
+		e2e:            e2e,
+		session:        session,
+		ud:             ud,
+		kv:             kv,
+		rng:            rng,
 	}
 
 	// Setting backup trigger in client
-	b.backupContainer.SetBackup(b.TriggerBackup)
+	b.container.SetBackup(b.TriggerBackup)
 
 	jww.INFO.Print("Resumed backup with password loaded from storage.")
 
@@ -181,7 +193,7 @@ func (b *Backup) TriggerBackup(reason string) {
 	b.mux.RLock()
 	defer b.mux.RUnlock()
 
-	key, salt, params, err := loadBackup(b.store.GetKV())
+	key, salt, params, err := loadBackup(b.kv)
 	if err != nil {
 		jww.ERROR.Printf("Backup Failed: could not load key, salt, and "+
 			"parameters for encrypting backup from storage: %+v", err)
@@ -217,7 +229,7 @@ func (b *Backup) AddJson(newJson string) {
 
 	if newJson != b.jsonParams {
 		b.jsonParams = newJson
-		if err := storeJson(newJson, b.store.GetKV()); err != nil {
+		if err := storeJson(newJson, b.kv); err != nil {
 			jww.FATAL.Panicf("Failed to store json: %+v", err)
 		}
 		go b.TriggerBackup("New Json")
@@ -231,12 +243,12 @@ func (b *Backup) StopBackup() error {
 	defer b.mux.Unlock()
 	b.updateBackupCb = nil
 
-	err := deletePassword(b.store.GetKV())
+	err := deletePassword(b.kv)
 	if err != nil {
 		return errors.Errorf(errDeletePassword, err)
 	}
 
-	err = deleteBackup(b.store.GetKV())
+	err = deleteBackup(b.kv)
 	if err != nil {
 		return errors.Errorf(errDeleteCrypto, err)
 	}
@@ -268,42 +280,38 @@ func (b *Backup) assembleBackup() backup.Backup {
 		Contacts:                  backup.Contacts{},
 	}
 
-	// get user and storage user
-	u := b.store.GetUser()
-	su := b.store.User()
-
-	// get registration timestamp
-	bu.RegistrationTimestamp = u.RegistrationTimestamp
+	// Get registration timestamp
+	bu.RegistrationTimestamp = b.session.GetRegistrationTimestamp().UnixNano()
 
-	// get registration code; ignore the error because if there is no
+	// Get registration code; ignore the error because if there is no
 	// registration, then an empty string is returned
-	bu.RegistrationCode, _ = b.store.GetRegCode()
+	bu.RegistrationCode, _ = b.session.GetRegCode()
 
-	// get transmission identity
+	// Get transmission identity
 	bu.TransmissionIdentity = backup.TransmissionIdentity{
-		RSASigningPrivateKey: u.TransmissionRSA,
-		RegistrarSignature:   su.GetTransmissionRegistrationValidationSignature(),
-		Salt:                 u.TransmissionSalt,
-		ComputedID:           u.TransmissionID,
+		RSASigningPrivateKey: b.session.GetTransmissionRSA(),
+		RegistrarSignature:   b.session.GetTransmissionRegistrationValidationSignature(),
+		Salt:                 b.session.GetTransmissionSalt(),
+		ComputedID:           b.session.GetTransmissionID(),
 	}
 
-	// get reception identity
+	// Get reception identity
 	bu.ReceptionIdentity = backup.ReceptionIdentity{
-		RSASigningPrivateKey: u.ReceptionRSA,
-		RegistrarSignature:   su.GetReceptionRegistrationValidationSignature(),
-		Salt:                 u.ReceptionSalt,
-		ComputedID:           u.ReceptionID,
-		DHPrivateKey:         u.E2eDhPrivateKey,
-		DHPublicKey:          u.E2eDhPublicKey,
+		RSASigningPrivateKey: b.session.GetReceptionRSA(),
+		RegistrarSignature:   b.session.GetReceptionRegistrationValidationSignature(),
+		Salt:                 b.session.GetReceptionSalt(),
+		ComputedID:           b.session.GetReceptionID(),
+		DHPrivateKey:         b.e2e.GetHistoricalDHPrivkey(),
+		DHPublicKey:          b.e2e.GetHistoricalDHPubkey(),
 	}
 
-	// get facts
-	bu.UserDiscoveryRegistration.FactList = b.store.GetUd().GetFacts()
+	// Get facts
+	bu.UserDiscoveryRegistration.FactList = b.ud.GetFacts()
 
-	// get contacts
-	bu.Contacts.Identities = b.store.E2e().GetPartners()
+	// Get contacts
+	bu.Contacts.Identities = b.e2e.GetAllPartnerIDs()
 
-	//add the memoized json params
+	// Add the memoized json params
 	bu.JSONParams = b.jsonParams
 
 	return bu
diff --git a/backup/backup_test.go b/backup/backup_test.go
index 434c76e78665692524849952b599652be428600a..076fc2d8c7451dbe039d60fc1c8cd9edc85204e4 100644
--- a/backup/backup_test.go
+++ b/backup/backup_test.go
@@ -9,29 +9,30 @@ package backup
 
 import (
 	"bytes"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/ekv"
 	"reflect"
 	"strings"
 	"testing"
 	"time"
 
-	"gitlab.com/elixxir/client/interfaces"
-	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/crypto/backup"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/xx_network/crypto/csprng"
 )
 
-// Tests that Backup.initializeBackup returns a new Backup with a copy of the
+// Tests that Backup.InitializeBackup returns a new Backup with a copy of the
 // key and the callback.
-func Test_initializeBackup(t *testing.T) {
+func Test_InitializeBackup(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
 	cbChan := make(chan []byte, 2)
 	cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup }
 	expectedPassword := "MySuperSecurePassword"
-	b, err := initializeBackup(expectedPassword, cb, nil,
-		storage.InitTestingSession(t), &interfaces.BackupContainer{},
-		fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG))
+	b, err := InitializeBackup(expectedPassword, cb, &Container{}, newMockE2e(t),
+		newMockSession(t), newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
-		t.Errorf("initializeBackup returned an error: %+v", err)
+		t.Errorf("InitializeBackup returned an error: %+v", err)
 	}
 
 	select {
@@ -41,7 +42,7 @@ func Test_initializeBackup(t *testing.T) {
 	}
 
 	// Check that the correct password is in storage
-	loadedPassword, err := loadPassword(b.store.GetKV())
+	loadedPassword, err := loadPassword(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load password: %+v", err)
 	}
@@ -51,7 +52,7 @@ func Test_initializeBackup(t *testing.T) {
 	}
 
 	// Check that the key, salt, and params were saved to storage
-	key, salt, p, err := loadBackup(b.store.GetKV())
+	key, salt, p, err := loadBackup(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load key, salt, and params: %+v", err)
 	}
@@ -80,17 +81,17 @@ func Test_initializeBackup(t *testing.T) {
 	}
 }
 
-// Initialises a new backup and then tests that Backup.resumeBackup overwrites
-// the callback but keeps the password.
-func Test_resumeBackup(t *testing.T) {
+// Initialises a new backup and then tests that ResumeBackup overwrites the
+// callback but keeps the password.
+func Test_ResumeBackup(t *testing.T) {
 	// Start the first backup
+	kv := versioned.NewKV(make(ekv.Memstore))
+	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
 	cbChan1 := make(chan []byte)
 	cb1 := func(encryptedBackup []byte) { cbChan1 <- encryptedBackup }
-	s := storage.InitTestingSession(t)
 	expectedPassword := "MySuperSecurePassword"
-	b, err := initializeBackup(expectedPassword, cb1, nil, s,
-		&interfaces.BackupContainer{},
-		fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG))
+	b, err := InitializeBackup(expectedPassword, cb1, &Container{},
+		newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
 		t.Errorf("Failed to initialize new Backup: %+v", err)
 	}
@@ -102,7 +103,7 @@ func Test_resumeBackup(t *testing.T) {
 	}
 
 	// get key and salt to compare to later
-	key1, salt1, _, err := loadBackup(b.store.GetKV())
+	key1, salt1, _, err := loadBackup(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load key, salt, and params from newly "+
 			"initialized backup: %+v", err)
@@ -111,14 +112,14 @@ func Test_resumeBackup(t *testing.T) {
 	// Resume the backup with a new callback
 	cbChan2 := make(chan []byte)
 	cb2 := func(encryptedBackup []byte) { cbChan2 <- encryptedBackup }
-	b2, err := resumeBackup(cb2, nil, s, &interfaces.BackupContainer{},
-		fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG))
+	b2, err := ResumeBackup(cb2, &Container{}, newMockE2e(t), newMockSession(t),
+		newMockUserDiscovery(), kv, rngGen)
 	if err != nil {
-		t.Errorf("resumeBackup returned an error: %+v", err)
+		t.Errorf("ResumeBackup returned an error: %+v", err)
 	}
 
 	// Check that the correct password is in storage
-	loadedPassword, err := loadPassword(b.store.GetKV())
+	loadedPassword, err := loadPassword(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load password: %+v", err)
 	}
@@ -128,7 +129,7 @@ func Test_resumeBackup(t *testing.T) {
 	}
 
 	// get key, salt, and parameters of resumed backup
-	key2, salt2, _, err := loadBackup(b.store.GetKV())
+	key2, salt2, _, err := loadBackup(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load key, salt, and params from resumed "+
 			"backup: %+v", err)
@@ -158,14 +159,16 @@ func Test_resumeBackup(t *testing.T) {
 	}
 }
 
-// Error path: Tests that Backup.resumeBackup returns an error if no password is
+// Error path: Tests that ResumeBackup returns an error if no password is
 // present in storage.
-func Test_resumeBackup_NoKeyError(t *testing.T) {
+func Test_ResumeBackup_NoKeyError(t *testing.T) {
 	expectedErr := strings.Split(errLoadPassword, "%")[0]
-	s := storage.InitTestingSession(t)
-	_, err := resumeBackup(nil, nil, s, &interfaces.BackupContainer{}, nil)
+	kv := versioned.NewKV(make(ekv.Memstore))
+	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
+	_, err := ResumeBackup(nil, &Container{}, newMockE2e(t), newMockSession(t),
+		newMockUserDiscovery(), kv, rngGen)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
-		t.Errorf("resumeBackup did not return the expected error when no "+
+		t.Errorf("ResumeBackup did not return the expected error when no "+
 			"password is present.\nexpected: %s\nreceived: %+v", expectedErr, err)
 	}
 }
@@ -178,7 +181,7 @@ func TestBackup_TriggerBackup(t *testing.T) {
 	b := newTestBackup("MySuperSecurePassword", cb, t)
 
 	// get password
-	password, err := loadPassword(b.store.GetKV())
+	password, err := loadPassword(b.kv)
 	if err != nil {
 		t.Errorf("Failed to load password from storage: %+v", err)
 	}
@@ -215,7 +218,7 @@ func TestBackup_TriggerBackup_NoKey(t *testing.T) {
 		t.Errorf("backup not called")
 	}
 
-	err := deleteBackup(b.store.GetKV())
+	err := deleteBackup(b.kv)
 	if err != nil {
 		t.Errorf("Failed to delete key, salt, and params: %+v", err)
 	}
@@ -260,13 +263,13 @@ func TestBackup_StopBackup(t *testing.T) {
 	}
 
 	// Make sure password is deleted
-	password, err := loadPassword(b.store.GetKV())
+	password, err := loadPassword(b.kv)
 	if err == nil || len(password) != 0 {
 		t.Errorf("Loaded password that should be deleted: %q", password)
 	}
 
 	// Make sure key, salt, and params are deleted
-	key, salt, p, err := loadBackup(b.store.GetKV())
+	key, salt, p, err := loadBackup(b.kv)
 	if err == nil || len(key) != 0 || len(salt) != 0 || p != (backup.Params{}) {
 		t.Errorf("Loaded key, salt, and params that should be deleted.")
 	}
@@ -296,77 +299,79 @@ func TestBackup_IsBackupRunning(t *testing.T) {
 
 func TestBackup_AddJson(t *testing.T) {
 	b := newTestBackup("MySuperSecurePassword", nil, t)
-	s := b.store
+	s := b.session.(*mockSession)
+	e2e := b.e2e.(*mockE2e)
 	json := "{'data': {'one': 1}}"
 
-	expectedCollatedBackup := backup.Backup{
-		RegistrationTimestamp: s.GetUser().RegistrationTimestamp,
+	expected := backup.Backup{
+		RegistrationCode:      s.regCode,
+		RegistrationTimestamp: s.registrationTimestamp.UnixNano(),
 		TransmissionIdentity: backup.TransmissionIdentity{
-			RSASigningPrivateKey: s.GetUser().TransmissionRSA,
-			RegistrarSignature:   s.User().GetTransmissionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().TransmissionSalt,
-			ComputedID:           s.GetUser().TransmissionID,
+			RSASigningPrivateKey: s.transmissionRSA,
+			RegistrarSignature:   s.transmissionRegistrationValidationSignature,
+			Salt:                 s.transmissionSalt,
+			ComputedID:           s.transmissionID,
 		},
 		ReceptionIdentity: backup.ReceptionIdentity{
-			RSASigningPrivateKey: s.GetUser().ReceptionRSA,
-			RegistrarSignature:   s.User().GetReceptionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().ReceptionSalt,
-			ComputedID:           s.GetUser().ReceptionID,
-			DHPrivateKey:         s.GetUser().E2eDhPrivateKey,
-			DHPublicKey:          s.GetUser().E2eDhPublicKey,
+			RSASigningPrivateKey: s.receptionRSA,
+			RegistrarSignature:   s.receptionRegistrationValidationSignature,
+			Salt:                 s.receptionSalt,
+			ComputedID:           s.receptionID,
+			DHPrivateKey:         e2e.historicalDHPrivkey,
+			DHPublicKey:          e2e.historicalDHPubkey,
 		},
 		UserDiscoveryRegistration: backup.UserDiscoveryRegistration{
-			FactList: s.GetUd().GetFacts(),
+			FactList: b.ud.(*mockUserDiscovery).facts,
 		},
-		Contacts:   backup.Contacts{Identities: s.E2e().GetPartners()},
+		Contacts:   backup.Contacts{Identities: e2e.partnerIDs},
 		JSONParams: json,
 	}
 
 	b.AddJson(json)
 
 	collatedBackup := b.assembleBackup()
-	if !reflect.DeepEqual(expectedCollatedBackup, collatedBackup) {
+	if !reflect.DeepEqual(expected, collatedBackup) {
 		t.Errorf("Collated backup does not match expected."+
-			"\nexpected: %+v\nreceived: %+v",
-			expectedCollatedBackup, collatedBackup)
+			"\nexpected: %+v\nreceived: %+v", expected, collatedBackup)
 	}
 }
 
 func TestBackup_AddJson_badJson(t *testing.T) {
 	b := newTestBackup("MySuperSecurePassword", nil, t)
-	s := b.store
+	s := b.session.(*mockSession)
+	e2e := b.e2e.(*mockE2e)
 	json := "abc{'i'm a bad json: 'one': 1'''}}"
 
-	expectedCollatedBackup := backup.Backup{
-		RegistrationTimestamp: s.GetUser().RegistrationTimestamp,
+	expected := backup.Backup{
+		RegistrationCode:      s.regCode,
+		RegistrationTimestamp: s.registrationTimestamp.UnixNano(),
 		TransmissionIdentity: backup.TransmissionIdentity{
-			RSASigningPrivateKey: s.GetUser().TransmissionRSA,
-			RegistrarSignature:   s.User().GetTransmissionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().TransmissionSalt,
-			ComputedID:           s.GetUser().TransmissionID,
+			RSASigningPrivateKey: s.transmissionRSA,
+			RegistrarSignature:   s.transmissionRegistrationValidationSignature,
+			Salt:                 s.transmissionSalt,
+			ComputedID:           s.transmissionID,
 		},
 		ReceptionIdentity: backup.ReceptionIdentity{
-			RSASigningPrivateKey: s.GetUser().ReceptionRSA,
-			RegistrarSignature:   s.User().GetReceptionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().ReceptionSalt,
-			ComputedID:           s.GetUser().ReceptionID,
-			DHPrivateKey:         s.GetUser().E2eDhPrivateKey,
-			DHPublicKey:          s.GetUser().E2eDhPublicKey,
+			RSASigningPrivateKey: s.receptionRSA,
+			RegistrarSignature:   s.receptionRegistrationValidationSignature,
+			Salt:                 s.receptionSalt,
+			ComputedID:           s.receptionID,
+			DHPrivateKey:         e2e.historicalDHPrivkey,
+			DHPublicKey:          e2e.historicalDHPubkey,
 		},
 		UserDiscoveryRegistration: backup.UserDiscoveryRegistration{
-			FactList: s.GetUd().GetFacts(),
+			FactList: b.ud.(*mockUserDiscovery).facts,
 		},
-		Contacts:   backup.Contacts{Identities: s.E2e().GetPartners()},
+		Contacts:   backup.Contacts{Identities: e2e.partnerIDs},
 		JSONParams: json,
 	}
 
 	b.AddJson(json)
 
 	collatedBackup := b.assembleBackup()
-	if !reflect.DeepEqual(expectedCollatedBackup, collatedBackup) {
+	if !reflect.DeepEqual(expected, collatedBackup) {
 		t.Errorf("Collated backup does not match expected."+
-			"\nexpected: %+v\nreceived: %+v",
-			expectedCollatedBackup, collatedBackup)
+			"\nexpected: %+v\nreceived: %+v", expected, collatedBackup)
 	}
 }
 
@@ -374,47 +379,51 @@ func TestBackup_AddJson_badJson(t *testing.T) {
 // results.
 func TestBackup_assembleBackup(t *testing.T) {
 	b := newTestBackup("MySuperSecurePassword", nil, t)
-	s := b.store
+	s := b.session.(*mockSession)
+	e2e := b.e2e.(*mockE2e)
 
-	expectedCollatedBackup := backup.Backup{
-		RegistrationTimestamp: s.GetUser().RegistrationTimestamp,
+	expected := backup.Backup{
+		RegistrationCode:      s.regCode,
+		RegistrationTimestamp: s.registrationTimestamp.UnixNano(),
 		TransmissionIdentity: backup.TransmissionIdentity{
-			RSASigningPrivateKey: s.GetUser().TransmissionRSA,
-			RegistrarSignature:   s.User().GetTransmissionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().TransmissionSalt,
-			ComputedID:           s.GetUser().TransmissionID,
+			RSASigningPrivateKey: s.transmissionRSA,
+			RegistrarSignature:   s.transmissionRegistrationValidationSignature,
+			Salt:                 s.transmissionSalt,
+			ComputedID:           s.transmissionID,
 		},
 		ReceptionIdentity: backup.ReceptionIdentity{
-			RSASigningPrivateKey: s.GetUser().ReceptionRSA,
-			RegistrarSignature:   s.User().GetReceptionRegistrationValidationSignature(),
-			Salt:                 s.GetUser().ReceptionSalt,
-			ComputedID:           s.GetUser().ReceptionID,
-			DHPrivateKey:         s.GetUser().E2eDhPrivateKey,
-			DHPublicKey:          s.GetUser().E2eDhPublicKey,
+			RSASigningPrivateKey: s.receptionRSA,
+			RegistrarSignature:   s.receptionRegistrationValidationSignature,
+			Salt:                 s.receptionSalt,
+			ComputedID:           s.receptionID,
+			DHPrivateKey:         e2e.historicalDHPrivkey,
+			DHPublicKey:          e2e.historicalDHPubkey,
 		},
 		UserDiscoveryRegistration: backup.UserDiscoveryRegistration{
-			FactList: s.GetUd().GetFacts(),
+			FactList: b.ud.(*mockUserDiscovery).facts,
 		},
-		Contacts: backup.Contacts{Identities: s.E2e().GetPartners()},
+		Contacts: backup.Contacts{Identities: e2e.partnerIDs},
 	}
 
 	collatedBackup := b.assembleBackup()
 
-	if !reflect.DeepEqual(expectedCollatedBackup, collatedBackup) {
+	if !reflect.DeepEqual(expected, collatedBackup) {
 		t.Errorf("Collated backup does not match expected."+
 			"\nexpected: %+v\nreceived: %+v",
-			expectedCollatedBackup, collatedBackup)
+			expected, collatedBackup)
 	}
 }
 
 // newTestBackup creates a new Backup for testing.
 func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup {
-	b, err := initializeBackup(
+	b, err := InitializeBackup(
 		password,
 		cb,
-		nil,
-		storage.InitTestingSession(t),
-		&interfaces.BackupContainer{},
+		&Container{},
+		newMockE2e(t),
+		newMockSession(t),
+		newMockUserDiscovery(),
+		versioned.NewKV(make(ekv.Memstore)),
 		fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
 	)
 	if err != nil {
diff --git a/interfaces/backup.go b/backup/container.go
similarity index 83%
rename from interfaces/backup.go
rename to backup/container.go
index 559b4b0f8756ee772aba9064757601d2ade417d6..fd456ea96c11337c4709991c97f6b84458adfe11 100644
--- a/interfaces/backup.go
+++ b/backup/container.go
@@ -5,14 +5,14 @@
 // LICENSE file                                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-package interfaces
+package backup
 
 import "sync"
 
 type TriggerBackup func(reason string)
 
-// BackupContainer contains the trigger to call to initiate a backup.
-type BackupContainer struct {
+// Container contains the trigger to call to initiate a backup.
+type Container struct {
 	triggerBackup TriggerBackup
 	mux           sync.RWMutex
 }
@@ -22,7 +22,7 @@ type BackupContainer struct {
 // should be in the paste tense. For example, if a contact is deleted, the
 // reason can be "contact deleted" and the log will show:
 //	Triggering backup: contact deleted
-func (bc *BackupContainer) TriggerBackup(reason string) {
+func (bc *Container) TriggerBackup(reason string) {
 	bc.mux.RLock()
 	defer bc.mux.RUnlock()
 	if bc.triggerBackup != nil {
@@ -32,7 +32,7 @@ func (bc *BackupContainer) TriggerBackup(reason string) {
 
 // SetBackup sets the backup trigger function which will cause a backup to start
 // on the next event that triggers is.
-func (bc *BackupContainer) SetBackup(triggerBackup TriggerBackup) {
+func (bc *Container) SetBackup(triggerBackup TriggerBackup) {
 	bc.mux.Lock()
 	defer bc.mux.Unlock()
 
diff --git a/backup/utils_test.go b/backup/utils_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c16969ff89da1f08b29574dba9f20e9da2e4fb44
--- /dev/null
+++ b/backup/utils_test.go
@@ -0,0 +1,156 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package backup
+
+import (
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/primitives/fact"
+	"gitlab.com/xx_network/crypto/large"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"testing"
+	"time"
+)
+
+// Adheres to the E2e interface.
+type mockE2e struct {
+	partnerIDs          []*id.ID
+	historicalDHPubkey  *cyclic.Int
+	historicalDHPrivkey *cyclic.Int
+}
+
+func newMockE2e(t *testing.T) *mockE2e {
+	grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(0))
+	return &mockE2e{
+		partnerIDs: []*id.ID{
+			id.NewIdFromString("partner1", id.User, t),
+			id.NewIdFromString("partner2", id.User, t),
+			id.NewIdFromString("partner3", id.User, t),
+		},
+		historicalDHPubkey:  grp.NewInt(45),
+		historicalDHPrivkey: grp.NewInt(46),
+	}
+}
+func (m *mockE2e) GetAllPartnerIDs() []*id.ID          { return m.partnerIDs }
+func (m *mockE2e) GetHistoricalDHPubkey() *cyclic.Int  { return m.historicalDHPubkey }
+func (m *mockE2e) GetHistoricalDHPrivkey() *cyclic.Int { return m.historicalDHPrivkey }
+
+// Adheres to the Session interface.
+type mockSession struct {
+	regCode                                     string
+	transmissionID                              *id.ID
+	transmissionSalt                            []byte
+	receptionID                                 *id.ID
+	receptionSalt                               []byte
+	receptionRSA                                *rsa.PrivateKey
+	transmissionRSA                             *rsa.PrivateKey
+	transmissionRegistrationValidationSignature []byte
+	receptionRegistrationValidationSignature    []byte
+	registrationTimestamp                       time.Time
+}
+
+func newMockSession(t *testing.T) *mockSession {
+	receptionRSA, _ := rsa.LoadPrivateKeyFromPem([]byte(privKey))
+	transmissionRSA, _ := rsa.LoadPrivateKeyFromPem([]byte(privKey))
+
+	return &mockSession{
+		regCode:          "regCode",
+		transmissionID:   id.NewIdFromString("transmission", id.User, t),
+		transmissionSalt: []byte("transmissionSalt"),
+		receptionID:      id.NewIdFromString("reception", id.User, t),
+		receptionSalt:    []byte("receptionSalt"),
+		receptionRSA:     receptionRSA,
+		transmissionRSA:  transmissionRSA,
+		transmissionRegistrationValidationSignature: []byte("transmissionSig"),
+		receptionRegistrationValidationSignature:    []byte("receptionSig"),
+		registrationTimestamp:                       time.Date(2012, 12, 21, 22, 8, 41, 0, time.UTC),
+	}
+
+}
+func (m mockSession) GetRegCode() (string, error)         { return m.regCode, nil }
+func (m mockSession) GetTransmissionID() *id.ID           { return m.transmissionID }
+func (m mockSession) GetTransmissionSalt() []byte         { return m.transmissionSalt }
+func (m mockSession) GetReceptionID() *id.ID              { return m.receptionID }
+func (m mockSession) GetReceptionSalt() []byte            { return m.receptionSalt }
+func (m mockSession) GetReceptionRSA() *rsa.PrivateKey    { return m.receptionRSA }
+func (m mockSession) GetTransmissionRSA() *rsa.PrivateKey { return m.transmissionRSA }
+func (m mockSession) GetTransmissionRegistrationValidationSignature() []byte {
+	return m.transmissionRegistrationValidationSignature
+}
+func (m mockSession) GetReceptionRegistrationValidationSignature() []byte {
+	return m.receptionRegistrationValidationSignature
+}
+func (m mockSession) GetRegistrationTimestamp() time.Time { return m.registrationTimestamp }
+
+// Adheres to the UserDiscovery interface.
+type mockUserDiscovery struct {
+	facts fact.FactList
+}
+
+func newMockUserDiscovery() *mockUserDiscovery {
+	return &mockUserDiscovery{facts: fact.FactList{
+		{"myUserName", fact.Username},
+		{"hello@example.com", fact.Email},
+		{"6175555212", fact.Phone},
+		{"name", fact.Nickname},
+	}}
+}
+func (m mockUserDiscovery) GetFacts() fact.FactList { return m.facts }
+
+const privKey = `-----BEGIN PRIVATE KEY-----
+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
+OaRA5ZbdE7g7vxKRV36jT3wvD7W+
+-----END PRIVATE KEY-----`
diff --git a/e2e/ratchet/partner/utils.go b/e2e/ratchet/partner/utils.go
new file mode 100644
index 0000000000000000000000000000000000000000..55a25ab9b2f9da82f655eed4dcf85b2331fffa9a
--- /dev/null
+++ b/e2e/ratchet/partner/utils.go
@@ -0,0 +1,113 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package partner
+
+import (
+	"github.com/cloudflare/circl/dh/sidh"
+	"gitlab.com/elixxir/client/cmix/message"
+	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
+	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/xx_network/primitives/id"
+	"testing"
+)
+
+// Test implementation of the Manager interface
+type testManager struct {
+	partnerId                *id.ID
+	grp                      *cyclic.Group
+	partnerPubKey, myPrivKey *cyclic.Int
+}
+
+// NewTestManager allows creation of a Manager interface object for testing purposes
+// Backwards compatibility must be maintained if you make changes here
+// Currently used for: Group chat testing
+func NewTestManager(partnerId *id.ID, partnerPubKey, myPrivKey *cyclic.Int, t *testing.T) Manager {
+	return &testManager{partnerId: partnerId, partnerPubKey: partnerPubKey, myPrivKey: myPrivKey}
+}
+
+func (p *testManager) GetPartnerID() *id.ID {
+	return p.partnerId
+}
+
+func (p *testManager) GetMyID() *id.ID {
+	panic("implement me")
+}
+
+func (p *testManager) GetMyOriginPrivateKey() *cyclic.Int {
+	return p.myPrivKey
+}
+
+func (p *testManager) GetPartnerOriginPublicKey() *cyclic.Int {
+	return p.partnerPubKey
+}
+
+func (p *testManager) GetSendRelationshipFingerprint() []byte {
+	panic("implement me")
+}
+
+func (p *testManager) GetReceiveRelationshipFingerprint() []byte {
+	panic("implement me")
+}
+
+func (p *testManager) GetConnectionFingerprintBytes() []byte {
+	panic("implement me")
+}
+
+func (p *testManager) GetConnectionFingerprint() string {
+	panic("implement me")
+}
+
+func (p *testManager) GetContact() contact.Contact {
+	panic("implement me")
+}
+
+func (p *testManager) PopSendCypher() (*session.Cypher, error) {
+	panic("implement me")
+}
+
+func (p *testManager) PopRekeyCypher() (*session.Cypher, error) {
+	panic("implement me")
+}
+
+func (p *testManager) NewReceiveSession(partnerPubKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, e2eParams session.Params, source *session.Session) (*session.Session, bool) {
+	panic("implement me")
+}
+
+func (p *testManager) NewSendSession(myDHPrivKey *cyclic.Int, mySIDHPrivateKey *sidh.PrivateKey, e2eParams session.Params, source *session.Session) *session.Session {
+	panic("implement me")
+}
+
+func (p *testManager) GetSendSession(sid session.SessionID) *session.Session {
+	panic("implement me")
+}
+
+func (p *testManager) GetReceiveSession(sid session.SessionID) *session.Session {
+	panic("implement me")
+}
+
+func (p *testManager) Confirm(sid session.SessionID) error {
+	panic("implement me")
+}
+
+func (p *testManager) TriggerNegotiations() []*session.Session {
+	panic("implement me")
+}
+
+func (p *testManager) MakeService(tag string) message.Service {
+	panic("implement me")
+}
+
+func (p *testManager) Delete() error {
+	panic("implement me")
+}
diff --git a/groupChat/makeGroup.go b/groupChat/makeGroup.go
index d8f6dd8c32d3f01c97724d497c6b3beafcc44ee0..cc0d22da3119d16a05b7f5dade00cc928ff1cf58 100644
--- a/groupChat/makeGroup.go
+++ b/groupChat/makeGroup.go
@@ -29,7 +29,6 @@ const (
 	makeMembershipErr = "failed to assemble group chat membership: %+v"
 	newIdPreimageErr  = "failed to create group ID preimage: %+v"
 	newKeyPreimageErr = "failed to create group key preimage: %+v"
-	addGroupErr       = "failed to save new group: %+v"
 )
 
 // MaxInitMessageSize is the maximum allowable length of the initial message
@@ -81,16 +80,12 @@ func (m Manager) MakeGroup(membership []*id.ID, name, msg []byte) (gs.Group,
 	// Create new group and add to manager
 	g := gs.NewGroup(
 		name, groupID, groupKey, idPreimage, keyPreimage, msg, created, mem, dkl)
-	if err = m.gs.Add(g); err != nil {
-		return gs.Group{}, nil, NotSent, errors.Errorf(addGroupErr, err)
-	}
 
 	jww.DEBUG.Printf("Created new group %q with ID %s and %d members %s",
 		g.Name, g.ID, len(g.Members), g.Members)
 
 	// Send all group requests
 	roundIDs, status, err := m.sendRequests(g)
-
 	if err == nil {
 		err = m.JoinGroup(g)
 	}
diff --git a/groupChat/makeGroup_test.go b/groupChat/makeGroup_test.go
index eb0676859a739945e6dd2821a97ac4d31da64586..a9541b84471d9d35db12787731916d761f5294e7 100644
--- a/groupChat/makeGroup_test.go
+++ b/groupChat/makeGroup_test.go
@@ -121,7 +121,7 @@ func TestManager_MakeGroup_AddGroupError(t *testing.T) {
 	prng := rand.New(rand.NewSource(42))
 	m, _ := newTestManagerWithStore(prng, gs.MaxGroupChats, 0, nil, nil, t)
 	memberIDs, _, _ := addPartners(m, t)
-	expectedErr := strings.SplitN(addGroupErr, "%", 2)[0]
+	expectedErr := strings.SplitN(joinGroupErr, "%", 2)[0]
 
 	_, _, _, err := m.MakeGroup(memberIDs, []byte{}, []byte{})
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
diff --git a/groupChat/manager.go b/groupChat/manager.go
index c67aae9bcb9c677d05709634ae8aca95e000d95e..19c4de8bbca37c62fb7284e9c52701b865f7abba 100644
--- a/groupChat/manager.go
+++ b/groupChat/manager.go
@@ -44,6 +44,7 @@ type GroupCmix interface {
 		response message.Processor)
 	DeleteService(clientID *id.ID, toDelete message.Service,
 		processor message.Processor)
+	GetMaxMessageLength() int
 }
 
 // GroupE2e is a subset of the e2e.Handler interface containing only the methods needed by GroupChat
diff --git a/groupChat/manager_test.go b/groupChat/manager_test.go
index 9cf51c8bcded7fd73381fff79d05a2cf57027604..5a9c30cdc4db6e31d486bdd54a7a5243b846a30d 100644
--- a/groupChat/manager_test.go
+++ b/groupChat/manager_test.go
@@ -31,7 +31,7 @@ func Test_newManager(t *testing.T) {
 	requestFunc := func(g gs.Group) { requestChan <- g }
 	receiveChan := make(chan MessageReceive)
 	receiveFunc := func(msg MessageReceive) { receiveChan <- msg }
-	m, err := NewManager(nil, nil, user.ID, nil, nil, kv, requestFunc, receiveFunc)
+	m, err := NewManager(nil, newTestE2eManager(user.DhKey), user.ID, nil, nil, kv, requestFunc, receiveFunc)
 	if err != nil {
 		t.Errorf("newManager() returned an error: %+v", err)
 	}
@@ -84,7 +84,7 @@ func Test_newManager_LoadStorage(t *testing.T) {
 		}
 	}
 
-	m, err := NewManager(nil, nil, user.ID, nil, nil, kv, nil, nil)
+	m, err := NewManager(newTestNetworkManager(0, t), newTestE2eManager(user.DhKey), user.ID, nil, nil, kv, nil, nil)
 	if err != nil {
 		t.Errorf("newManager() returned an error: %+v", err)
 	}
@@ -118,7 +118,7 @@ func Test_newManager_LoadError(t *testing.T) {
 
 	expectedErr := strings.SplitN(newGroupStoreErr, "%", 2)[0]
 
-	_, err = NewManager(nil, nil, user.ID, nil, nil, kv, nil, nil)
+	_, err = NewManager(nil, newTestE2eManager(user.DhKey), user.ID, nil, nil, kv, nil, nil)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("newManager() did not return the expected error."+
 			"\nexpected: %s\nreceived: %+v", expectedErr, err)
diff --git a/groupChat/receive.go b/groupChat/receive.go
index b559a0b0d4776cd70425f86c0744b3b6eac2b5f4..503a52fa79434510348680b442596c1a6b3dff5c 100644
--- a/groupChat/receive.go
+++ b/groupChat/receive.go
@@ -38,7 +38,6 @@ type receptionProcessor struct {
 // Process incoming group chat messages
 func (p *receptionProcessor) Process(message format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 	jww.TRACE.Print("Group message reception received cMix message.")
-
 	// Attempt to read the message
 	roundTimestamp := round.Timestamps[states.QUEUED]
 
@@ -117,7 +116,6 @@ func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte,
 
 	// Compute the current epoch
 	epoch := group.ComputeEpoch(roundTimestamp)
-
 	for _, dhKey := range dhKeys {
 
 		// Create a key with the correct epoch
diff --git a/groupChat/receiveRequest.go b/groupChat/receiveRequest.go
index 127cd9a37ad2297d931974936dc74e279fcf9a53..3a8741d6b0a7e494c137ac53c6f1f7de9834a389 100644
--- a/groupChat/receiveRequest.go
+++ b/groupChat/receiveRequest.go
@@ -89,7 +89,7 @@ func (m *Manager) readRequest(msg receive.Message) (gs.Group, error) {
 
 	// Generate the DH keys with each group member
 	privKey := partner.GetMyOriginPrivateKey()
-	dkl := gs.GenerateDhKeyList(m.gs.GetUser().ID, privKey, membership, m.grp)
+	dkl := gs.GenerateDhKeyList(m.receptionId, privKey, membership, m.grp)
 
 	// Restore the original public key for the leader so that the membership
 	// digest generated later is correct
diff --git a/groupChat/receiveRequest_test.go b/groupChat/receiveRequest_test.go
index 265309f6e92fe1057e495143029550b4f9360325..398de2f495a348b2f34323cadee1d060074834e0 100644
--- a/groupChat/receiveRequest_test.go
+++ b/groupChat/receiveRequest_test.go
@@ -66,7 +66,7 @@ func TestRequestListener_Hear(t *testing.T) {
 	_, _ = m.e2e.AddPartner(
 		g.Members[0].ID,
 		g.Members[0].DhKey,
-		m.grp.NewInt(2),
+		m.e2e.GetHistoricalDHPrivkey(),
 		theirSIDHPubKey, mySIDHPrivKey,
 		session.GetDefaultParams(),
 		session.GetDefaultParams(),
@@ -165,7 +165,7 @@ func TestManager_readRequest(t *testing.T) {
 	_, _ = m.e2e.AddPartner(
 		g.Members[0].ID,
 		g.Members[0].DhKey,
-		m.grp.NewInt(2),
+		m.e2e.GetHistoricalDHPrivkey(),
 		theirSIDHPubKey, mySIDHPrivKey,
 		session.GetDefaultParams(),
 		session.GetDefaultParams(),
diff --git a/groupChat/send.go b/groupChat/send.go
index dfcc522ef11627cd3ccb32648e8b7549f1a45858..64796dd35111424ff438b5ce2b6d7f721cb2083d 100644
--- a/groupChat/send.go
+++ b/groupChat/send.go
@@ -27,7 +27,6 @@ import (
 const (
 	newCmixMsgErr     = "failed to generate cMix messages for group chat: %+v"
 	sendManyCmixErr   = "failed to send group chat message from member %s to group %s: %+v"
-	newCmixErr        = "failed to generate cMix message for member %d with ID %s in group %s: %+v"
 	messageLenErr     = "message length %d is greater than maximum message space %d"
 	newNoGroupErr     = "failed to create message for group %s that cannot be found"
 	newKeyErr         = "failed to generate key for encrypting group payload"
@@ -94,7 +93,7 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
 		}
 
 		// Add cMix message to list
-		cMixMsg, err := newCmixMsg(g, msg, timestamp, member, rng, m.receptionId, m.grp)
+		cMixMsg, err := newCmixMsg(g, msg, timestamp, member, rng, m.receptionId, m.services.GetMaxMessageLength())
 		if err != nil {
 			return nil, err
 		}
@@ -106,7 +105,7 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
 
 // newCmixMsg generates a new cMix message to be sent to a group member.
 func newCmixMsg(g gs.Group, msg []byte, timestamp time.Time,
-	mem group.Member, rng io.Reader, senderId *id.ID, grp *cyclic.Group) (cmix.TargetedCmixMessage, error) {
+	mem group.Member, rng io.Reader, senderId *id.ID, maxCmixMessageSize int) (cmix.TargetedCmixMessage, error) {
 
 	// Initialize targeted message
 	cmixMsg := cmix.TargetedCmixMessage{
@@ -119,7 +118,7 @@ func newCmixMsg(g gs.Group, msg []byte, timestamp time.Time,
 	}
 
 	// Create three message layers
-	pubMsg, intlMsg, err := newMessageParts(grp.GetP().ByteLen())
+	pubMsg, intlMsg, err := newMessageParts(maxCmixMessageSize)
 	if err != nil {
 		return cmixMsg, err
 	}
diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go
index f87b53bb9b3d3c761145897d2c70c2dcd01f02e0..3bc201d41ecd77df369a85ba44a47056c456e22d 100644
--- a/groupChat/sendRequests.go
+++ b/groupChat/sendRequests.go
@@ -118,7 +118,7 @@ func (m Manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, error
 	p.LastServiceTag = catalog.GroupRq
 	p.CMIX.DebugTag = "group.Request"
 
-	rounds, _, _, err := m.e2e.SendE2E(catalog.GroupCreationRequest, m.receptionId, request, p)
+	rounds, _, _, err := m.e2e.SendE2E(catalog.GroupCreationRequest, memberID, request, p)
 	if err != nil {
 		return nil, errors.Errorf(sendE2eErr, memberID, err)
 	}
diff --git a/groupChat/send_test.go b/groupChat/send_test.go
index ec257fd4e11dd2bbadc9f614fcb5b1afc12c4972..72d98232909c7d10f401e7805b0be4ef52393765 100644
--- a/groupChat/send_test.go
+++ b/groupChat/send_test.go
@@ -10,11 +10,12 @@ package groupChat
 import (
 	"bytes"
 	"encoding/base64"
-	"gitlab.com/elixxir/client/cmix/rounds"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
 	"gitlab.com/elixxir/crypto/group"
 	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
 	"math/rand"
@@ -50,8 +51,10 @@ func TestManager_Send(t *testing.T) {
 		t.Error("No group cMix messages received.")
 	}
 
+	timestamps := make(map[states.Round]time.Time)
+	timestamps[states.QUEUED] = netTime.Now().Round(0)
 	for _, msg := range messages {
-		reception.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{ID: roundId})
+		reception.Process(msg, receptionID.EphemeralIdentity{}, rounds.Round{ID: roundId, Timestamps: timestamps})
 		select {
 		case result := <-receiveChan:
 			if !result.SenderID.Cmp(m.receptionId) {
@@ -70,26 +73,13 @@ func TestManager_Send(t *testing.T) {
 	}
 }
 
-// Error path: an error is returned when Manager.neCmixMsg returns an error.
-func TestGroup_newMessages_NewCmixMsgError(t *testing.T) {
-	expectedErr := strings.SplitN(newCmixErr, "%", 2)[0]
-	prng := rand.New(rand.NewSource(42))
-	m, g := newTestManager(prng, t)
-
-	_, err := m.newMessages(g, make([]byte, 1000), netTime.Now())
-	if err == nil || !strings.Contains(err.Error(), expectedErr) {
-		t.Errorf("newMessages() failed to return the expected error."+
-			"\nexpected: %s\nreceived: %+v", expectedErr, err)
-	}
-}
-
 // Error path: reader returns an error.
 func TestGroup_newCmixMsg_SaltReaderError(t *testing.T) {
 	expectedErr := strings.SplitN(saltReadErr, "%", 2)[0]
-	m := &Manager{}
+	m, _ := newTestManager(rand.New(rand.NewSource(42)), t)
 
-	_, err := newCmixMsg(gs.Group{},
-		[]byte{}, time.Time{}, group.Member{}, strings.NewReader(""), m.receptionId, m.grp)
+	_, err := newCmixMsg(gs.Group{ID: id.NewIdFromString("test", id.User, t)},
+		[]byte{}, time.Time{}, group.Member{}, strings.NewReader(""), m.receptionId, m.services.GetMaxMessageLength())
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("newCmixMsg() failed to return the expected error"+
 			"\nexpected: %s\nreceived: %+v", expectedErr, err)
@@ -102,15 +92,15 @@ func TestGroup_newCmixMsg_InternalMsgSizeError(t *testing.T) {
 
 	// Create new test Manager and Group
 	prng := rand.New(rand.NewSource(42))
-	m, g := newTestManager(prng, t)
+	m, g := newTestManagerWithStore(prng, 10, 0, nil, nil, t)
 
 	// Create test parameters
-	testMsg := make([]byte, 341)
+	testMsg := make([]byte, 1500)
 	mem := group.Member{ID: id.NewIdFromString("memberID", id.User, t)}
 
 	// Create cMix message
 	prng = rand.New(rand.NewSource(42))
-	_, err := newCmixMsg(g, testMsg, netTime.Now(), mem, prng, m.receptionId, m.grp)
+	_, err := newCmixMsg(g, testMsg, netTime.Now(), mem, prng, m.receptionId, m.services.GetMaxMessageLength())
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("newCmixMsg() failed to return the expected error"+
 			"\nexpected: %s\nreceived: %+v", expectedErr, err)
diff --git a/groupChat/utils_test.go b/groupChat/utils_test.go
index 4854e56500b3964a01628475f8e9a17d69a86264..afbb0ec0604330cb27b35227dcacb93ff0a7f2aa 100644
--- a/groupChat/utils_test.go
+++ b/groupChat/utils_test.go
@@ -47,19 +47,15 @@ func newTestManager(rng *rand.Rand, t *testing.T) (*Manager, gs.Group) {
 		rng:         fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
 		grp:         getGroup(),
 		services:    newTestNetworkManager(0, t),
-		e2e: &testE2eManager{
-			e2eMessages: []testE2eMessage{},
-			errSkip:     0,
-			sendErr:     0,
-		},
+		e2e:         newTestE2eManager(randCycInt(rng)),
 	}
 	user := group.Member{
 		ID:    m.receptionId,
-		DhKey: randCycInt(rng),
+		DhKey: m.e2e.GetHistoricalDHPubkey(),
 	}
 
 	g := newTestGroupWithUser(m.grp, user.ID, user.DhKey,
-		randCycInt(rng), rng, t)
+		m.e2e.GetHistoricalDHPrivkey(), rng, t)
 	gStore, err := gs.NewStore(versioned.NewKV(make(ekv.Memstore)), user)
 	if err != nil {
 		t.Fatalf("Failed to create new group store: %+v", err)
@@ -84,14 +80,15 @@ func newTestManagerWithStore(rng *rand.Rand, numGroups int, sendErr int,
 		services:    newTestNetworkManager(sendErr, t),
 		e2e: &testE2eManager{
 			e2eMessages: []testE2eMessage{},
-			errSkip:     0,
 			sendErr:     sendErr,
+			grp:         getGroup(),
+			dhPubKey:    randCycInt(rng),
+			partners:    make(map[id.ID]partner.Manager),
 		},
 	}
-
 	user := group.Member{
 		ID:    m.receptionId,
-		DhKey: randCycInt(rng),
+		DhKey: m.e2e.GetHistoricalDHPubkey(),
 	}
 
 	gStore, err := gs.NewStore(versioned.NewKV(make(ekv.Memstore)), user)
@@ -111,6 +108,16 @@ func newTestManagerWithStore(rng *rand.Rand, numGroups int, sendErr int,
 	return m, g
 }
 
+func newTestE2eManager(dhPubKey *cyclic.Int) *testE2eManager {
+	return &testE2eManager{
+		e2eMessages: []testE2eMessage{},
+		errSkip:     0,
+		grp:         getGroup(),
+		dhPubKey:    dhPubKey,
+		partners:    make(map[id.ID]partner.Manager),
+	}
+}
+
 // getMembership returns a Membership with random members for testing.
 func getMembership(size int, uid *id.ID, pubKey *cyclic.Int, grp *cyclic.Group,
 	prng *rand.Rand, t *testing.T) group.Membership {
@@ -219,6 +226,7 @@ func newTestNetworkManager(sendErr int, t *testing.T) GroupCmix {
 	return &testNetworkManager{
 		receptionMessages: [][]format.Message{},
 		sendMessages:      [][]cmix.TargetedCmixMessage{},
+		grp:               getGroup(),
 		sendErr:           sendErr,
 	}
 }
@@ -226,8 +234,11 @@ func newTestNetworkManager(sendErr int, t *testing.T) GroupCmix {
 // testE2eManager is a test implementation of NetworkManager interface.
 type testE2eManager struct {
 	e2eMessages []testE2eMessage
+	partners    map[id.ID]partner.Manager
 	errSkip     int
 	sendErr     int
+	dhPubKey    *cyclic.Int
+	grp         *cyclic.Group
 	sync.RWMutex
 }
 
@@ -237,20 +248,27 @@ type testE2eMessage struct {
 }
 
 func (tnm *testE2eManager) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int,
-	partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, receiveParams session.Params) (partner.Manager, error) {
-	return nil, nil
+	partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey,
+	sendParams, receiveParams session.Params) (partner.Manager, error) {
+
+	testPartner := partner.NewTestManager(partnerID, partnerPubKey, myPrivKey, &testing.T{})
+	tnm.partners[*partnerID] = testPartner
+	return testPartner, nil
 }
 
 func (tnm *testE2eManager) GetPartner(partnerID *id.ID) (partner.Manager, error) {
-	return nil, nil
+	if partner, ok := tnm.partners[*partnerID]; ok {
+		return partner, nil
+	}
+	return nil, errors.New("Unable to find partner")
 }
 
 func (tnm *testE2eManager) GetHistoricalDHPubkey() *cyclic.Int {
-	panic("implement me")
+	return tnm.dhPubKey
 }
 
 func (tnm *testE2eManager) GetHistoricalDHPrivkey() *cyclic.Int {
-	panic("implement me")
+	return tnm.dhPubKey
 }
 
 func (tnm *testE2eManager) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params clientE2E.Params) ([]id.Round, e2e.MessageID, time.Time, error) {
@@ -273,11 +291,11 @@ func (tnm *testE2eManager) SendE2E(mt catalog.MessageType, recipient *id.ID, pay
 }
 
 func (*testE2eManager) RegisterListener(user *id.ID, messageType catalog.MessageType, newListener receive.Listener) receive.ListenerID {
-	panic("implement me")
+	return receive.ListenerID{}
 }
 
 func (*testE2eManager) AddService(tag string, processor message.Processor) error {
-	panic("implement me")
+	return nil
 }
 
 func (*testE2eManager) GetDefaultHistoricalDHPubkey() *cyclic.Int {
@@ -300,9 +318,14 @@ type testNetworkManager struct {
 	sendMessages      [][]cmix.TargetedCmixMessage
 	errSkip           int
 	sendErr           int
+	grp               *cyclic.Group
 	sync.RWMutex
 }
 
+func (tnm *testNetworkManager) GetMaxMessageLength() int {
+	return format.NewMessage(tnm.grp.GetP().ByteLen()).ContentsSize()
+}
+
 func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, []ephemeral.Id, error) {
 	if tnm.sendErr == 1 {
 		return 0, nil, errors.New("SendManyCMIX error")
@@ -315,7 +338,7 @@ func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p c
 
 	receiveMessages := []format.Message{}
 	for _, msg := range messages {
-		receiveMsg := format.Message{}
+		receiveMsg := format.NewMessage(tnm.grp.GetP().ByteLen())
 		receiveMsg.SetMac(msg.Mac)
 		receiveMsg.SetContents(msg.Payload)
 		receiveMsg.SetKeyFP(msg.Fingerprint)
@@ -326,11 +349,11 @@ func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p c
 }
 
 func (*testNetworkManager) AddService(clientID *id.ID, newService message.Service, response message.Processor) {
-	panic("implement me")
+	return
 }
 
 func (*testNetworkManager) DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) {
-	panic("implement me")
+	return
 }
 
 type dummyEventMgr struct{}