diff --git a/cmix/nodes/interfaces.go b/cmix/nodes/interfaces.go
new file mode 100644
index 0000000000000000000000000000000000000000..cced1ecd17772741bf647cdde9c41fe901c8f522
--- /dev/null
+++ b/cmix/nodes/interfaces.go
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package nodes
+
+import (
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"time"
+)
+
+// Session is a sub-interface of the storage.Session interface relevant to
+// the methods used in this package.
+type Session interface {
+	GetTransmissionID() *id.ID
+	IsPrecanned() bool
+	GetTransmissionRSA() *rsa.PrivateKey
+	GetRegistrationTimestamp() time.Time
+	GetTransmissionSalt() []byte
+	GetTransmissionRegistrationValidationSignature() []byte
+}
diff --git a/cmix/nodes/register.go b/cmix/nodes/register.go
index af18976e4402845ea513aae0e8ae400f6683bbb5..9a3c3854481e9b48ec200657db88a9672a267fa6 100644
--- a/cmix/nodes/register.go
+++ b/cmix/nodes/register.go
@@ -10,31 +10,19 @@ package nodes
 import (
 	"crypto/sha256"
 	"encoding/hex"
+	"gitlab.com/xx_network/crypto/csprng"
 	"strconv"
 	"sync"
 	"time"
 
-	"github.com/golang/protobuf/proto"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/cmix/gateway"
 	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/client/storage"
-	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/comms/network"
 	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/diffieHellman"
-	"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/chacha"
-	"gitlab.com/xx_network/crypto/csprng"
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/crypto/tls"
-	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
-	"gitlab.com/xx_network/primitives/netTime"
 )
 
 func registerNodes(r *registrar, s storage.Session, stop *stoppable.Single,
@@ -64,7 +52,8 @@ func registerNodes(r *registrar, s storage.Session, stop *stoppable.Single,
 					"Not registering node %s, already registered", nid)
 			}
 
-			if _, operating := inProgress.LoadOrStore(nidStr, struct{}{}); operating {
+			if _, operating := inProgress.LoadOrStore(nidStr,
+				struct{}{}); operating {
 				continue
 			}
 
@@ -105,8 +94,8 @@ func registerNodes(r *registrar, s storage.Session, stop *stoppable.Single,
 // registerWithNode serves as a helper for registerNodes. It registers a user
 // with a specific in the client's NDF.
 func registerWithNode(sender gateway.Sender, comms RegisterNodeCommsInterface,
-	ngw network.NodeGateway, s storage.Session, r *registrar, rng csprng.Source,
-	stop *stoppable.Single) error {
+	ngw network.NodeGateway, s Session, r *registrar,
+	rng csprng.Source, stop *stoppable.Single) error {
 
 	nodeID, err := ngw.Node.GetNodeId()
 	if err != nil {
@@ -118,7 +107,8 @@ func registerWithNode(sender gateway.Sender, comms RegisterNodeCommsInterface,
 		return nil
 	}
 
-	jww.INFO.Printf("registerWithNode begin registration with node: %s", nodeID)
+	jww.INFO.Printf("registerWithNode begin registration with node: %s",
+		nodeID)
 
 	var transmissionKey *cyclic.Int
 	var validUntil uint64
@@ -149,165 +139,3 @@ func registerWithNode(sender gateway.Sender, comms RegisterNodeCommsInterface,
 
 	return nil
 }
-
-func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface,
-	ngw network.NodeGateway, s storage.Session, r *registrar, rng csprng.Source,
-	stop *stoppable.Single) (*cyclic.Int, []byte, uint64, error) {
-
-	grp := r.session.GetCmixGroup()
-
-	prime := grp.GetPBytes()
-	keyLen := len(prime)
-	dhPrivBytes, err := csprng.GenerateInGroup(prime, keyLen, rng)
-	if err != nil {
-		return nil, nil, 0, err
-	}
-
-	dhPriv := grp.NewIntFromBytes(dhPrivBytes)
-
-	dhPub := diffieHellman.GeneratePublicKey(dhPriv, grp)
-
-	// Reconstruct client confirmation message
-	userPubKeyRSA := rsa.CreatePublicKeyPem(s.GetTransmissionRSA().GetPublic())
-	confirmation := &pb.ClientRegistrationConfirmation{
-		RSAPubKey: string(userPubKeyRSA),
-		Timestamp: s.GetRegistrationTimestamp().UnixNano(),
-	}
-	confirmationSerialized, err := proto.Marshal(confirmation)
-	if err != nil {
-		return nil, nil, 0, err
-	}
-
-	keyRequest := &pb.ClientKeyRequest{
-		Salt: s.GetTransmissionSalt(),
-		ClientTransmissionConfirmation: &pb.SignedRegistrationConfirmation{
-			RegistrarSignature: &messages.RSASignature{
-				Signature: s.GetTransmissionRegistrationValidationSignature()},
-			ClientRegistrationConfirmation: confirmationSerialized,
-		},
-		ClientDHPubKey:        dhPub.Bytes(),
-		RegistrationTimestamp: s.GetRegistrationTimestamp().UnixNano(),
-		RequestTimestamp:      netTime.Now().UnixNano(),
-	}
-
-	serializedMessage, err := proto.Marshal(keyRequest)
-	if err != nil {
-		return nil, nil, 0, err
-	}
-
-	opts := rsa.NewDefaultOptions()
-	opts.Hash = hash.CMixHash
-	h := opts.Hash.New()
-	h.Write(serializedMessage)
-	data := h.Sum(nil)
-
-	// Sign DH pubkey
-	clientSig, err := rsa.Sign(rng, s.GetTransmissionRSA(), opts.Hash, data, opts)
-	if err != nil {
-		return nil, nil, 0, err
-	}
-
-	gwId := ngw.Gateway.ID
-	gatewayID, err := id.Unmarshal(gwId)
-	if err != nil {
-		jww.ERROR.Printf("registerWithNode failed to decode gateway ID: %v", err)
-		return nil, nil, 0, err
-	}
-
-	// Request nonce message from gateway
-	jww.INFO.Printf("Register: Requesting client key from gateway %s", gatewayID)
-
-	result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) {
-		keyResponse, err2 := comms.SendRequestClientKeyMessage(host,
-			&pb.SignedClientKeyRequest{
-				ClientKeyRequest:          serializedMessage,
-				ClientKeyRequestSignature: &messages.RSASignature{Signature: clientSig},
-				Target:                    gatewayID.Bytes(),
-			})
-		if err2 != nil {
-			return nil, errors.WithMessage(err2,
-				"Register: Failed requesting client key from gateway")
-		}
-		if keyResponse.Error != "" {
-			return nil, errors.WithMessage(err2,
-				"requestKey: clientKeyResponse error")
-		}
-
-		return keyResponse, nil
-	}, stop)
-
-	if err != nil {
-		return nil, nil, 0, err
-	}
-
-	signedKeyResponse := result.(*pb.SignedKeyResponse)
-	if signedKeyResponse.Error != "" {
-		return nil, nil, 0, errors.New(signedKeyResponse.Error)
-	}
-
-	// Hash the response
-	h.Reset()
-	h.Write(signedKeyResponse.KeyResponse)
-	hashedResponse := h.Sum(nil)
-
-	// Load nodes certificate
-	gatewayCert, err := tls.LoadCertificate(ngw.Gateway.TlsCertificate)
-	if err != nil {
-		return nil, nil, 0,
-			errors.WithMessagef(err, "Unable to load nodes's certificate")
-	}
-
-	// Extract public key
-	nodePubKey, err := tls.ExtractPublicKey(gatewayCert)
-	if err != nil {
-		return nil, nil, 0,
-			errors.WithMessagef(err, "Unable to load node's public key")
-	}
-
-	// Verify the response signature
-	err = rsa.Verify(nodePubKey, opts.Hash, hashedResponse,
-		signedKeyResponse.KeyResponseSignedByGateway.Signature, opts)
-	if err != nil {
-		return nil, nil, 0,
-			errors.WithMessagef(err, "Could not verify nodes's signature")
-	}
-
-	// Unmarshal the response
-	keyResponse := &pb.ClientKeyResponse{}
-	err = proto.Unmarshal(signedKeyResponse.KeyResponse, keyResponse)
-	if err != nil {
-		return nil, nil, 0,
-			errors.WithMessagef(err, "Failed to unmarshal client key response")
-	}
-
-	h.Reset()
-
-	// Convert Node DH Public key to a cyclic.Int
-	nodeDHPub := grp.NewIntFromBytes(keyResponse.NodeDHPubKey)
-
-	// Construct the session key
-	sessionKey := registration.GenerateBaseKey(grp,
-		nodeDHPub, dhPriv, h)
-
-	// Verify the HMAC
-	h.Reset()
-	if !registration.VerifyClientHMAC(sessionKey.Bytes(),
-		keyResponse.EncryptedClientKey, opts.Hash.New,
-		keyResponse.EncryptedClientKeyHMAC) {
-		return nil, nil, 0, errors.New("Failed to verify client HMAC")
-	}
-
-	// Decrypt the client key
-	clientKey, err := chacha.Decrypt(
-		sessionKey.Bytes(), keyResponse.EncryptedClientKey)
-	if err != nil {
-		return nil, nil, 0,
-			errors.WithMessagef(err, "Failed to decrypt client key")
-	}
-
-	// Construct the transmission key from the client key
-	transmissionKey := grp.NewIntFromBytes(clientKey)
-
-	// Use Client keypair to sign Server nonce
-	return transmissionKey, keyResponse.KeyID, keyResponse.ValidUntil, nil
-}
diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..fe251e46a97bae064b840e7bcc6ac84278a481fa
--- /dev/null
+++ b/cmix/nodes/request.go
@@ -0,0 +1,223 @@
+package nodes
+
+import (
+	"github.com/golang/protobuf/proto"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/cmix/gateway"
+	"gitlab.com/elixxir/client/stoppable"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
+	"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/chacha"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/crypto/tls"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/netTime"
+	"io"
+)
+
+// requestKey is a helper function which constructs a ClientKeyRequest message.
+// This message is sent to the passed gateway. It will further handle the
+// request from the gateway.
+func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface,
+	ngw network.NodeGateway, s Session, r *registrar,
+	rng io.Reader,
+	stop *stoppable.Single) (*cyclic.Int, []byte, uint64, error) {
+
+	// Generate a Diffie-Hellman keypair
+	grp := r.session.GetCmixGroup()
+
+	prime := grp.GetPBytes()
+	keyLen := len(prime)
+	dhPrivBytes, err := csprng.GenerateInGroup(prime, keyLen, rng)
+	if err != nil {
+		return nil, nil, 0, err
+	}
+	dhPriv := grp.NewIntFromBytes(dhPrivBytes)
+	dhPub := diffieHellman.GeneratePublicKey(dhPriv, grp)
+
+	// Parse the ID into an id.ID object.
+	gwId := ngw.Gateway.ID
+	gatewayID, err := id.Unmarshal(gwId)
+	if err != nil {
+		jww.ERROR.Printf("registerWithNode failed to decode "+
+			"gateway ID: %v", err)
+		return nil, nil, 0, err
+	}
+
+	signedKeyReq, err := makeSignedKeyRequest(s, rng, gatewayID, dhPub)
+	if err != nil {
+		return nil, nil, 0, err
+	}
+
+	// Request nonce message from gateway
+	jww.INFO.Printf("Register: Requesting client key from "+
+		"gateway %s", gatewayID)
+
+	result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) {
+		keyResponse, err2 := comms.SendRequestClientKeyMessage(host, signedKeyReq)
+		if err2 != nil {
+			return nil, errors.WithMessage(err2,
+				"Register: Failed requesting client key from gateway")
+		}
+		if keyResponse.Error != "" {
+			return nil, errors.WithMessage(err2,
+				"requestKey: clientKeyResponse error")
+		}
+
+		return keyResponse, nil
+	}, stop)
+
+	if err != nil {
+		return nil, nil, 0, err
+	}
+
+	// Cast the response
+	signedKeyResponse := result.(*pb.SignedKeyResponse)
+	if signedKeyResponse.Error != "" {
+		return nil, nil, 0, errors.New(signedKeyResponse.Error)
+	}
+
+	// Process the server's response
+	return processRequestResponse(signedKeyResponse, ngw, grp, dhPriv)
+}
+
+// makeSignedKeyRequest is a helper function which constructs a
+// pb.SignedClientKeyRequest to send to the node/gateway pair the
+// user is trying to register with.
+func makeSignedKeyRequest(s Session, rng io.Reader,
+	gwId *id.ID, dhPub *cyclic.Int) (*pb.SignedClientKeyRequest, error) {
+
+	// Reconstruct client confirmation message
+	userPubKeyRSA := rsa.CreatePublicKeyPem(s.GetTransmissionRSA().GetPublic())
+	confirmation := &pb.ClientRegistrationConfirmation{
+		RSAPubKey: string(userPubKeyRSA),
+		Timestamp: s.GetRegistrationTimestamp().UnixNano(),
+	}
+	confirmationSerialized, err := proto.Marshal(confirmation)
+	if err != nil {
+		return nil, err
+	}
+
+	// Construct a key request message
+	keyRequest := &pb.ClientKeyRequest{
+		Salt: s.GetTransmissionSalt(),
+		ClientTransmissionConfirmation: &pb.SignedRegistrationConfirmation{
+			RegistrarSignature: &messages.RSASignature{
+				Signature: s.GetTransmissionRegistrationValidationSignature()},
+			ClientRegistrationConfirmation: confirmationSerialized,
+		},
+		ClientDHPubKey:        dhPub.Bytes(),
+		RegistrationTimestamp: s.GetRegistrationTimestamp().UnixNano(),
+		RequestTimestamp:      netTime.Now().UnixNano(),
+	}
+
+	// Serialize the reconstructed message
+	serializedMessage, err := proto.Marshal(keyRequest)
+	if err != nil {
+		return nil, err
+	}
+
+	// Sign DH public key
+	opts := rsa.NewDefaultOptions()
+	opts.Hash = hash.CMixHash
+	h := opts.Hash.New()
+	h.Write(serializedMessage)
+	data := h.Sum(nil)
+	clientSig, err := rsa.Sign(rng, s.GetTransmissionRSA(), opts.Hash,
+		data, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	// Construct signed key request message
+	signedRequest := &pb.SignedClientKeyRequest{
+		ClientKeyRequest:          serializedMessage,
+		ClientKeyRequestSignature: &messages.RSASignature{Signature: clientSig},
+		Target:                    gwId.Bytes(),
+	}
+
+	return signedRequest, nil
+}
+
+// processRequestResponse is a helper function which handles the server's
+// key request response.
+func processRequestResponse(signedKeyResponse *pb.SignedKeyResponse,
+	ngw network.NodeGateway, grp *cyclic.Group,
+	dhPrivKey *cyclic.Int) (*cyclic.Int, []byte, uint64, error) {
+	// Define hashing algorithm
+	opts := rsa.NewDefaultOptions()
+	opts.Hash = hash.CMixHash
+	h := opts.Hash.New()
+
+	// Hash the response
+	h.Reset()
+	h.Write(signedKeyResponse.KeyResponse)
+	hashedResponse := h.Sum(nil)
+
+	// Load nodes certificate
+	gatewayCert, err := tls.LoadCertificate(ngw.Gateway.TlsCertificate)
+	if err != nil {
+		return nil, nil, 0,
+			errors.Errorf("Unable to load nodes's certificate: %+v", err)
+	}
+
+	// Extract public key
+	nodePubKey, err := tls.ExtractPublicKey(gatewayCert)
+	if err != nil {
+		return nil, nil, 0,
+			errors.Errorf("Unable to load node's public key: %v", err)
+	}
+
+	// Verify the response signature
+	err = rsa.Verify(nodePubKey, opts.Hash, hashedResponse,
+		signedKeyResponse.KeyResponseSignedByGateway.Signature, opts)
+	if err != nil {
+		return nil, nil, 0,
+			errors.Errorf("Could not verify nodes's signature: %v", err)
+	}
+
+	// Unmarshal the response
+	keyResponse := &pb.ClientKeyResponse{}
+	err = proto.Unmarshal(signedKeyResponse.KeyResponse, keyResponse)
+	if err != nil {
+		return nil, nil, 0,
+			errors.WithMessagef(err, "Failed to unmarshal client key response")
+	}
+
+	// Convert Node DH Public key to a cyclic.Int
+	nodeDHPub := grp.NewIntFromBytes(keyResponse.NodeDHPubKey)
+
+	// Construct the session key
+	h.Reset()
+	sessionKey := registration.GenerateBaseKey(grp,
+		nodeDHPub, dhPrivKey, h)
+
+	// Verify the HMAC
+	if !registration.VerifyClientHMAC(sessionKey.Bytes(),
+		keyResponse.EncryptedClientKey, opts.Hash.New,
+		keyResponse.EncryptedClientKeyHMAC) {
+		return nil, nil, 0, errors.New("Failed to verify client HMAC")
+	}
+
+	// Decrypt the client key
+	clientKey, err := chacha.Decrypt(
+		sessionKey.Bytes(), keyResponse.EncryptedClientKey)
+	if err != nil {
+		return nil, nil, 0,
+			errors.WithMessagef(err, "Failed to decrypt client key")
+	}
+
+	// Construct the transmission key from the client key
+	transmissionKey := grp.NewIntFromBytes(clientKey)
+
+	// Use Client keypair to sign Server nonce
+	return transmissionKey, keyResponse.KeyID, keyResponse.ValidUntil, nil
+}