diff --git a/.gitignore b/.gitignore
index 1348703249512ef3a56de1dada944640e8269c15..872d4c5002777a957a3614f8005b36d548ebbb68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,5 +27,6 @@ localdev_*
 *.class
 *.aar
 *.jar
+glide.yaml
 # Ignore genered version file
 cmd/version_vars.go
diff --git a/api/client.go b/api/client.go
index 96d53f4397504bf15cbd16aa06cd9d6a0cbd8b11..d57b99e661ef4291b8fbd8810b434762e3672d69 100644
--- a/api/client.go
+++ b/api/client.go
@@ -7,6 +7,7 @@
 package api
 
 import (
+	"crypto"
 	"crypto/rand"
 	"crypto/sha256"
 	"encoding/base64"
@@ -29,7 +30,6 @@ import (
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/crypto/large"
 	"gitlab.com/elixxir/crypto/registration"
-	"gitlab.com/elixxir/crypto/signature"
 	"gitlab.com/elixxir/crypto/signature/rsa"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/id"
@@ -47,6 +47,8 @@ type Client struct {
 	topology *circuit.Circuit
 }
 
+var PermissioningAddrID = "registration"
+
 // Populates a text message and returns its wire representation
 // TODO support multi-type messages or telling if a message is too long?
 func FormatTextMessage(message string) []byte {
@@ -160,6 +162,7 @@ func (cl *Client) Connect() error {
 		if gateway.TlsCertificate != "" {
 			gwCreds = []byte(gateway.TlsCertificate)
 		}
+
 		gwID := id.NewNodeFromBytes(cl.ndf.Nodes[i].ID).NewGateway()
 		globals.Log.INFO.Printf("Connecting to gateway %s at %s...",
 			gwID.String(), gateway.Address)
@@ -179,8 +182,8 @@ func (cl *Client) Connect() error {
 		if cl.ndf.Registration.TlsCertificate != "" {
 			regCert = []byte(cl.ndf.Registration.TlsCertificate)
 		}
-		addr := io.ConnAddr("registration")
-		globals.Log.INFO.Printf("Connecting to permissioning at %s...",
+		addr := io.ConnAddr(PermissioningAddrID)
+		globals.Log.INFO.Printf("Connecting to permissioning/registration at %s...",
 			cl.ndf.Registration.Address)
 		err = (cl.comm).(*io.Messaging).Comms.ConnectToRegistration(addr, cl.ndf.Registration.Address, regCert)
 		if err != nil {
@@ -203,70 +206,43 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (*
 	var u *user.User
 	var UID *id.User
 
+	largeIntBits := 16
+
 	cmixGrp := cyclic.NewGroup(
-		large.NewIntFromString(cl.ndf.CMIX.Prime, 16),
-		large.NewIntFromString(cl.ndf.CMIX.Generator, 16),
-		large.NewIntFromString(cl.ndf.CMIX.SmallPrime, 16))
+		large.NewIntFromString(cl.ndf.CMIX.Prime, largeIntBits),
+		large.NewIntFromString(cl.ndf.CMIX.Generator, largeIntBits),
+		large.NewIntFromString(cl.ndf.CMIX.SmallPrime, largeIntBits))
 
 	e2eGrp := cyclic.NewGroup(
-		large.NewIntFromString(cl.ndf.E2E.Prime, 16),
-		large.NewIntFromString(cl.ndf.E2E.Generator, 16),
-		large.NewIntFromString(cl.ndf.E2E.SmallPrime, 16))
+		large.NewIntFromString(cl.ndf.E2E.Prime, largeIntBits),
+		large.NewIntFromString(cl.ndf.E2E.Generator, largeIntBits),
+		large.NewIntFromString(cl.ndf.E2E.SmallPrime, largeIntBits))
 
 	// Make CMIX keys array
 	nk := make(map[id.Node]user.NodeKeys)
 
-	// Generate DSA keypair even for precanned users as it will probably
-	// be needed for the new UDB flow
-	params := signature.CustomDSAParams(
-		cmixGrp.GetP(),
-		cmixGrp.GetQ(),
-		cmixGrp.GetG())
-	privateKey := params.PrivateKeyGen(rand.Reader)
-	publicKey := privateKey.PublicKeyGen()
+	// GENERATE CLIENT RSA KEYS
+	privateKeyRSA, err := rsa.GenerateKey(rand.Reader, rsa.DefaultRSABitLen)
+	if err != nil {
+		return nil, err
+	}
+	publicKeyRSA := privateKeyRSA.GetPublic()
 
-	fmt.Println("gened private keys")
+	privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewMaxInt())
 
 	// Handle precanned registration
 	if preCan {
-		var successLook bool
-		globals.Log.DEBUG.Printf("Registering precanned user")
-		UID, successLook = user.Users.LookupUser(registrationCode)
-
-		fmt.Println("UID:", UID, "success:", successLook)
-
-		if !successLook {
-			globals.Log.ERROR.Printf("Register: HUID does not match")
-			return id.ZeroID, errors.New("could not register due to invalid HUID")
-		}
-
-		var successGet bool
-		u, successGet = user.Users.GetUser(UID)
-
-		if !successGet {
-			globals.Log.ERROR.Printf("Register: ID lookup failed")
-			err = errors.New("could not register due to ID lookup failure")
-			return id.ZeroID, err
-		}
-
-		if nick != "" {
-			u.Nick = nick
-		}
-
-		nodekeys, successKeys := user.Users.LookupKeys(u.User)
-
-		if !successKeys {
-			globals.Log.ERROR.Printf("Register: could not find user keys")
-			err = errors.New("could not register due to missing user keys")
+		globals.Log.INFO.Printf("Registering precanned user")
+		u, UID, nk, err = cl.precannedRegister(registrationCode, nick, nk)
+		if err != nil {
+			globals.Log.ERROR.Printf("Unable to complete precanned registration: %+v", err)
 			return id.ZeroID, err
 		}
-
-		for i := 0; i < len(cl.ndf.Gateways); i++ {
-			nk[*cl.topology.GetNodeAtIndex(i)] = *nodekeys
-		}
 	} else {
+		saltSize := 256
 		// Generate salt for UserID
-		salt := make([]byte, 256)
+		salt := make([]byte, saltSize)
 		_, err = csprng.NewSystemRNG().Read(salt)
 		if err != nil {
 			globals.Log.ERROR.Printf("Register: Unable to generate salt! %s", err)
@@ -274,131 +250,59 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (*
 		}
 
 		// Generate UserID by hashing salt and public key
-		UID = registration.GenUserID(publicKey, salt)
-		// Keep track of Server public keys provided at end of registration
-		var serverPublicKeys []*signature.DSAPublicKey
+		UID = registration.GenUserID(publicKeyRSA, salt)
+
 		// Initialized response from Registration Server
-		regHash, regR, regS := make([]byte, 0), make([]byte, 0), make([]byte, 0)
+		regHash := make([]byte, 0)
 
 		// If Registration Server is specified, contact it
 		// Only if registrationCode is set
+		globals.Log.INFO.Println("Register: Contacting registration server")
 		if cl.ndf.Registration.Address != "" && registrationCode != "" {
-			// Send registration code and public key to RegistrationServer
-			response, err := (cl.comm).(*io.Messaging).Comms.
-				SendRegistrationMessage(io.ConnAddr("registration"),
-					&pb.UserRegistration{
-						RegistrationCode: registrationCode,
-						Client: &pb.DSAPublicKey{
-							Y: publicKey.GetKey().Bytes(),
-							P: params.GetP().Bytes(),
-							Q: params.GetQ().Bytes(),
-							G: params.GetG().Bytes(),
-						},
-					})
+			regHash, err = cl.sendRegistrationMessage(registrationCode, publicKeyRSA)
 			if err != nil {
-				globals.Log.ERROR.Printf(
-					"Register: Unable to contact Registration Server! %s", err)
+				globals.Log.ERROR.Printf("Register: Unable to send registration message: %+v", err)
 				return id.ZeroID, err
 			}
-			if response.Error != "" {
-				globals.Log.ERROR.Printf("Register: %s", response.Error)
-				return id.ZeroID, errors.New(response.Error)
-			}
-			regHash = response.ClientSignedByServer.Hash
-			regR = response.ClientSignedByServer.R
-			regS = response.ClientSignedByServer.S
-			// Disconnect from regServer here since it will not be needed
-			(cl.comm).(*io.Messaging).Comms.Disconnect(cl.ndf.Registration.Address)
 		}
-		fmt.Println("passed reg")
+		globals.Log.INFO.Println("Register: successfully passed Registration message")
+
+		// Initialise blake2b hash for transmission keys and sha256 for reception
+		// keys
+		transmissionHash, _ := hash.NewCMixHash()
+		receptionHash := sha256.New()
+
 		// Loop over all Servers
+		globals.Log.INFO.Println("Register: Requesting nonces")
 		for i := range cl.ndf.Gateways {
 
 			gwID := id.NewNodeFromBytes(cl.ndf.Nodes[i].ID).NewGateway()
 
-			// Send signed public key and salt for UserID to Server
-			nonceResponse, err := (cl.comm).(*io.Messaging).Comms.
-				SendRequestNonceMessage(gwID,
-					&pb.NonceRequest{
-						Salt: salt,
-						Client: &pb.DSAPublicKey{
-							Y: publicKey.GetKey().Bytes(),
-							P: params.GetP().Bytes(),
-							Q: params.GetQ().Bytes(),
-							G: params.GetG().Bytes(),
-						},
-						ClientSignedByServer: &pb.DSASignature{
-							Hash: regHash,
-							R:    regR,
-							S:    regS,
-						},
-					})
+			// Request nonce message from gateway
+			globals.Log.INFO.Printf("Register: Requesting nonce from gateway %v/%v", i, len(cl.ndf.Gateways))
+			nonce, dhPub, err := cl.requestNonce(salt, regHash, publicKeyDH, publicKeyRSA, privateKeyRSA, gwID)
 			if err != nil {
-				globals.Log.ERROR.Printf(
-					"Register: Unable to request nonce! %s",
-					err)
+				globals.Log.ERROR.Printf("Register: Failed requesting nonce from gateway: %+v", err)
 				return id.ZeroID, err
 			}
-			if nonceResponse.Error != "" {
-				globals.Log.ERROR.Printf("Register: %s", nonceResponse.Error)
-				return id.ZeroID, errors.New(nonceResponse.Error)
-			}
 
-			// Use Client keypair to sign Server nonce
-			nonce := nonceResponse.Nonce
-			sig, err := privateKey.Sign(nonce, rand.Reader)
-			if err != nil {
-				globals.Log.ERROR.Printf(
-					"Register: Unable to sign nonce! %s", err)
-				return id.ZeroID, err
-			}
+			// Load server DH pubkey
+			serverPubDH := cmixGrp.NewIntFromBytes(dhPub)
 
-			// Send signed nonce to Server
-			// TODO: This returns a receipt that can be used to speed up registration
-			confirmResponse, err := (cl.comm).(*io.Messaging).Comms.
-				SendConfirmNonceMessage(gwID,
-					&pb.DSASignature{
-						Hash: nonce,
-						R:    sig.R.Bytes(),
-						S:    sig.S.Bytes(),
-					})
+			// Confirm received nonce
+			globals.Log.INFO.Println("Register: Confirming received nonce")
+			err = cl.confirmNonce(UID.Bytes(), nonce, privateKeyRSA, gwID)
 			if err != nil {
-				globals.Log.ERROR.Printf(
-					"Register: Unable to send signed nonce! %s", err)
+				globals.Log.ERROR.Printf("Register: Unable to confirm nonce: %+v", err)
 				return id.ZeroID, err
 			}
-			if confirmResponse.Error != "" {
-				globals.Log.ERROR.Printf(
-					"Register: %s", confirmResponse.Error)
-				return id.ZeroID, errors.New(confirmResponse.Error)
-			}
-
-			// Append Server public key
-			serverPublicKeys = append(serverPublicKeys,
-				signature.ReconstructPublicKey(signature.
-					CustomDSAParams(
-						large.NewIntFromBytes(confirmResponse.Server.GetP()),
-						large.NewIntFromBytes(confirmResponse.Server.GetQ()),
-						large.NewIntFromBytes(confirmResponse.Server.GetG())),
-					large.NewIntFromBytes(confirmResponse.Server.GetY())))
-
-		}
-
-		// Initialise blake2b hash for transmission keys and sha256 for reception
-		// keys
-		transmissionHash, _ := hash.NewCMixHash()
-		receptionHash := sha256.New()
-
-		// Loop through all the server public keys
-		for itr, publicKey := range serverPublicKeys {
-
-			nodeID := *cl.topology.GetNodeAtIndex(itr)
 
+			nodeID := *cl.topology.GetNodeAtIndex(i)
 			nk[nodeID] = user.NodeKeys{
 				TransmissionKey: registration.GenerateBaseKey(cmixGrp,
-					publicKey, privateKey, transmissionHash),
-				ReceptionKey: registration.GenerateBaseKey(cmixGrp, publicKey,
-					privateKey, receptionHash),
+					serverPubDH, privateKeyDH, transmissionHash),
+				ReceptionKey: registration.GenerateBaseKey(cmixGrp, serverPubDH,
+					privateKeyDH, receptionHash),
 			}
 
 			receptionHash.Reset()
@@ -418,10 +322,10 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (*
 	u.Email = email
 
 	// Create the user session
-	nus := user.NewSession(cl.storage, u, nk, publicKey, privateKey, cmixGrp, e2eGrp)
+	newSession := user.NewSession(cl.storage, u, nk, publicKeyRSA, privateKeyRSA, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp)
 
 	// Store the user session
-	errStore := nus.StoreSession()
+	errStore := newSession.StoreSession()
 
 	// FIXME If we have an error here, the session that gets created doesn't get immolated.
 	// Immolation should happen in a deferred call instead.
@@ -433,15 +337,177 @@ func (cl *Client) Register(preCan bool, registrationCode, nick, email string) (*
 		return id.ZeroID, err
 	}
 
-	err = nus.Immolate()
+	err = newSession.Immolate()
 	if err != nil {
 		globals.Log.ERROR.Printf("Error on immolate: %+v", err)
 	}
-	nus = nil
+	newSession = nil
 
 	return UID, nil
 }
 
+// precannedRegister is a helper function for Register
+// It handles the precanned registration case
+func (cl *Client) precannedRegister(registrationCode, nick string,
+	nk map[id.Node]user.NodeKeys) (*user.User, *id.User, map[id.Node]user.NodeKeys, error) {
+	var successLook bool
+	var UID *id.User
+	var u *user.User
+	var err error
+
+	UID, successLook = user.Users.LookupUser(registrationCode)
+
+	globals.Log.DEBUG.Printf("UID: %+v, success: %+v", UID, successLook)
+
+	if !successLook {
+		return nil, nil, nil, errors.New("precannedRegister: could not register due to invalid HUID")
+	}
+
+	var successGet bool
+	u, successGet = user.Users.GetUser(UID)
+
+	if !successGet {
+		err = errors.New("precannedRegister: could not register due to ID lookup failure")
+		return nil, nil, nil, err
+	}
+
+	if nick != "" {
+		u.Nick = nick
+	}
+
+	nodekeys, successKeys := user.Users.LookupKeys(u.User)
+
+	if !successKeys {
+		err = errors.New("precannedRegister: could not register due to missing user keys")
+		return nil, nil, nil, err
+	}
+
+	for i := 0; i < len(cl.ndf.Gateways); i++ {
+		nk[*cl.topology.GetNodeAtIndex(i)] = *nodekeys
+	}
+	return u, UID, nk, nil
+}
+
+// sendRegistrationMessage is a helper for the Register function
+// It sends a registration message and returns the registration hash
+func (cl *Client) sendRegistrationMessage(registrationCode string,
+	publicKeyRSA *rsa.PublicKey) ([]byte, error) {
+	regHash := make([]byte, 0)
+	// Send registration code and public key to RegistrationServer
+	response, err := (cl.comm).(*io.Messaging).Comms.
+		SendRegistrationMessage(io.ConnAddr(PermissioningAddrID),
+			&pb.UserRegistration{
+				RegistrationCode: registrationCode,
+				ClientRSAPubKey:  string(rsa.CreatePublicKeyPem(publicKeyRSA)),
+			})
+	if err != nil {
+		err = errors.New(fmt.Sprintf(
+			"sendRegistrationMessage: Unable to contact Registration Server! %s", err))
+		return nil, err
+	}
+	if response.Error != "" {
+		err = errors.New(fmt.Sprintf("sendRegistrationMessage: error handing message: %s", response.Error))
+		return nil, err
+	}
+	regHash = response.ClientSignedByServer.Signature
+	// Disconnect from regServer here since it will not be needed
+	(cl.comm).(*io.Messaging).Comms.Disconnect(cl.ndf.Registration.Address)
+	return regHash, nil
+}
+
+// requestNonce is a helper for the Register function
+// It sends a request nonce message containing the client's keys for signing
+// Returns nonce if successful
+func (cl *Client) requestNonce(salt, regHash []byte,
+	publicKeyDH *cyclic.Int, publicKeyRSA *rsa.PublicKey,
+	privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) ([]byte, []byte, error) {
+	dhPub := publicKeyDH.Bytes()
+	sha := crypto.SHA256
+	opts := rsa.NewDefaultOptions()
+	opts.Hash = sha
+	h := sha.New()
+	h.Write(dhPub)
+	data := h.Sum(nil)
+	fmt.Println(data)
+	// Sign DH pubkey
+	rng := csprng.NewSystemRNG()
+	signed, err := rsa.Sign(rng, privateKeyRSA, sha, data, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// Send signed public key and salt for UserID to Server
+	nonceResponse, err := (cl.comm).(*io.Messaging).Comms.
+		SendRequestNonceMessage(gwID,
+			&pb.NonceRequest{
+				Salt:            salt,
+				ClientRSAPubKey: string(rsa.CreatePublicKeyPem(publicKeyRSA)),
+				ClientSignedByServer: &pb.RSASignature{
+					Signature: regHash,
+				},
+				ClientDHPubKey: publicKeyDH.Bytes(),
+				RequestSignature: &pb.RSASignature{
+					Signature: signed,
+				},
+			}) // TODO: modify this to return server DH
+	if err != nil {
+		err := errors.New(fmt.Sprintf(
+			"requestNonce: Unable to request nonce! %s", err))
+		return nil, nil, err
+	}
+	if nonceResponse.Error != "" {
+		err := errors.New(fmt.Sprintf("requestNonce: nonceResponse error: %s", nonceResponse.Error))
+		return nil, nil, err
+	}
+
+	// Use Client keypair to sign Server nonce
+	return nonceResponse.Nonce, nonceResponse.DHPubKey, nil
+
+}
+
+// confirmNonce is a helper for the Register function
+// It signs a nonce and sends it for confirmation
+// Returns nil if successful, error otherwise
+func (cl *Client) confirmNonce(UID, nonce []byte,
+	privateKeyRSA *rsa.PrivateKey, gwID *id.Gateway) error {
+	sha := crypto.SHA256
+	opts := rsa.NewDefaultOptions()
+	opts.Hash = sha
+	h := sha.New()
+	h.Write(nonce)
+	data := h.Sum(nil)
+
+	// Hash nonce & sign
+	sig, err := rsa.Sign(rand.Reader, privateKeyRSA, sha, data, opts)
+	if err != nil {
+		globals.Log.ERROR.Printf(
+			"Register: Unable to sign nonce! %s", err)
+		return err
+	}
+
+	// Send signed nonce to Server
+	// TODO: This returns a receipt that can be used to speed up registration
+	msg := &pb.RequestRegistrationConfirmation{
+		UserID: UID,
+		NonceSignedByClient: &pb.RSASignature{
+			Signature: sig,
+		},
+	}
+	confirmResponse, err := (cl.comm).(*io.Messaging).Comms.
+		SendConfirmNonceMessage(gwID, msg)
+	if err != nil {
+		err := errors.New(fmt.Sprintf(
+			"confirmNonce: Unable to send signed nonce! %s", err))
+		return err
+	}
+	if confirmResponse.Error != "" {
+		err := errors.New(fmt.Sprintf(
+			"confirmNonce: Error confirming nonce: %s", confirmResponse.Error))
+		return err
+	}
+	return nil
+}
+
 // LoadSession loads the session object for the UID
 func (cl *Client) Login(UID *id.User) (string, error) {
 	session, err := user.LoadSession(cl.storage, UID)
@@ -453,6 +519,10 @@ func (cl *Client) Login(UID *id.User) (string, error) {
 		return "", err
 	}
 
+	if session == nil {
+		return "", errors.New("Unable to load session: " + err.Error())
+	}
+
 	cl.session = session
 	return cl.session.GetCurrentUser().Nick, nil
 }
@@ -591,8 +661,8 @@ func (cl *Client) registerForUserDiscovery(emailAddress string) error {
 		return err
 	}
 
-	publicKey := cl.session.GetPublicKey()
-	publicKeyBytes := publicKey.GetKey().LeftpadBytes(256)
+	publicKey := cl.session.GetRSAPublicKey()
+	publicKeyBytes := rsa.CreatePublicKeyPem(publicKey)
 	return bots.Register(valueType, emailAddress, publicKeyBytes)
 }
 
@@ -651,8 +721,8 @@ func (cl *Client) registerUserE2E(partnerID *id.User,
 
 	// Create user private key and partner public key
 	// in the group
-	privKey := cl.session.GetPrivateKey()
-	privKeyCyclic := grp.NewIntFromLargeInt(privKey.GetKey())
+	privKey := cl.session.GetDHPrivateKey()
+	privKeyCyclic := grp.NewIntFromLargeInt(privKey.GetLargeInt())
 	partnerPubKeyCyclic := grp.NewIntFromBytes(partnerPubKey)
 
 	// Generate baseKey
diff --git a/api/client_test.go b/api/client_test.go
index 6c6a825e520e37fa4907f854a0861383c54a63e3..21839c58048681a5f76a00d9bdef881331696690 100644
--- a/api/client_test.go
+++ b/api/client_test.go
@@ -23,7 +23,7 @@ import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/crypto/large"
-	"gitlab.com/elixxir/crypto/signature"
+	"gitlab.com/elixxir/crypto/signature/rsa"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/elixxir/primitives/id"
@@ -32,6 +32,8 @@ import (
 	"time"
 )
 
+var TestKeySize = 768
+
 func TestRegistrationGob(t *testing.T) {
 	// Get a Client
 	testClient, err := NewClient(&globals.RamStorage{}, "", def)
@@ -188,24 +190,23 @@ func TestRegisterUserE2E(t *testing.T) {
 		t.Error(err)
 	}
 
+	rng := csprng.NewSystemRNG()
 	cmixGrp, e2eGrp := getGroups()
 	userID := id.NewUserFromUint(18, t)
 	partner := id.NewUserFromUint(14, t)
-	params := signature.CustomDSAParams(
-		cmixGrp.GetP(),
-		cmixGrp.GetQ(),
-		cmixGrp.GetG())
-	rng := csprng.NewSystemRNG()
-	myPrivKey := params.PrivateKeyGen(rng)
-	myPrivKeyCyclic := cmixGrp.NewIntFromLargeInt(myPrivKey.GetKey())
-	myPubKey := myPrivKey.PublicKeyGen()
-	partnerPrivKey := params.PrivateKeyGen(rng)
-	partnerPubKey := partnerPrivKey.PublicKeyGen()
-	partnerPubKeyCyclic := cmixGrp.NewIntFromLargeInt(partnerPubKey.GetKey())
+
+	myPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	myPubKeyCyclic := cmixGrp.ExpG(myPrivKeyCyclic, cmixGrp.NewMaxInt())
+
+	partnerPubKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+
+	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
+	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
 
 	myUser := &user.User{User: userID, Nick: "test"}
 	session := user.NewSession(testClient.storage,
-		myUser, make(map[id.Node]user.NodeKeys), myPubKey, myPrivKey, cmixGrp, e2eGrp)
+		myUser, make(map[id.Node]user.NodeKeys), &publicKeyRSA, privateKeyRSA,
+		myPubKeyCyclic, myPrivKeyCyclic, cmixGrp, e2eGrp)
 
 	testClient.session = session
 	fmt.Println("runn")
@@ -280,22 +281,21 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) {
 	cmixGrp, e2eGrp := getGroups()
 	userID := id.NewUserFromUint(18, t)
 	partner := id.NewUserFromUint(14, t)
-	params := signature.CustomDSAParams(
-		cmixGrp.GetP(),
-		cmixGrp.GetQ(),
-		cmixGrp.GetG())
+
 	rng := csprng.NewSystemRNG()
-	myPrivKey := params.PrivateKeyGen(rng)
-	myPrivKeyCyclic := cmixGrp.NewIntFromLargeInt(myPrivKey.GetKey())
-	myPubKey := myPrivKey.PublicKeyGen()
-	partnerPrivKey := params.PrivateKeyGen(rng)
-	partnerPubKey := partnerPrivKey.PublicKeyGen()
-	partnerPubKeyCyclic := cmixGrp.NewIntFromLargeInt(partnerPubKey.GetKey())
+	myPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	myPubKeyCyclic := cmixGrp.ExpG(myPrivKeyCyclic, cmixGrp.NewMaxInt())
+
+	partnerPrivKeyCyclic := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	partnerPubKeyCyclic := cmixGrp.ExpG(partnerPrivKeyCyclic, cmixGrp.NewMaxInt())
+
+	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
+	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
 
 	myUser := &user.User{User: userID, Nick: "test"}
 	session := user.NewSession(testClient.storage,
-		myUser, make(map[id.Node]user.NodeKeys), myPubKey,
-		myPrivKey, cmixGrp, e2eGrp)
+		myUser, make(map[id.Node]user.NodeKeys), &publicKeyRSA,
+		privateKeyRSA, myPubKeyCyclic, myPrivKeyCyclic, cmixGrp, e2eGrp)
 
 	testClient.session = session
 
@@ -417,80 +417,99 @@ func TestRegisterUserE2E_CheckAllKeys(t *testing.T) {
 	}
 }
 
-// FIXME Reinstate tests for the UDB api
-//var ListenCh chan *format.Message
-//var lastmsg string
-
-//type dummyMessaging struct {
-//	listener chan *format.Message
-//}
-
-// SendMessage to the server
-//func (d *dummyMessaging) SendMessage(recipientID id.User,
-//	message string) error {
-//	jww.INFO.Printf("Sending: %s", message)
-//	lastmsg = message
-//	return nil
-//}
-
-// Listen for messages from a given sender
-//func (d *dummyMessaging) Listen(senderID id.User) chan *format.Message {
-//	return d.listener
-//}
-
-// StopListening to a given switchboard (closes and deletes)
-//func (d *dummyMessaging) StopListening(listenerCh chan *format.Message) {}
-
-// MessageReceiver thread to get new messages
-//func (d *dummyMessaging) MessageReceiver(delay time.Duration) {}
-
-//var pubKeyBits []string
-//var keyFingerprint string
-//var pubKey []byte
-
-// SendMsg puts a fake udb response message on the channel
-//func SendMsg(msg string) {
-//	m, _ := format.NewMessage(13, 1, msg)
-//	ListenCh <- &m[0]
-//}
-
-//func TestRegisterPubKeyByteLen(t *testing.T) {
-//	ListenCh = make(chan *format.Message, 100)
-//	io.Messaging = &dummyMessaging{
-//		switchboard: ListenCh,
-//	}
-//	pubKeyBits = []string{
-//		"S8KXBczy0jins9uS4LgBPt0bkFl8t00MnZmExQ6GcOcu8O7DKgAsNz" +
-//			"LU7a+gMTbIsS995IL/kuFF8wcBaQJBY23095PMSQ/nMuetzhk9HdXxrGIiKBo3C/n4SClp" +
-//			"q4H+PoF9XziEVKua8JxGM2o83KiCK3tNUpaZbAAElkjueY4=",
-//		"8Lg/eoeKGgPlleTYfO3JyGfnwBtLi73ti0h2dBQWW94JTqTQDr+z" +
-//			"xVpLzdgTt+87TkAl0yXu9mOUXqGJ+51lTcRlIdIpWpfgUbibdRme8IThg0RNCF31ESKCts" +
-//			"o8gJ8mSVljIXxrC+Uuoi+Gl1LNN5nPARykatx0Y70xNdJd2BQ=",
-//	}
-//	pubKey = make([]byte, 256)
-//	for i := range pubKeyBits {
-//		pubkeyBytes, _ := base64.StdEncoding.DecodeString(pubKeyBits[i])
-//		for j := range pubkeyBytes {
-//			pubKey[j+i*128] = pubkeyBytes[j]
-//		}
-//	}
-//
-//	keyFingerprint = "8oKh7TYG4KxQcBAymoXPBHSD/uga9pX3Mn/jKhvcD8M="
-//	//SendMsg("SEARCH blah@privategrity.com NOTFOUND")
-//	SendMsg(fmt.Sprintf("GETKEY %s NOTFOUND", keyFingerprint))
-//	SendMsg("PUSHKEY ACK NEED 128")
-//	SendMsg(fmt.Sprintf("PUSHKEY COMPLETE %s", keyFingerprint))
-//	SendMsg("REGISTRATION COMPLETE")
-//
-//	err := bots.Register("EMAIL", "blah@privategrity.com", pubKey)
-//
-//	if err != nil {
-//		t.Errorf("Unexpected error: %s", err.Error())
-//	}
-//	if len(lastmsg) != 81 {
-//		t.Errorf("Message wrong length: %d v. expected 81", len(lastmsg))
-//	}
-//}
+// Test happy path for precannedRegister
+func TestClient_precannedRegister(t *testing.T) {
+	testClient, err := NewClient(&globals.RamStorage{}, "", def)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = testClient.Connect()
+	if err != nil {
+		t.Error(err)
+	}
+
+	nk := make(map[id.Node]user.NodeKeys)
+
+	_, _, nk, err = testClient.precannedRegister("UAV6IWD6", "tony_johns", nk)
+	if err != nil {
+		t.Errorf("Error during precannedRegister: %+v", err)
+	}
+}
+
+// Test happy path for sendRegistrationMessage
+func TestClient_sendRegistrationMessage(t *testing.T) {
+	testClient, err := NewClient(&globals.RamStorage{}, "", def)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = testClient.Connect()
+	if err != nil {
+		t.Error(err)
+	}
+
+	rng := csprng.NewSystemRNG()
+	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
+	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
+
+	_, err = testClient.sendRegistrationMessage("UAV6IWD6", &publicKeyRSA)
+	if err != nil {
+		t.Errorf("Error during sendRegistrationMessage: %+v", err)
+	}
+}
+
+// Test happy path for requestNonce
+func TestClient_requestNonce(t *testing.T) {
+	cmixGrp, _ := getGroups()
+	privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewMaxInt())
+	rng := csprng.NewSystemRNG()
+	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
+	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
+
+	testClient, err := NewClient(&globals.RamStorage{}, "", def)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = testClient.Connect()
+	if err != nil {
+		t.Error(err)
+	}
+
+	salt := make([]byte, 256)
+	_, err = csprng.NewSystemRNG().Read(salt)
+	if err != nil {
+		t.Errorf("Unable to generate salt! %s", err)
+	}
+
+	gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway()
+	_, _, err = testClient.requestNonce(salt, []byte("test"), publicKeyDH, &publicKeyRSA, privateKeyRSA, gwID)
+	if err != nil {
+		t.Errorf("Error during requestNonce: %+v", err)
+	}
+}
+
+// Test happy path for confirmNonce
+func TestClient_confirmNonce(t *testing.T) {
+	testClient, err := NewClient(&globals.RamStorage{}, "", def)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = testClient.Connect()
+	if err != nil {
+		t.Error(err)
+	}
+	rng := csprng.NewSystemRNG()
+	privateKeyRSA, _ := rsa.GenerateKey(rng, TestKeySize)
+	gwID := id.NewNodeFromBytes(testClient.ndf.Nodes[0].ID).NewGateway()
+	err = testClient.confirmNonce([]byte("user"), []byte("test"), privateKeyRSA, gwID)
+	if err != nil {
+		t.Errorf("Error during confirmNonce: %+v", err)
+	}
+}
 
 func getGroups() (*cyclic.Group, *cyclic.Group) {
 
diff --git a/api/mockserver.go b/api/mockserver.go
index abeb89278e4ee7f74f9bac3dad43b70efd3c19a6..89a41be371ae9ceecf2e748f29e08737b8ff8c5a 100644
--- a/api/mockserver.go
+++ b/api/mockserver.go
@@ -11,6 +11,7 @@ import (
 	"gitlab.com/elixxir/client/cmixproto"
 	"gitlab.com/elixxir/client/parse"
 	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/large"
 	"gitlab.com/elixxir/primitives/id"
 	"sync"
@@ -77,16 +78,11 @@ func (m *TestInterface) PutMessage(msg *pb.Slot) bool {
 	return true
 }
 
-func (m *TestInterface) ConfirmNonce(message *pb.DSASignature) (*pb.RegistrationConfirmation, error) {
+func (m *TestInterface) ConfirmNonce(message *pb.RequestRegistrationConfirmation) (*pb.RegistrationConfirmation, error) {
 	regConfirmation := &pb.RegistrationConfirmation{
-		Server: &pb.DSAPublicKey{},
+		ClientSignedByServer: &pb.RSASignature{},
 	}
 
-	regConfirmation.Server.P = large.NewInt(1).Bytes()
-	regConfirmation.Server.Q = large.NewInt(1).Bytes()
-	regConfirmation.Server.G = large.NewInt(1).Bytes()
-	regConfirmation.Server.Y = large.NewInt(1).Bytes()
-
 	return regConfirmation, nil
 }
 
@@ -101,14 +97,41 @@ func (s *MockRegistration) RegisterNode(ID []byte,
 }
 
 // Registers a user and returns a signed public key
-func (s *MockRegistration) RegisterUser(registrationCode string,
-	Y, P, Q, G []byte) (hash, R, S []byte, err error) {
-	return nil, nil, nil, nil
+func (s *MockRegistration) RegisterUser(registrationCode,
+	key string) (hash []byte, err error) {
+	return nil, nil
+}
+
+func getDHPubKey() *cyclic.Int {
+	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),
+		large.NewIntFromString("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", 16))
+
+	dh := cmixGrp.RandomCoprime(cmixGrp.NewMaxInt())
+	return cmixGrp.ExpG(dh, cmixGrp.NewMaxInt())
 }
 
 // Pass-through for Registration Nonce Communication
 func (m *TestInterface) RequestNonce(message *pb.NonceRequest) (*pb.Nonce, error) {
-	return &pb.Nonce{}, nil
+	dh := getDHPubKey().Bytes()
+	return &pb.Nonce{
+		DHPubKey: dh,
+	}, nil
 }
 
 // Mock dummy storage interface for testing.
diff --git a/bots/bots_test.go b/bots/bots_test.go
index 88a7bafc0ba67a78dcd002d0fd05cfb016f2c9ad..ad22272a5d94dabe59f0d3b94a5ba87b73bb5c00 100644
--- a/bots/bots_test.go
+++ b/bots/bots_test.go
@@ -70,7 +70,7 @@ func TestMain(m *testing.M) {
 	cmixGrp, e2eGrp := getGroups()
 
 	fakeSession := user.NewSession(&globals.RamStorage{},
-		u, nil, nil, nil, cmixGrp, e2eGrp)
+		u, nil, nil, nil, nil, nil, cmixGrp, e2eGrp)
 	fakeComm := &dummyMessaging{
 		listener: ListenCh,
 	}
diff --git a/cmd/root.go b/cmd/root.go
index 7e761275eab0b0ffe2644889d69a8050c724091b..2b0caf60f1fdd4cd27a39b060db2c9c54b1f3f37 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -36,16 +36,13 @@ import (
 var verbose bool
 var userId uint64
 var destinationUserId uint64
-var gwAddresses []string
 var message string
 var sessionFile string
 var dummyFrequency float64
 var noBlockingTransmission bool
 var rateLimiting uint32
 var showVer bool
-var gwCertPath string
 var registrationCertPath string
-var registrationAddr string
 var registrationCode string
 var userEmail string
 var userNick string
@@ -56,6 +53,7 @@ var skipNDFVerification bool
 var ndfRegistration []string
 var ndfUDB []string
 var ndfPubKey string
+var noTLS bool
 
 // Execute adds all child commands to the root command and sets flags
 // appropriately.  This is called by main.main(). It only needs to
@@ -381,8 +379,14 @@ var rootCmd = &cobra.Command{
 			cryptoType = parse.E2E
 		}
 
-		// Only send a message if we have a message to send (except dummy messages)
-		recipientId := id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId})
+		var recipientId *id.User
+
+		if destinationUserId == 0 {
+			recipientId = userID
+		} else {
+			recipientId = id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId})
+		}
+
 		if message != "" {
 			// Get the recipient's nick
 			recipientNick := ""
@@ -504,20 +508,10 @@ func init() {
 
 	rootCmd.PersistentFlags().Uint64VarP(&userId, "userid", "i", 0,
 		"ID to sign in as")
-	rootCmd.PersistentFlags().StringSliceVarP(&gwAddresses, "gwaddresses",
-		"g", make([]string, 0), "Gateway addresses:port for message sending, "+
-			"comma-separated")
-	rootCmd.PersistentFlags().StringVarP(&gwCertPath, "gwcertpath", "c", "",
-		"Path to the certificate file for connecting to gateway using TLS")
 	rootCmd.PersistentFlags().StringVarP(&registrationCertPath, "registrationcertpath", "r",
 		"",
 		"Path to the certificate file for connecting to registration server"+
 			" using TLS")
-	rootCmd.PersistentFlags().StringVarP(&registrationAddr,
-		"registrationaddr", "a",
-		"",
-		"Address:Port for connecting to registration server"+
-			" using TLS")
 
 	rootCmd.PersistentFlags().StringVarP(&registrationCode,
 		"regcode", "e",
@@ -585,6 +579,9 @@ func init() {
 	rootCmd.PersistentFlags().StringSliceVarP(&keyParams, "keyParams", "",
 		make([]string, 0), "Define key generation parameters. Pass values in comma separated list"+
 			" in the following order: MinKeys,MaxKeys,NumRekeys,TTLScalar,MinNumKeys")
+
+	rootCmd.Flags().BoolVarP(&noTLS, "noTLS", "", false,
+		"Set to ignore TLS")
 }
 
 // initConfig reads in config file and ENV variables if set.
@@ -637,4 +634,14 @@ func overwriteNDF(n *ndf.NetworkDefinition) {
 		globals.Log.WARN.Println("Overwrote UDB values in the " +
 			"NetworkDefinition from the commandline")
 	}
+
+	if noTLS {
+		for i := 0; i < len(n.Nodes); i++ {
+			n.Nodes[i].TlsCertificate = ""
+		}
+		n.Registration.TlsCertificate = ""
+		for i := 0; i < len(n.Gateways); i++ {
+			n.Gateways[i].TlsCertificate = ""
+		}
+	}
 }
diff --git a/crypto/encryptdecrypt_test.go b/crypto/encryptdecrypt_test.go
index 4285747ec311fb5591cdeeefab589f9b5e1c5ec9..5ec2bdc6db91ac06b1680be054c67f2c24d7201a 100644
--- a/crypto/encryptdecrypt_test.go
+++ b/crypto/encryptdecrypt_test.go
@@ -81,7 +81,7 @@ func setup() {
 	}
 
 	session = user.NewSession(nil, u, nkMap,
-		nil, nil, cmixGrp, e2eGrp)
+		nil, nil, nil, nil, cmixGrp, e2eGrp)
 }
 
 func TestMain(m *testing.M) {
@@ -124,9 +124,9 @@ func TestFullEncryptDecrypt(t *testing.T) {
 	// This block imitates what the server does during the realtime
 	payloadA := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA())
 	payloadB := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB())
-	// Multiply payloadA by its server key
+	// Multiply payloadA and associated data by serverPayloadBkey
 	cmixGrp.Mul(payloadA, serverPayloadAKey, payloadA)
-	// Multiply payloadB by its server key
+	// Multiply payloadB data only by serverPayloadAkey
 	cmixGrp.Mul(payloadB, serverPayloadBKey, payloadB)
 
 	decMsg := format.NewMessage()
@@ -186,17 +186,17 @@ func TestFullEncryptDecrypt_Unsafe(t *testing.T) {
 	// This block imitates what the server does during the realtime
 	var encryptedNet *pb.Slot
 	{
-		payloadA := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA())
-		payloadB := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB())
-		// Multiply payloadA by transmission key
-		cmixGrp.Mul(payloadA, serverPayloadAKey, payloadA)
-		// Multiply payloadB by transmission key
-		cmixGrp.Mul(payloadB, serverPayloadBKey, payloadB)
+		payload := cmixGrp.NewIntFromBytes(encMsg.GetPayloadA())
+		assocData := cmixGrp.NewIntFromBytes(encMsg.GetPayloadB())
+		// Multiply payload and associated data by transmission key only
+		cmixGrp.Mul(payload, serverPayloadAKey, payload)
+		// Multiply associated data only by transmission key
+		cmixGrp.Mul(assocData, serverPayloadBKey, assocData)
 		encryptedNet = &pb.Slot{
 			SenderID: sender.Bytes(),
 			Salt:     salt,
-			PayloadA: payloadA.LeftpadBytes(uint64(format.PayloadLen)),
-			PayloadB: payloadB.LeftpadBytes(uint64(format.PayloadLen)),
+			PayloadA: payload.LeftpadBytes(uint64(format.PayloadLen)),
+			PayloadB: assocData.LeftpadBytes(uint64(format.PayloadLen)),
 		}
 	}
 
diff --git a/glide.yaml b/glide.yaml
index 1819086cd5dc7cbd637c11919299e54f7200a25e..404fd85339e3572c75cf665f48a8c31f6d05e063 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -4,15 +4,15 @@ import:
   version: master
   vcs: git
 - package: gitlab.com/elixxir/crypto
-  version: release
+  version: master
   repo: git@gitlab.com:elixxir/crypto
   vcs: git
 - package: gitlab.com/elixxir/comms
-  version: release
+  version: master
   repo: git@gitlab.com:elixxir/comms
   vcs: git
 - package: gitlab.com/elixxir/primitives
-  version: release
+  version: master
   repo: git@gitlab.com:elixxir/primitives
   vcs: git
 - package: github.com/mitchellh/go-homedir
diff --git a/rekey/rekey.go b/rekey/rekey.go
index 7f369a2c1fc8a3811f3b24578b33e790b63fdf35..e749340d822d094ad789ff900f2f61809bc40e04 100644
--- a/rekey/rekey.go
+++ b/rekey/rekey.go
@@ -2,7 +2,6 @@ package rekey
 
 import (
 	"bytes"
-	"crypto/rand"
 	"fmt"
 	"gitlab.com/elixxir/client/cmixproto"
 	"gitlab.com/elixxir/client/globals"
@@ -14,7 +13,6 @@ import (
 	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/crypto/hash"
-	"gitlab.com/elixxir/crypto/signature"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/elixxir/primitives/id"
@@ -164,37 +162,36 @@ func rekeyProcess(rt rekeyType, partner *id.User, data []byte) error {
 	// Add context to RekeyManager in case of RekeyTrigger
 	var privKeyCyclic *cyclic.Int
 	var pubKeyCyclic *cyclic.Int
+	var partnerPubKeyCyclic *cyclic.Int
 	var baseKey *cyclic.Int
-	var pubKey *signature.DSAPublicKey
 	if ctx == nil {
 		if rt == RekeyTrigger {
-			params := signature.GetDefaultDSAParams()
-			privateKey := params.PrivateKeyGen(rand.Reader)
-			pubKey = privateKey.PublicKeyGen()
-			privKeyCyclic = grp.NewIntFromLargeInt(privateKey.GetKey())
+			privKeyCyclic = grp.RandomCoprime(grp.NewInt(1))
+			fmt.Println("Private key actual: ", privKeyCyclic.Text(16))
+			pubKeyCyclic = grp.ExpG(privKeyCyclic, grp.NewInt(1))
 			// Get Current Partner Public Key from RekeyKeys
-			pubKeyCyclic = keys.CurrPubKey
+			partnerPubKeyCyclic = keys.CurrPubKey
 			// Set new Own Private Key
 			keys.NewPrivKey = privKeyCyclic
 		} else {
 			// Get Current Own Private Key from RekeyKeys
 			privKeyCyclic = keys.CurrPrivKey
 			// Get Partner New Public Key from data
-			pubKeyCyclic = grp.NewIntFromBytes(data)
+			partnerPubKeyCyclic = grp.NewIntFromBytes(data)
 			// Set new Partner Public Key
-			keys.NewPubKey = pubKeyCyclic
+			keys.NewPubKey = partnerPubKeyCyclic
 		}
 
 		// Generate baseKey
 		baseKey, _ = diffieHellman.CreateDHSessionKey(
-			pubKeyCyclic,
+			partnerPubKeyCyclic,
 			privKeyCyclic,
 			grp)
 
 		ctx = &keyStore.RekeyContext{
 			BaseKey: baseKey,
 			PrivKey: privKeyCyclic,
-			PubKey:  pubKeyCyclic,
+			PubKey:  partnerPubKeyCyclic,
 		}
 
 		if rt == RekeyTrigger {
@@ -254,7 +251,7 @@ func rekeyProcess(rt rekeyType, partner *id.User, data []byte) error {
 		// This ensures that the publicKey fits in a single message, which
 		// is sent with E2E encryption using a send Rekey, and without padding
 		return messaging.SendMessageNoPartition(session, topology, partner, parse.E2E,
-			pubKey.GetKey().LeftpadBytes(uint64(format.ContentsLen)))
+			pubKeyCyclic.LeftpadBytes(uint64(format.ContentsLen)))
 	case Rekey:
 		// Send rekey confirm message with hash of the baseKey
 		h, _ := hash.NewCMixHash()
diff --git a/rekey/rekey_test.go b/rekey/rekey_test.go
index 6580a0f5e95fae24db97de64910c311d838d340e..3cffc7fb951b548bf780b029954592fbc5eda16e 100644
--- a/rekey/rekey_test.go
+++ b/rekey/rekey_test.go
@@ -2,6 +2,7 @@ package rekey
 
 import (
 	"bytes"
+	"fmt"
 	"gitlab.com/elixxir/client/cmixproto"
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/client/keyStore"
@@ -13,7 +14,7 @@ import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/crypto/large"
-	"gitlab.com/elixxir/crypto/signature"
+	"gitlab.com/elixxir/crypto/signature/rsa"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/id"
 	"os"
@@ -56,25 +57,22 @@ func TestMain(m *testing.M) {
 
 	grp, e2eGrp := getGroups()
 	user.InitUserRegistry(grp)
-	params := signature.CustomDSAParams(
-		grp.GetP(),
-		grp.GetQ(),
-		grp.GetG())
 	rng := csprng.NewSystemRNG()
 	u := &user.User{
 		User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}),
 		Nick: "Bernie",
 	}
-	myPrivKey := params.PrivateKeyGen(rng)
-	myPrivKeyCyclic := grp.NewIntFromLargeInt(myPrivKey.GetKey())
-	myPubKey := myPrivKey.PublicKeyGen()
+	myPrivKeyCyclic := grp.RandomCoprime(grp.NewMaxInt())
+	myPubKeyCyclic := grp.ExpG(myPrivKeyCyclic, grp.NewInt(1))
 	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
-	partnerPrivKey := params.PrivateKeyGen(rng)
-	partnerPubKey := partnerPrivKey.PublicKeyGen()
-	partnerPubKeyCyclic := grp.NewIntFromLargeInt(partnerPubKey.GetKey())
+
+	partnerPubKeyCyclic := grp.RandomCoprime(grp.NewMaxInt())
+
+	privateKeyRSA, _ := rsa.GenerateKey(rng, 768)
+	publicKeyRSA := rsa.PublicKey{PublicKey: privateKeyRSA.PublicKey}
 
 	session := user.NewSession(&globals.RamStorage{},
-		u, nil, myPubKey, myPrivKey, grp, e2eGrp)
+		u, nil, &publicKeyRSA, privateKeyRSA, myPubKeyCyclic, myPrivKeyCyclic, grp, e2eGrp)
 	ListenCh = make(chan []byte, 100)
 	fakeComm := &dummyMessaging{
 		listener: ListenCh,
@@ -146,13 +144,15 @@ func TestRekeyTrigger(t *testing.T) {
 	grp := session.GetCmixGroup()
 	actualPubKey := grp.NewIntFromBytes(value)
 	privKey := session.GetRekeyManager().GetCtx(partnerID).PrivKey
+	fmt.Println("privKey: ", privKey.Text(16))
 	expectedPubKey := grp.NewInt(1)
 	grp.ExpG(privKey, expectedPubKey)
+	fmt.Println("new pub key: ", value)
 
 	if expectedPubKey.Cmp(actualPubKey) != 0 {
 		t.Errorf("RekeyTrigger publicKey mismatch, expected %s,"+
-			" got %s", expectedPubKey.Text(10),
-			actualPubKey.Text(10))
+			" got %s", expectedPubKey.Text(16),
+			actualPubKey.Text(16))
 	}
 
 	// Check that trying to send another rekeyTrigger message returns an error
@@ -216,7 +216,7 @@ func TestRekeyConfirm(t *testing.T) {
 
 	// Confirm that user Private key in Send Key Manager
 	// differs from the one stored in session
-	if session.GetPrivateKey().GetKey().Cmp(
+	if session.GetDHPrivateKey().GetLargeInt().Cmp(
 		session.GetKeyStore().GetSendManager(partnerID).
 			GetPrivKey().GetLargeInt()) == 0 {
 		t.Errorf("PrivateKey remained unchanged after Outgoing Rekey!")
@@ -247,19 +247,14 @@ func TestRekey(t *testing.T) {
 	km := session.GetKeyStore().GetSendManager(partnerID)
 	// Generate new partner public key
 	grp, _ := getGroups()
-	params := signature.CustomDSAParams(
-		grp.GetP(),
-		grp.GetQ(),
-		grp.GetG())
-	rng := csprng.NewSystemRNG()
-	partnerPrivKey := params.PrivateKeyGen(rng)
-	partnerPubKey := partnerPrivKey.PublicKeyGen()
+	privKey := grp.RandomCoprime(grp.NewMaxInt())
+	pubKey := grp.ExpG(privKey, grp.NewMaxInt())
 	// Test receiving a Rekey message
 	msg := &parse.Message{
 		Sender: partnerID,
 		TypedBody: parse.TypedBody{
 			MessageType: int32(cmixproto.Type_NO_TYPE),
-			Body:        partnerPubKey.GetKey().Bytes(),
+			Body:        pubKey.Bytes(),
 		},
 		InferredType: parse.Rekey,
 		Receiver:     session.GetCurrentUser().User,
@@ -291,12 +286,12 @@ func TestRekey(t *testing.T) {
 	keys := rkm.GetKeys(partnerID)
 
 	if keys.CurrPrivKey.GetLargeInt().
-		Cmp(session.GetPrivateKey().GetKey()) == 0 {
+		Cmp(session.GetDHPrivateKey().GetLargeInt()) == 0 {
 		t.Errorf("Own PrivateKey didn't update properly after both parties rekeys")
 	}
 
 	if keys.CurrPubKey.GetLargeInt().
-		Cmp(partnerPubKey.GetKey()) != 0 {
+		Cmp(pubKey.GetLargeInt()) != 0 {
 		t.Errorf("Partner PublicKey didn't update properly after both parties rekeys")
 	}
 }
diff --git a/user/session.go b/user/session.go
index 43c8144e14f74d23c6343bb0aba34551858b6196..e6f792759c2fdfca666747e235d8979ca13732ed 100644
--- a/user/session.go
+++ b/user/session.go
@@ -15,7 +15,7 @@ import (
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/client/keyStore"
 	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/signature"
+	"gitlab.com/elixxir/crypto/signature/rsa"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/id"
 	"gitlab.com/elixxir/primitives/switchboard"
@@ -31,8 +31,10 @@ var ErrQuery = errors.New("element not in map")
 type Session interface {
 	GetCurrentUser() (currentUser *User)
 	GetKeys(topology *circuit.Circuit) []NodeKeys
-	GetPrivateKey() *signature.DSAPrivateKey
-	GetPublicKey() *signature.DSAPublicKey
+	GetRSAPrivateKey() *rsa.PrivateKey
+	GetRSAPublicKey() *rsa.PublicKey
+	GetDHPrivateKey() *cyclic.Int
+	GetDHPublicKey() *cyclic.Int
 	GetCmixGroup() *cyclic.Group
 	GetE2EGroup() *cyclic.Group
 	GetLastMessageID() string
@@ -59,16 +61,20 @@ type NodeKeys struct {
 // Creates a new Session interface for registration
 func NewSession(store globals.Storage,
 	u *User, nk map[id.Node]NodeKeys,
-	publicKey *signature.DSAPublicKey,
-	privateKey *signature.DSAPrivateKey,
+	publicKeyRSA *rsa.PublicKey,
+	privateKeyRSA *rsa.PrivateKey,
+	publicKeyDH *cyclic.Int,
+	privateKeyDH *cyclic.Int,
 	cmixGrp, e2eGrp *cyclic.Group) Session {
 
 	// With an underlying Session data structure
 	return Session(&SessionObj{
 		CurrentUser:         u,
 		Keys:                nk,
-		PrivateKey:          privateKey,
-		PublicKey:           publicKey,
+		RSAPublicKey:        publicKeyRSA,
+		RSAPrivateKey:       privateKeyRSA,
+		DHPublicKey:         publicKeyDH,
+		DHPrivateKey:        privateKeyDH,
 		CmixGrp:             cmixGrp,
 		E2EGrp:              e2eGrp,
 		InterfaceMap:        make(map[string]interface{}),
@@ -147,11 +153,13 @@ type SessionObj struct {
 	// Currently authenticated user
 	CurrentUser *User
 
-	Keys       map[id.Node]NodeKeys
-	PrivateKey *signature.DSAPrivateKey
-	PublicKey  *signature.DSAPublicKey
-	CmixGrp    *cyclic.Group
-	E2EGrp     *cyclic.Group
+	Keys          map[id.Node]NodeKeys
+	RSAPrivateKey *rsa.PrivateKey
+	RSAPublicKey  *rsa.PublicKey
+	DHPrivateKey  *cyclic.Int
+	DHPublicKey   *cyclic.Int
+	CmixGrp       *cyclic.Group
+	E2EGrp        *cyclic.Group
 
 	// Last received message ID. Check messages after this on the gateway.
 	LastMessageID string
@@ -203,16 +211,28 @@ func (s *SessionObj) GetKeys(topology *circuit.Circuit) []NodeKeys {
 	return keys
 }
 
-func (s *SessionObj) GetPrivateKey() *signature.DSAPrivateKey {
+func (s *SessionObj) GetRSAPrivateKey() *rsa.PrivateKey {
 	s.LockStorage()
 	defer s.UnlockStorage()
-	return s.PrivateKey
+	return s.RSAPrivateKey
 }
 
-func (s *SessionObj) GetPublicKey() *signature.DSAPublicKey {
+func (s *SessionObj) GetRSAPublicKey() *rsa.PublicKey {
 	s.LockStorage()
 	defer s.UnlockStorage()
-	return s.PublicKey
+	return s.RSAPublicKey
+}
+
+func (s *SessionObj) GetDHPrivateKey() *cyclic.Int {
+	s.LockStorage()
+	defer s.UnlockStorage()
+	return s.DHPrivateKey
+}
+
+func (s *SessionObj) GetDHPublicKey() *cyclic.Int {
+	s.LockStorage()
+	defer s.UnlockStorage()
+	return s.DHPublicKey
 }
 
 func (s *SessionObj) GetCmixGroup() *cyclic.Group {
diff --git a/user/session_test.go b/user/session_test.go
index a54f6beb2e59caa674ed7b792a3fcd980966adce..9d170a05fd9e789f503e8647b45977460035a1e4 100644
--- a/user/session_test.go
+++ b/user/session_test.go
@@ -11,7 +11,7 @@ import (
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/large"
-	"gitlab.com/elixxir/crypto/signature"
+	"gitlab.com/elixxir/crypto/signature/rsa"
 	"gitlab.com/elixxir/primitives/circuit"
 	"gitlab.com/elixxir/primitives/id"
 	"math/rand"
@@ -51,14 +51,16 @@ func TestUserSession(t *testing.T) {
 	storage := &globals.RamStorage{}
 
 	rng := rand.New(rand.NewSource(42))
-	params := signature.NewDSAParams(rng, signature.L1024N160)
-	privateKey := params.PrivateKeyGen(rng)
-	publicKey := privateKey.PublicKeyGen()
+	privateKey, _ := rsa.GenerateKey(rng, 768)
+	publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey}
 
 	cmixGrp, e2eGrp := getGroups()
 
+	privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1))
+	publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1))
+
 	ses := NewSession(storage,
-		u, keys, publicKey, privateKey, cmixGrp, e2eGrp)
+		u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp)
 
 	ses.SetLastMessageID("totally unique ID")
 
@@ -118,10 +120,26 @@ func TestUserSession(t *testing.T) {
 
 		for i := 0; i < len(ses.GetKeys(topology)); i++ {
 
-			if !reflect.DeepEqual(*ses.GetPublicKey(), *publicKey) {
+			sesPriv := ses.GetRSAPrivateKey().PrivateKey
+			if !reflect.DeepEqual(*ses.GetRSAPublicKey(), publicKey) {
 				t.Errorf("Error: Public key not set correctly!")
-			} else if !reflect.DeepEqual(*ses.GetPrivateKey(), *privateKey) {
-				t.Errorf("Error: Private key not set correctly!")
+			} else if !reflect.DeepEqual(sesPriv, privateKey.PrivateKey) {
+				orig := privateKey.PrivateKey
+				if sesPriv.E != orig.E {
+					t.Errorf("Error: Private key not set correctly E!  \nExpected: %+v\nreceived: %+v",
+						orig.E, sesPriv.E)
+				} else if sesPriv.D.Cmp(orig.D) != 0 {
+					t.Errorf("Error: Private key not set correctly D!  \nExpected: %+v\nreceived: %+v",
+						orig.D, sesPriv.D)
+				} else if sesPriv.N.Cmp(orig.N) != 0 {
+					t.Errorf("Error: Private key not set correctly N!  \nExpected: %+v\nreceived: %+v",
+						orig.N, sesPriv.N)
+				} else if !reflect.DeepEqual(sesPriv.Primes, orig.Primes) {
+					t.Errorf("Error: Private key not set correctly PRIMES!  \nExpected: %+v\nreceived: %+v",
+						orig, sesPriv)
+				} else {
+					t.Log("DeepEqual failed, but values are equal...")
+				}
 			} else if ses.GetKeys(topology)[i].ReceptionKey.Cmp(grp.
 				NewInt(2)) != 0 {
 				t.Errorf("Error: Reception key not set correctly!")
@@ -135,7 +153,7 @@ func TestUserSession(t *testing.T) {
 	}
 
 	//TODO: FIX THIS?
-	if ses.GetPrivateKey() == nil {
+	if ses.GetRSAPrivateKey() == nil {
 		t.Errorf("Error: Private Keys not set correctly!")
 	} else {
 		pass++
@@ -212,15 +230,17 @@ func TestGetPubKey(t *testing.T) {
 	}
 
 	rng := rand.New(rand.NewSource(42))
-	params := signature.NewDSAParams(rng, signature.L1024N160)
-	privateKey := params.PrivateKeyGen(rng)
-	publicKey := privateKey.PublicKeyGen()
+	privateKey, _ := rsa.GenerateKey(rng, 768)
+	publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey}
 
 	cmixGrp, e2eGrp := getGroups()
 
-	ses := NewSession(nil, u, keys, publicKey, privateKey, cmixGrp, e2eGrp)
+	privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1))
+	publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1))
+
+	ses := NewSession(nil, u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp)
 
-	pubKey := ses.GetPublicKey()
+	pubKey := *ses.GetRSAPublicKey()
 	if !reflect.DeepEqual(pubKey, publicKey) {
 		t.Errorf("Public key not returned correctly!")
 	}
@@ -243,15 +263,17 @@ func TestGetPrivKey(t *testing.T) {
 	}
 
 	rng := rand.New(rand.NewSource(42))
-	params := signature.NewDSAParams(rng, signature.L1024N160)
-	privateKey := params.PrivateKeyGen(rng)
-	publicKey := privateKey.PublicKeyGen()
+	privateKey, _ := rsa.GenerateKey(rng, 768)
+	publicKey := rsa.PublicKey{PublicKey: privateKey.PublicKey}
 
 	cmixGrp, e2eGrp := getGroups()
 
-	ses := NewSession(nil, u, keys, publicKey, privateKey, cmixGrp, e2eGrp)
+	privateKeyDH := cmixGrp.RandomCoprime(cmixGrp.NewInt(1))
+	publicKeyDH := cmixGrp.ExpG(privateKeyDH, cmixGrp.NewInt(1))
+
+	ses := NewSession(nil, u, keys, &publicKey, privateKey, publicKeyDH, privateKeyDH, cmixGrp, e2eGrp)
 
-	privKey := ses.GetPrivateKey()
+	privKey := ses.GetRSAPrivateKey()
 	if !reflect.DeepEqual(*privKey, *privateKey) {
 		t.Errorf("Private key is not returned correctly!")
 	}