diff --git a/context/context.go b/context/context.go
index c9de4b8781eed4f47c21c994bbae81027fe0f977..896f641e50a3b6b9b59e58794d56a2696aa2ffb1 100644
--- a/context/context.go
+++ b/context/context.go
@@ -3,6 +3,7 @@ package context
 import (
 	"gitlab.com/elixxir/client/context/switchboard"
 	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/crypto/fastRNG"
 )
 
 type Context struct {
@@ -12,4 +13,6 @@ type Context struct {
 	// this interface allows it to be mocked for easy testing without the
 	// loop
 	Manager NetworkManager
+
+	Rng *fastRNG.StreamGenerator
 }
diff --git a/context/stoppable/single.go b/context/stoppable/single.go
index bd0184656f86d56021e3cb1a351765dc56e40929..8b82c59f2a6121554f37de60e800e9472d0f2cd4 100644
--- a/context/stoppable/single.go
+++ b/context/stoppable/single.go
@@ -47,12 +47,11 @@ func (s *Single) Close(timeout time.Duration) error {
 	defer atomic.StoreUint32(&s.running, 0)
 	timer := time.NewTimer(timeout)
 	select {
+	case s.quit <- struct{}{}:
+		return nil
 	case <-timer.C:
 		jww.ERROR.Printf("Stopper for %s failed to stop after "+
 			"timeout of %s", s.name, timeout)
 		return errors.Errorf("%s failed to close", s.name)
-	case <-s.quit:
-
-		return nil
 	}
 }
diff --git a/go.mod b/go.mod
index adbd4d07551cd2a65a3d57cb31ad2522485e6703..8b362ab5f4e650d7ada1a5c3f89c508d1650dbe4 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.6.2
-	gitlab.com/elixxir/comms v0.0.0-20200909162307-0465eee5adb1
+	gitlab.com/elixxir/comms v0.0.0-20200909214857-b106ce82d9e8
 	gitlab.com/elixxir/crypto v0.0.0-20200907171019-008a9d4aa264
 	gitlab.com/elixxir/ekv v0.1.1
 	gitlab.com/elixxir/primitives v0.0.0-20200907165319-16ed0124890b
diff --git a/go.sum b/go.sum
index ff20f5c2fa9475b98d9ff5a9f966e179f696b8b6..cbf5ad9dd66a594dd29b5abc8d1a9a7e2bdc49bc 100644
--- a/go.sum
+++ b/go.sum
@@ -179,6 +179,8 @@ gitlab.com/elixxir/comms v0.0.0-20200903181126-c92d7a304999 h1:fxrqseawjJ2q6Z3NZ
 gitlab.com/elixxir/comms v0.0.0-20200903181126-c92d7a304999/go.mod h1:HW3Ige10aeJeyb2fcQ/YOBPiyzY/4jHau1Cj6/1WBHc=
 gitlab.com/elixxir/comms v0.0.0-20200909162307-0465eee5adb1 h1:Ma2phdeDx+7HZjLz4gAKlZN/bNsiqSmMPWCFnX9FrDI=
 gitlab.com/elixxir/comms v0.0.0-20200909162307-0465eee5adb1/go.mod h1:Z97ZjbtBLT3ojpGrT4jqlBhgscEjHl8kjA/ktLnhmOo=
+gitlab.com/elixxir/comms v0.0.0-20200909214857-b106ce82d9e8 h1:y+0aElewUD0ceZHvf96+s8oUZnfBMD9aflOBztMNlZ0=
+gitlab.com/elixxir/comms v0.0.0-20200909214857-b106ce82d9e8/go.mod h1:ZMwe9xZbPY1s81CVvy51hh+96b/supA797uxXEJJqRE=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
 gitlab.com/elixxir/crypto v0.0.0-20200805174804-bdf909f2a16d/go.mod h1:cu6uNoANVLV0J6HyTL6KqVtVyh9SHU1RjJhytYlsbVQ=
diff --git a/network/node/register.go b/network/node/register.go
index 8f748bfa8a23ad41ef66d573b7b42979f21815c6..97f6e759cd1c715f1af70cb23581feb23f32eb46 100644
--- a/network/node/register.go
+++ b/network/node/register.go
@@ -3,100 +3,132 @@ package node
 import (
 	"crypto"
 	"crypto/rand"
+	"crypto/sha256"
+	"encoding/binary"
 	"fmt"
 	"github.com/pkg/errors"
 	"github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/context"
 	"gitlab.com/elixxir/client/context/stoppable"
 	"gitlab.com/elixxir/client/globals"
-	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/client/storage/cmix"
 	"gitlab.com/elixxir/client/storage/user"
-	"gitlab.com/elixxir/comms/client"
 	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/comms/network"
 	"gitlab.com/elixxir/crypto/csprng"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/crypto/registration"
+	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/comms/messages"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
-	"gitlab.com/xx_network/primitives/ndf"
 	"time"
 )
 
-func StartRegistration(ctx context.Context, comms client.Comms) stoppable.Stoppable {
+type RegisterNodeCommsInterface interface {
+	GetHost(hostId *id.ID) (*connect.Host, bool)
+	SendRequestNonceMessage(host *connect.Host,
+		message *pb.NonceRequest) (*pb.Nonce, error)
+	SendConfirmNonceMessage(host *connect.Host,
+		message *pb.RequestRegistrationConfirmation) (*pb.RegistrationConfirmation, error)
+}
+
+func StartRegistration(ctx context.Context, comms RegisterNodeCommsInterface) stoppable.Stoppable {
+	stop := stoppable.NewSingle("NodeRegistration")
 	instance := ctx.Manager.GetInstance()
 
-	c := make(chan ndf.Gateway, 100)
+	c := make(chan network.NodeGateway, 100)
 	instance.SetAddGatewayChan(c)
 
+	go RegisterNodes(ctx, comms, stop, c)
+
+	return stop
+}
+
+func RegisterNodes(ctx context.Context, comms RegisterNodeCommsInterface,
+	stop *stoppable.Single, c chan network.NodeGateway) {
 	u := ctx.Session.User()
 	regSignature := u.GetRegistrationValidationSignature()
 	userCryptographicIdentity := u.GetCryptographicIdentity()
 	ctx.Session.Cmix()
 
-	stop := stoppable.NewSingle("NodeRegistration")
-
-	go func() {
-		for true {
-			select {
-			case <-stop.Quit():
-				return
-			case gw := <-c:
-				err := registerWithNode(comms, gw, regSignature, userCryptographicIdentity,
-					ctx.Session.Cmix(), ctx.Session)
-				if err != nil {
-					jwalterweatherman.ERROR.Printf("Failed")
-				}
-			default:
-				time.Sleep(0.5)
+	rng := ctx.Rng.GetStream()
+	interval := time.Duration(500) * time.Millisecond
+	for true {
+		select {
+		case <-stop.Quit():
+			return
+		case gw := <-c:
+			err := registerWithNode(comms, gw, regSignature, userCryptographicIdentity,
+				ctx.Session.Cmix(), rng)
+			if err != nil {
+				jwalterweatherman.ERROR.Printf("Failed")
 			}
+		default:
+			time.Sleep(interval)
 		}
-	}()
-
-	return stop
+	}
 
 }
 
 //registerWithNode serves as a helper for RegisterWithNodes
 // It registers a user with a specific in the client's ndf.
-func registerWithNode(comms client.Comms, gw ndf.Gateway, regHash []byte,
-	userCryptographicIdentity *user.CryptographicIdentity, store *cmix.Store, session *storage.Session) error {
-
+func registerWithNode(comms RegisterNodeCommsInterface, ngw network.NodeGateway, regSig []byte,
+	userCryptographicIdentity *user.CryptographicIdentity, store *cmix.Store, rng csprng.Source) error {
+	gw := ngw.Gateway
 	gatewayID, err := id.Unmarshal(gw.ID)
 	if err != nil {
 		return err
 	}
 
-	// Initialise blake2b hash for transmission keys and sha256 for reception
-	// keys
-	transmissionHash, _ := hash.NewCMixHash()
+	nodeID := gatewayID.DeepCopy()
+	nodeID.SetType(id.Node)
 
-	nonce, dhPub, err := requestNonce(comms, gatewayID, regHash, userCryptographicIdentity, store)
+	if store.IsRegistered(nodeID) {
+		return nil
+	}
 
-	// Load server DH pubkey
-	serverPubDH := store.GetGroup().NewIntFromBytes(dhPub)
+	var transmissionKey *cyclic.Int
+	if userCryptographicIdentity.IsPrecanned() {
+		userNum := binary.BigEndian.Uint64(userCryptographicIdentity.GetUserID().Bytes())
+		h := sha256.New()
+		h.Reset()
+		h.Write([]byte(string(40000 + userNum)))
+
+		transmissionKey = store.GetGroup().NewIntFromBytes(h.Sum(nil))
+	} else {
+		// Initialise blake2b hash for transmission keys and sha256 for reception
+		// keys
+		transmissionHash, _ := hash.NewCMixHash()
+
+		nonce, dhPub, err := requestNonce(comms, gatewayID, regSig, userCryptographicIdentity, store, rng)
+		if err != nil {
+			return errors.Errorf("Failed to request nonce: %+v", err)
+		}
 
-	// Confirm received nonce
-	globals.Log.INFO.Println("Register: Confirming received nonce")
-	err = confirmNonce(comms, userCryptographicIdentity.GetUserID().Bytes(),
-		nonce, userCryptographicIdentity.GetRSA(), gatewayID)
-	if err != nil {
-		errMsg := fmt.Sprintf("Register: Unable to confirm nonce: %v", err)
-		return errors.New(errMsg)
+		// Load server DH pubkey
+		serverPubDH := store.GetGroup().NewIntFromBytes(dhPub)
+
+		// Confirm received nonce
+		globals.Log.INFO.Println("Register: Confirming received nonce")
+		err = confirmNonce(comms, userCryptographicIdentity.GetUserID().Bytes(),
+			nonce, userCryptographicIdentity.GetRSA(), gatewayID)
+		if err != nil {
+			errMsg := fmt.Sprintf("Register: Unable to confirm nonce: %v", err)
+			return errors.New(errMsg)
+		}
+		transmissionKey = registration.GenerateBaseKey(store.GetGroup(),
+			serverPubDH, store.GetDHPrivateKey(), transmissionHash)
 	}
 
-	nodeID := gatewayID.DeepCopy()
-	nodeID.SetType(id.Node)
-	transmissionKey := registration.GenerateBaseKey(store.GetGroup(),
-		serverPubDH, store.GetDHPrivateKey(), transmissionHash)
-	session.Cmix().Add(nodeID, transmissionKey)
+	store.Add(nodeID, transmissionKey)
 
 	return nil
 }
 
-func requestNonce(comms client.Comms, gwId *id.ID, regHash []byte,
-	userCryptographicIdentity *user.CryptographicIdentity, store *cmix.Store) ([]byte, []byte, error) {
+func requestNonce(comms RegisterNodeCommsInterface, gwId *id.ID, regHash []byte,
+	userCryptographicIdentity *user.CryptographicIdentity, store *cmix.Store, rng csprng.Source) ([]byte, []byte, error) {
 	dhPub := store.GetDHPublicKey().Bytes()
 	sha := crypto.SHA256
 	opts := rsa.NewDefaultOptions()
@@ -106,7 +138,6 @@ func requestNonce(comms client.Comms, gwId *id.ID, regHash []byte,
 	data := h.Sum(nil)
 
 	// Sign DH pubkey
-	rng := csprng.NewSystemRNG()
 	signed, err := rsa.Sign(rng, userCryptographicIdentity.GetRSA(), sha, data, opts)
 	if err != nil {
 		return nil, nil, err
@@ -148,7 +179,7 @@ func requestNonce(comms client.Comms, gwId *id.ID, regHash []byte,
 // confirmNonce is a helper for the Register function
 // It signs a nonce and sends it for confirmation
 // Returns nil if successful, error otherwise
-func confirmNonce(comms client.Comms, UID, nonce []byte,
+func confirmNonce(comms RegisterNodeCommsInterface, UID, nonce []byte,
 	privateKeyRSA *rsa.PrivateKey, gwID *id.ID) error {
 	sha := crypto.SHA256
 	opts := rsa.NewDefaultOptions()
diff --git a/network/node/register_test.go b/network/node/register_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..05e1a36b14d79e4e5f69ace2872ef56265446a38
--- /dev/null
+++ b/network/node/register_test.go
@@ -0,0 +1,188 @@
+package node
+
+import (
+	"crypto/rand"
+	"gitlab.com/elixxir/client/context"
+	"gitlab.com/elixxir/client/context/message"
+	"gitlab.com/elixxir/client/context/params"
+	"gitlab.com/elixxir/client/context/stoppable"
+	"gitlab.com/elixxir/client/storage"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/crypto/csprng"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/ndf"
+	"testing"
+	"time"
+)
+
+// Mock network manager for
+type MockNetworkManager struct {
+	instance *network.Instance
+}
+
+func (nm *MockNetworkManager) SendE2E(m message.Send, e2eP params.E2E, cmixP params.CMIX) ([]id.Round, error) {
+	return nil, nil
+}
+func (nm *MockNetworkManager) SendUnsafe(m message.Send) ([]id.Round, error) {
+	return nil, nil
+}
+func (nm *MockNetworkManager) SendCMIX(message format.Message) (id.Round, error) {
+	return id.Round(0), nil
+}
+func (nm *MockNetworkManager) GetInstance() *network.Instance {
+	return nm.instance
+}
+func (nm *MockNetworkManager) GetHealthTracker() context.HealthTracker {
+	return nil
+}
+
+// Mock client comms object
+type MockClientComms struct {
+	request chan bool
+	confirm chan bool
+}
+
+func NewMockClientComms() *MockClientComms {
+	return &MockClientComms{
+		request: make(chan bool, 1),
+		confirm: make(chan bool, 1),
+	}
+}
+
+func (mcc *MockClientComms) GetHost(hostId *id.ID) (*connect.Host, bool) {
+	return &connect.Host{}, true
+}
+func (mcc *MockClientComms) SendRequestNonceMessage(host *connect.Host,
+	message *pb.NonceRequest) (*pb.Nonce, error) {
+	// Use this channel to confirm that request nonce was called
+	mcc.request <- true
+	return &pb.Nonce{
+		Nonce:    []byte("nonce"),
+		DHPubKey: []byte("dhpub"),
+	}, nil
+}
+func (mcc *MockClientComms) SendConfirmNonceMessage(host *connect.Host,
+	message *pb.RequestRegistrationConfirmation) (*pb.RegistrationConfirmation, error) {
+	// Use this channel to confirm that confirm nonce was called
+	mcc.confirm <- true
+	return &pb.RegistrationConfirmation{
+		ClientSignedByServer: nil,
+		ClientGatewayKey:     nil,
+		Error:                "",
+	}, nil
+}
+
+func TestRegisterNodes(t *testing.T) {
+	privKey, err := rsa.LoadPrivateKeyFromPem([]byte("-----BEGIN PRIVATE KEY-----\n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\nOaRA5ZbdE7g7vxKRV36jT3wvD7W+\n-----END PRIVATE KEY-----\n"))
+	if err != nil || privKey == nil {
+		t.Error("Failed to load privKey\n")
+	}
+	pub := "-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n"
+
+	salt := make([]byte, 32)
+	_, err = rand.Read(salt)
+	if err != nil {
+		t.Errorf("Failed to generate salt: %+v", err)
+	}
+	//uid := id.NewIdFromString("zezima", id.User, t)
+	comms := NewMockClientComms()
+
+	def := getNDF()
+	instanceComms := &connect.ProtoComms{}
+	_, err = instanceComms.AddHost(&id.Permissioning, "0.0.0.0:420", []byte(pub), false, false)
+	if err != nil {
+		t.Errorf("Faield to add perm host: %+v", err)
+	}
+	instance, err := network.NewInstanceTesting(instanceComms, def, def, nil, nil, t)
+	if err != nil {
+		t.Errorf("Failed to init test instance: %+v", err)
+	}
+	sess := storage.InitTestingSession(t)
+	ctx := context.Context{
+		Manager: &MockNetworkManager{
+			instance: instance,
+		},
+		Session: sess,
+		Rng:     fastRNG.NewStreamGenerator(7, 3, csprng.NewSystemRNG),
+	}
+
+	stop := stoppable.NewSingle("test")
+	c := make(chan network.NodeGateway, 100)
+	go RegisterNodes(ctx, comms, stop, c)
+
+	c <- network.NodeGateway{
+		Node: ndf.Node{
+			ID:             id.NewIdFromString("zezima", id.Node, t).Bytes(),
+			Address:        "0.0.0.0:420",
+			TlsCertificate: pub,
+		},
+		Gateway: ndf.Gateway{
+			ID:             id.NewIdFromString("zezima", id.Gateway, t).Bytes(),
+			Address:        "0.0.0.0:421",
+			TlsCertificate: pub,
+		},
+	}
+
+	timeout := time.NewTimer(time.Second * 5)
+	select {
+	case <-timeout.C:
+		t.Errorf("Timed out waiting for request nonce channel signal")
+	case <-comms.request:
+	}
+
+	timeout.Reset(5 * time.Second)
+	select {
+	case <-timeout.C:
+		t.Errorf("Timed out waiting for confirm nonce channel signal")
+	case <-comms.confirm:
+	}
+
+	err = stop.Close(5 * time.Second)
+	if err != nil {
+		t.Errorf("Failed to stop registration thread: %+v", err)
+	}
+}
+
+func getNDF() *ndf.NetworkDefinition {
+	return &ndf.NetworkDefinition{
+		E2E: ndf.Group{
+			Prime: "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B" +
+				"7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE" +
+				"DF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861575E745D31F" +
+				"8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC718DD2A3E041" +
+				"023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FFB1BC51DADDF45" +
+				"3B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBCA23EAC5ACE9209" +
+				"6EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD161C7738F32BF29" +
+				"A841698978825B4111B4BC3E1E198455095958333D776D8B2BEEED3A1A1A221A6E" +
+				"37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F2" +
+				"78DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696" +
+				"015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E" +
+				"6319BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC35873" +
+				"847AEF49F66E43873",
+			Generator: "2",
+		},
+		CMIX: ndf.Group{
+			Prime: "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
+				"C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
+				"FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
+				"B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
+				"35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
+				"F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
+				"92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
+				"3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B",
+			Generator: "5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
+				"D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
+				"6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
+				"085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
+				"AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
+				"3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
+				"BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
+				"DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7",
+		},
+	}
+}
diff --git a/storage/cmix/store.go b/storage/cmix/store.go
index b77b1733903f00e081086ec1105b95177b6eccb0..0dd31917f0b3c4cd46a0aba9e40defb5d3213236 100644
--- a/storage/cmix/store.go
+++ b/storage/cmix/store.go
@@ -175,6 +175,14 @@ func (s *Store) GetGroup() *cyclic.Group {
 	return s.grp
 }
 
+func (s *Store) IsRegistered(nid *id.ID) bool {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+
+	_, ok := s.nodes[*nid]
+	return ok
+}
+
 // stores the cmix store
 func (s *Store) save() error {
 	now := time.Now()
diff --git a/storage/session.go b/storage/session.go
index 53ff91e39354b24633dd0e1f41d22dc3880616ec..c5bf387e2948b8aad0e1d300a5a5a3965cbf58a7 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -19,6 +19,7 @@ import (
 	"gitlab.com/elixxir/client/storage/utility"
 	"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"
@@ -220,7 +221,37 @@ func InitTestingSession(i interface{}) *Session {
 		globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i)
 	}
 
+	privKey, _ := rsa.LoadPrivateKeyFromPem([]byte("-----BEGIN PRIVATE KEY-----\n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\nOaRA5ZbdE7g7vxKRV36jT3wvD7W+\n-----END PRIVATE KEY-----\n"))
 	store := make(ekv.Memstore)
-	return &Session{kv: versioned.NewKV(store)}
-
+	kv := versioned.NewKV(store)
+	s := &Session{kv: kv}
+	u, err := user.NewUser(kv, id.NewIdFromString("zezima", id.User, i), []byte("salt"), privKey, false)
+	if err != nil {
+		globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err)
+	}
+	u.SetRegistrationValidationSignature([]byte("sig"))
+	s.user = u
+	cmixGrp := cyclic.NewGroup(
+		large.NewIntFromString("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48"+
+			"C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F"+
+			"FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5"+
+			"B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2"+
+			"35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41"+
+			"F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE"+
+			"92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15"+
+			"3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", 16),
+		large.NewIntFromString("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613"+
+			"D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4"+
+			"6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472"+
+			"085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5"+
+			"AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA"+
+			"3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71"+
+			"BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0"+
+			"DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16))
+	cmix, err := cmix.NewStore(cmixGrp, kv, cmixGrp.NewInt(2))
+	if err != nil {
+		globals.Log.FATAL.Panicf("InitTestingSession failed to create dummy cmix session: %+v", err)
+	}
+	s.cmix = cmix
+	return s
 }