diff --git a/auth/request.go b/auth/request.go
index 3a80c3c989c4ac5c755d558de46d72c94e60ec80..d37385815b55d2f6b1e87fabc5e1f167bb704360 100644
--- a/auth/request.go
+++ b/auth/request.go
@@ -31,6 +31,14 @@ import (
 
 const terminator = ";"
 
+// Error constant strings. Any changes to these should go over usages of the
+// affected messages in other applications (if applicable)
+const (
+	// ErrChannelExists is a message returned in state.Request when an
+	// authenticated channel exists between the partner and me.
+	ErrChannelExists = "Authenticated channel already established with partner"
+)
+
 // Request sends a contact request from the user identity in the imported e2e
 // structure to the passed contact, as well as the passed facts (will error if
 // they are too long).
@@ -46,8 +54,7 @@ func (s *state) Request(partner contact.Contact, myfacts fact.FactList) (id.Roun
 	// check that an authenticated channel does not already exist
 	if _, err := s.e2e.GetPartner(partner.ID); err == nil ||
 		!strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) {
-		return 0, errors.Errorf("Authenticated channel already " +
-			"established with partner")
+		return 0, errors.Errorf(ErrChannelExists)
 	}
 
 	return s.request(partner, myfacts, false)
diff --git a/cmd/backup.go b/cmd/backup.go
index c8a5c78608785a10f8b18d2813a5a9a4197c7933..f3c7f308d30b7f3d9f286970a8f72b8c5a9c0c2a 100644
--- a/cmd/backup.go
+++ b/cmd/backup.go
@@ -24,7 +24,7 @@ import (
 // loadOrInitBackup will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitBackup(backupPath string, backupPass string, password []byte, storeDir string,
-	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
 	jww.INFO.Printf("Using Backup sender")
 
 	// create a new client if none exist
@@ -92,7 +92,7 @@ func loadOrInitBackup(backupPath string, backupPass string, password []byte, sto
 		}
 	}
 
-	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
diff --git a/cmd/broadcast.go b/cmd/broadcast.go
index fc58be9a51a808ec4bad667de77b2934a0e57b77..ccb86bc76e6111ce6b736859264ab66b48ab8500 100644
--- a/cmd/broadcast.go
+++ b/cmd/broadcast.go
@@ -25,7 +25,9 @@ var broadcastCmd = &cobra.Command{
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		// Write user contact to file
 		user := client.GetReceptionIdentity()
diff --git a/cmd/connect.go b/cmd/connect.go
new file mode 100644
index 0000000000000000000000000000000000000000..9b11ffa9a184b0dc61a2f0822561936e2f1bcec4
--- /dev/null
+++ b/cmd/connect.go
@@ -0,0 +1,581 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package cmd
+
+import (
+	"fmt"
+	"github.com/spf13/cobra"
+	jww "github.com/spf13/jwalterweatherman"
+	"github.com/spf13/viper"
+	"gitlab.com/elixxir/client/catalog"
+	"gitlab.com/elixxir/client/connect"
+	"gitlab.com/elixxir/client/e2e"
+	"gitlab.com/elixxir/client/e2e/receive"
+	"gitlab.com/elixxir/client/xxdk"
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+)
+
+// connectionCmd handles the operation of connection operations within the CLI.
+var connectionCmd = &cobra.Command{
+	Use:   "connection",
+	Short: "Runs clients and servers in the connections paradigm.",
+	Args:  cobra.NoArgs,
+	Run: func(cmd *cobra.Command, args []string) {
+		logLevel := viper.GetUint(logLevelFlag)
+		logPath := viper.GetString(logFlag)
+		initLog(logLevel, logPath)
+		jww.INFO.Printf(Version())
+
+		statePass := parsePassword(viper.GetString(passwordFlag))
+		statePath := viper.GetString(sessionFlag)
+		regCode := viper.GetString(regCodeFlag)
+		cmixParams, e2eParams := initParams()
+		forceLegacy := viper.GetBool(forceLegacyFlag)
+		if viper.GetBool(connectionStartServerFlag) {
+			if viper.GetBool(connectionAuthenticatedFlag) {
+				secureConnServer(forceLegacy, statePass, statePath, regCode,
+					cmixParams, e2eParams)
+			} else {
+				insecureConnServer(forceLegacy, statePass, statePath, regCode,
+					cmixParams, e2eParams)
+			}
+		} else {
+			if viper.GetBool(connectionAuthenticatedFlag) {
+				secureConnClient(forceLegacy, statePass, statePath, regCode,
+					cmixParams, e2eParams)
+			} else {
+				insecureConnClient(forceLegacy, statePass, statePath, regCode,
+					cmixParams, e2eParams)
+			}
+
+		}
+
+	},
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Connection Server Logic
+////////////////////////////////////////////////////////////////////////////////////////////
+
+// Secure (authenticated) connection server path
+func secureConnServer(forceLegacy bool, statePass []byte, statePath, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) {
+	connChan := make(chan connect.Connection, 1)
+
+	// Load client state and identity------------------------------------------
+	net := loadOrInitCmix(statePass, statePath, regCode, cmixParams)
+	identity := loadOrInitReceptionIdentity(forceLegacy, net)
+
+	// Save contact file-------------------------------------------------------
+	writeContact(identity.GetContact())
+
+	// Handle incoming connections---------------------------------------------
+	authCb := connect.AuthenticatedCallback(
+		func(connection connect.AuthenticatedConnection) {
+			partnerId := connection.GetPartner().PartnerId()
+			jww.INFO.Printf("[CONN] Received authenticated connection from %s", partnerId)
+			fmt.Println("Established authenticated connection with client")
+
+			_, err := connection.RegisterListener(catalog.XxMessage, listener{"AuthServer"})
+			if err != nil {
+				jww.FATAL.Panicf("Failed to register listener for client message!")
+			}
+
+			connChan <- connection
+		})
+
+	// Start connection server-------------------------------------------------
+	connectionParam := connect.DefaultConnectionListParams()
+	connectServer, err := connect.StartAuthenticatedServer(identity,
+		authCb, net, e2eParams, connectionParam)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start authenticated "+
+			"connection server: %v", err)
+	}
+
+	fmt.Println("Established connection server, begin listening...")
+	jww.INFO.Printf("[CONN] Established connection server, begin listening...")
+
+	// Start network threads---------------------------------------------------
+	networkFollowerTimeout := 5 * time.Second
+	err = connectServer.Messenger.StartNetworkFollower(networkFollowerTimeout)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
+	}
+
+	// Set up a wait for the network to be connected
+	waitUntilConnected := func(connected chan bool) {
+		waitTimeout := 30 * time.Second
+		timeoutTimer := time.NewTimer(waitTimeout)
+		isConnected := false
+		// Wait until we connect or panic if we cannot before the timeout
+		for !isConnected {
+			select {
+			case isConnected = <-connected:
+				jww.INFO.Printf("Network Status: %v", isConnected)
+				break
+			case <-timeoutTimer.C:
+				jww.FATAL.Panicf("Timeout on starting network follower")
+			}
+		}
+	}
+
+	// Create a tracker channel to be notified of network changes
+	connected := make(chan bool, 10)
+	// Provide a callback that will be signalled when network health
+	// status changes
+	connectServer.Messenger.GetCmix().AddHealthCallback(
+		func(isConnected bool) {
+			connected <- isConnected
+		})
+	// Wait until connected or crash on timeout
+	waitUntilConnected(connected)
+
+	// Wait for connection establishment----------------------------------------
+
+	// Wait for connection to be established
+	connectionTimeout := time.NewTimer(240 * time.Second)
+	select {
+	case conn := <-connChan:
+		// Perform functionality shared by client & server
+		miscConnectionFunctions(connectServer.Messenger, conn)
+
+	case <-connectionTimeout.C:
+		connectionTimeout.Stop()
+		jww.FATAL.Panicf("[CONN] Failed to establish connection within " +
+			"default time period, closing process")
+	}
+
+	// Keep server running to receive messages------------------------------------
+	serverTimeout := viper.GetDuration(connectionServerTimeoutFlag)
+	if serverTimeout != 0 {
+		timer := time.NewTimer(serverTimeout)
+		select {
+		case <-timer.C:
+			fmt.Println("Shutting down connection server")
+			timer.Stop()
+			return
+		}
+	}
+
+	// Keep app running to receive messages------------------------------------
+
+	// Wait until the user terminates the program
+	c := make(chan os.Signal)
+	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+	<-c
+
+	err = connectServer.Messenger.StopNetworkFollower()
+	if err != nil {
+		jww.ERROR.Printf("Failed to stop network follower: %+v", err)
+	} else {
+		jww.INFO.Printf("Stopped network follower.")
+	}
+
+	os.Exit(0)
+
+}
+
+// Insecure (unauthenticated) connection server path
+func insecureConnServer(forceLegacy bool, statePass []byte, statePath, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) {
+
+	connChan := make(chan connect.Connection, 1)
+
+	// Load client state and identity------------------------------------------
+	net := loadOrInitCmix(statePass, statePath, regCode, cmixParams)
+	identity := loadOrInitReceptionIdentity(forceLegacy, net)
+
+	// Save contact file-------------------------------------------------------
+	writeContact(identity.GetContact())
+
+	// Handle incoming connections---------------------------------------------
+	cb := connect.Callback(func(connection connect.Connection) {
+		partnerId := connection.GetPartner().PartnerId()
+		jww.INFO.Printf("[CONN] Received connection request from %s", partnerId)
+		fmt.Println("Established connection with client")
+
+		_, err := connection.RegisterListener(catalog.XxMessage, listener{"ConnectionServer"})
+		if err != nil {
+			jww.FATAL.Panicf("Failed to register listener for client message!")
+		}
+
+		connChan <- connection
+	})
+
+	// Start connection server-------------------------------------------------
+	connectionParam := connect.DefaultConnectionListParams()
+	connectServer, err := connect.StartServer(identity,
+		cb, net, e2eParams, connectionParam)
+	if err != nil {
+		jww.FATAL.Panicf("[CONN] Failed to start connection server: %v", err)
+	}
+
+	fmt.Println("Established connection server, begin listening...")
+	jww.INFO.Printf("[CONN] Established connection server, begin listening...")
+
+	// Start network threads---------------------------------------------------
+	networkFollowerTimeout := 5 * time.Second
+	err = connectServer.Messenger.StartNetworkFollower(networkFollowerTimeout)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
+	}
+
+	// Set up a wait for the network to be connected
+	waitUntilConnected := func(connected chan bool) {
+		waitTimeout := 30 * time.Second
+		timeoutTimer := time.NewTimer(waitTimeout)
+		isConnected := false
+		// Wait until we connect or panic if we cannot before the timeout
+		for !isConnected {
+			select {
+			case isConnected = <-connected:
+				jww.INFO.Printf("Network Status: %v", isConnected)
+				break
+			case <-timeoutTimer.C:
+				jww.FATAL.Panicf("Timeout on starting network follower")
+			}
+		}
+	}
+
+	// Create a tracker channel to be notified of network changes
+	connected := make(chan bool, 10)
+	// Provide a callback that will be signalled when network health
+	// status changes
+	connectServer.Messenger.GetCmix().AddHealthCallback(
+		func(isConnected bool) {
+			connected <- isConnected
+		})
+	// Wait until connected or crash on timeout
+	waitUntilConnected(connected)
+
+	// Wait for connection establishment----------------------------------------
+
+	// Wait for connection to be established
+	connectionTimeout := time.NewTimer(240 * time.Second)
+	select {
+	case conn := <-connChan:
+		// Perform functionality shared by client & server
+		miscConnectionFunctions(connectServer.Messenger, conn)
+
+	case <-connectionTimeout.C:
+		connectionTimeout.Stop()
+		jww.FATAL.Panicf("[CONN] Failed to establish connection within " +
+			"default time period, closing process")
+	}
+
+	// Keep server running to receive messages------------------------------------
+	if viper.GetDuration(connectionServerTimeoutFlag) != 0 {
+		timer := time.NewTimer(viper.GetDuration(connectionServerTimeoutFlag))
+		select {
+		case <-timer.C:
+			fmt.Println("Shutting down connection server")
+			timer.Stop()
+			return
+		}
+	}
+	// Keep app running to receive messages------------------------------------
+
+	// Wait until the user terminates the program
+	c := make(chan os.Signal)
+	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+	<-c
+
+	err = connectServer.Messenger.StopNetworkFollower()
+	if err != nil {
+		jww.ERROR.Printf("Failed to stop network follower: %+v", err)
+	} else {
+		jww.INFO.Printf("Stopped network follower.")
+	}
+
+	os.Exit(0)
+
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Connection Client Logic
+////////////////////////////////////////////////////////////////////////////////////////////
+
+// Secure (authenticated) connection client path
+func secureConnClient(forceLegacy bool, statePass []byte, statePath, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) {
+	// Load client ------------------------------------------------------------------
+	var messenger *xxdk.E2e
+	if viper.GetBool(connectionEphemeralFlag) {
+		fmt.Println("Loading ephemerally")
+		messenger = loadOrInitEphemeral(forceLegacy, statePass, statePath, regCode,
+			cmixParams, e2eParams, xxdk.DefaultAuthCallbacks{})
+	} else {
+		fmt.Println("Loading non-ephemerally")
+		messenger = loadOrInitMessenger(forceLegacy, statePass, statePath, regCode,
+			cmixParams, e2eParams, xxdk.DefaultAuthCallbacks{})
+	}
+
+	// Start network threads---------------------------------------------------------
+
+	// Set networkFollowerTimeout to a value of your choice (seconds)
+	networkFollowerTimeout := 5 * time.Second
+	err := messenger.StartNetworkFollower(networkFollowerTimeout)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
+	}
+
+	// Set up a wait for the network to be connected
+	waitUntilConnected := func(connected chan bool) {
+		waitTimeout := 30 * time.Second
+		timeoutTimer := time.NewTimer(waitTimeout)
+		isConnected := false
+		// Wait until we connect or panic if we cannot before the timeout
+		for !isConnected {
+			select {
+			case isConnected = <-connected:
+				jww.INFO.Printf("Network Status: %v", isConnected)
+				break
+			case <-timeoutTimer.C:
+				jww.FATAL.Panicf("Timeout on starting network follower")
+			}
+		}
+	}
+
+	// Create a tracker channel to be notified of network changes
+	connected := make(chan bool, 10)
+	// Provide a callback that will be signalled when network
+	// health status changes
+	messenger.GetCmix().AddHealthCallback(
+		func(isConnected bool) {
+			connected <- isConnected
+		})
+	// Wait until connected or crash on timeout
+	waitUntilConnected(connected)
+
+	// Connect with the server-------------------------------------------------
+	contactPath := viper.GetString(connectionFlag)
+	serverContact := getContactFromFile(contactPath)
+	fmt.Println("Sending connection request")
+
+	// Establish connection with partner
+	conn, err := connect.ConnectWithAuthentication(serverContact, messenger,
+		e2eParams)
+	if err != nil {
+		jww.FATAL.Panicf("[CONN] Failed to build connection with %s: %v",
+			serverContact.ID, err)
+	}
+
+	jww.INFO.Printf("[CONN] Established authenticated connection with %s",
+		conn.GetPartner().PartnerId())
+	fmt.Println("Established authenticated connection with server.")
+
+	miscConnectionFunctions(messenger, conn)
+
+}
+
+// Insecure (unauthenticated) connection client path
+func insecureConnClient(forceLegacy bool, statePass []byte, statePath, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) {
+
+	// Load client ------------------------------------------------------------------
+	var messenger *xxdk.E2e
+	if viper.GetBool(connectionEphemeralFlag) {
+		fmt.Println("Loading ephemerally")
+		messenger = loadOrInitEphemeral(forceLegacy, statePass, statePath, regCode,
+			cmixParams, e2eParams, xxdk.DefaultAuthCallbacks{})
+	} else {
+		fmt.Println("Loading non-ephemerally")
+		messenger = loadOrInitMessenger(forceLegacy, statePass, statePath, regCode,
+			cmixParams, e2eParams, xxdk.DefaultAuthCallbacks{})
+	}
+
+	// Start network threads---------------------------------------------------------
+
+	// Set networkFollowerTimeout to a value of your choice (seconds)
+	networkFollowerTimeout := 5 * time.Second
+	err := messenger.StartNetworkFollower(networkFollowerTimeout)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
+	}
+
+	// Set up a wait for the network to be connected
+	waitUntilConnected := func(connected chan bool) {
+		waitTimeout := 30 * time.Second
+		timeoutTimer := time.NewTimer(waitTimeout)
+		isConnected := false
+		// Wait until we connect or panic if we cannot before the timeout
+		for !isConnected {
+			select {
+			case isConnected = <-connected:
+				jww.INFO.Printf("Network Status: %v", isConnected)
+				break
+			case <-timeoutTimer.C:
+				jww.FATAL.Panicf("Timeout on starting network follower")
+			}
+		}
+	}
+
+	// Create a tracker channel to be notified of network changes
+	connected := make(chan bool, 10)
+	// Provide a callback that will be signalled when network
+	// health status changes
+	messenger.GetCmix().AddHealthCallback(
+		func(isConnected bool) {
+			connected <- isConnected
+		})
+	// Wait until connected or crash on timeout
+	waitUntilConnected(connected)
+
+	// Connect with the server-------------------------------------------------
+	contactPath := viper.GetString(connectionFlag)
+	serverContact := getContactFromFile(contactPath)
+	fmt.Println("Sending connection request")
+	jww.INFO.Printf("[CONN] Sending connection request to %s",
+		serverContact.ID)
+
+	// Establish connection with partner
+	handler, err := connect.Connect(serverContact, messenger,
+		e2eParams)
+	if err != nil {
+		jww.FATAL.Panicf("[CONN] Failed to build connection with %s: %v",
+			serverContact.ID, err)
+
+	}
+
+	fmt.Println("Established connection with server")
+	jww.INFO.Printf("[CONN] Established connection with %s", handler.GetPartner().PartnerId())
+
+	miscConnectionFunctions(messenger, handler)
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Misc Logic (shared between client & server)
+////////////////////////////////////////////////////////////////////////////////////////////
+
+// miscConnectionFunctions contains miscellaneous functionality for the subcommand connect.
+// This functionality should be shared between client & server.
+func miscConnectionFunctions(client *xxdk.E2e, conn connect.Connection) {
+	// Send a message to connection partner--------------------------------------------
+	msgBody := viper.GetString(messageFlag)
+	paramsE2E := e2e.GetDefaultParams()
+	if msgBody != "" {
+		// Send message
+		jww.INFO.Printf("[CONN] Sending message to %s",
+			conn.GetPartner().PartnerId())
+		payload := []byte(msgBody)
+		for {
+			roundIDs, _, _, err := conn.SendE2E(catalog.XxMessage, payload,
+				paramsE2E)
+			if err != nil {
+				jww.FATAL.Panicf("[CONN] Failed to send E2E message: %v", err)
+			}
+
+			// Verify message sends were successful when verifySendFlag is present
+			if viper.GetBool(verifySendFlag) {
+				if !verifySendSuccess(client, paramsE2E, roundIDs,
+					conn.GetPartner().PartnerId(), payload) {
+					continue
+				}
+			}
+			jww.INFO.Printf("[CONN] Sent message %q to %s", msgBody,
+				conn.GetPartner().PartnerId())
+			fmt.Printf("Sent message %q to connection partner.\n", msgBody)
+			break
+		}
+	}
+
+	// Disconnect from connection partner--------------------------------------------
+	if viper.GetBool(connectionDisconnectFlag) {
+		// Close the connection
+		if err := conn.Close(); err != nil {
+			jww.FATAL.Panicf("Failed to disconnect with %s: %v",
+				conn.GetPartner().PartnerId(), err)
+		}
+		jww.INFO.Printf("[CONN] Disconnected from %s",
+			conn.GetPartner().PartnerId())
+		fmt.Println("Disconnected from partner")
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Recreated Callback & Listener for connection testing
+///////////////////////////////////////////////////////////////////////////////
+
+//var connAuthCbs *authConnHandler
+
+// listener implements the receive.Listener interface
+type listener struct {
+	name string
+}
+
+// Hear will be called whenever a message matching
+// the RegisterListener call is received
+// User-defined message handling logic goes here
+func (l listener) Hear(item receive.Message) {
+	fmt.Printf("%s heard message \"%s\"\n", l.name, string(item.Payload))
+}
+
+// Name is used for debugging purposes
+func (l listener) Name() string {
+	return l.name
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Command Line Flags                                                         /
+///////////////////////////////////////////////////////////////////////////////
+
+// init initializes commands and flags for Cobra.
+func init() {
+	connectionCmd.Flags().String(connectionFlag, "",
+		"This flag is a client side operation. "+
+			"This flag expects a path to a contact file (similar "+
+			"to destfile). It will parse this into an contact object,"+
+			" referred to as a server contact. The client will "+
+			"establish a connection with the server contact. "+
+			"If a connection already exists between "+
+			"the client and the server, this will be used instead of "+
+			"resending a connection request to the server.")
+	bindFlagHelper(connectionFlag, connectionCmd)
+
+	connectionCmd.Flags().Bool(connectionStartServerFlag, false,
+		"This flag is a server-side operation and takes no arguments. "+
+			"This initiates a connection server. "+
+			"Calling this flag will have this process call "+
+			"connection.StartServer().")
+	bindFlagHelper(connectionStartServerFlag, connectionCmd)
+
+	connectionCmd.Flags().Duration(connectionServerTimeoutFlag, time.Duration(0),
+		"This flag is a connection parameter. "+
+			"This takes as an argument a time.Duration. "+
+			"This duration specifies how long a server will run before "+
+			"closing. Without this flag present, a server will be "+
+			"long-running.")
+	bindFlagHelper(connectionServerTimeoutFlag, connectionCmd)
+
+	connectionCmd.Flags().Bool(connectionDisconnectFlag, false,
+		"This flag is available to both server and client. "+
+			"This uses a contact object from a file specified by --destfile."+
+			"This will close the connection with the given contact "+
+			"if it exists.")
+	bindFlagHelper(connectionDisconnectFlag, connectionCmd)
+
+	connectionCmd.Flags().Bool(connectionAuthenticatedFlag, false,
+		"This flag is available to both server and client. "+
+			"This flag operates as a switch for the authenticated code-path. "+
+			"With this flag present, any additional connection related flags"+
+			" will call the applicable authenticated counterpart")
+	bindFlagHelper(connectionAuthenticatedFlag, connectionCmd)
+
+	connectionCmd.Flags().Bool(connectionEphemeralFlag, false,
+		"This flag is available to both server and client. "+
+			"This flag operates as a switch determining the initialization path."+
+			"If present, the messenger will be initialized ephemerally. Without this flag, "+
+			"the messenger will be initialized as stateful.")
+	bindFlagHelper(connectionEphemeralFlag, connectionCmd)
+
+	rootCmd.AddCommand(connectionCmd)
+}
diff --git a/cmd/dumpRounds.go b/cmd/dumpRounds.go
index 401d894ad12dc1003798849d970c7b287c75425a..4aa2f7ee8e96ff40a4708ba74f6193e199c6844c 100644
--- a/cmd/dumpRounds.go
+++ b/cmd/dumpRounds.go
@@ -11,6 +11,7 @@ package cmd
 import (
 	"encoding/base64"
 	"fmt"
+	"github.com/spf13/viper"
 	"strconv"
 	"time"
 
@@ -32,7 +33,9 @@ var dumpRoundsCmd = &cobra.Command{
 		roundIDs := parseRoundIDs(args)
 
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 		err := client.StartNetworkFollower(5 * time.Second)
 		if err != nil {
 			jww.FATAL.Panicf("%+v", err)
diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go
index 9540c7cabbf448d87b1b099ad66b056d9d779bb7..b44bdbf50f3755e24375e0562d11694b6e65b5f2 100644
--- a/cmd/fileTransfer.go
+++ b/cmd/fileTransfer.go
@@ -36,7 +36,9 @@ var ftCmd = &cobra.Command{
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		// Print user's reception ID and save contact file
 		user := client.GetReceptionIdentity()
diff --git a/cmd/flags.go b/cmd/flags.go
index 32ce750fae4f6efe97a546b60b24f7633063a52e..5244b7a12b62ee1e1c7d5a718f45b2bbccfad005 100644
--- a/cmd/flags.go
+++ b/cmd/flags.go
@@ -100,6 +100,7 @@ const (
 	connectionServerTimeoutFlag = "serverTimeout"
 	connectionDisconnectFlag    = "disconnect"
 	connectionAuthenticatedFlag = "authenticated"
+	connectionEphemeralFlag     = "ephemeral"
 
 	///////////////// File Transfer subcommand flags //////////////////////////
 	fileSendFlag          = "sendFile"
diff --git a/cmd/group.go b/cmd/group.go
index 783eff474813b1f3bb3c69a3b2f3212c4d56b427..0595779059bae5297255cab14a74f573cd1b5247 100644
--- a/cmd/group.go
+++ b/cmd/group.go
@@ -35,7 +35,9 @@ var groupCmd = &cobra.Command{
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		// Print user's reception ID
 		user := client.GetReceptionIdentity()
diff --git a/cmd/init.go b/cmd/init.go
index 7854b816344b151caaa8853885b475f7c9cbc41c..d278a0f9b834b62ca68f9e1cdf249432328327ef 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -71,12 +71,10 @@ func init() {
 	rootCmd.AddCommand(initCmd)
 }
 
-// loadOrInitMessenger will build a new xxdk.E2e from existing storage
+// loadOrInitCmix will build a new xxdk.Cmix from existing storage
 // or from a new storage that it will create if none already exists
-func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string,
-	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
-	jww.INFO.Printf("Using normal sender")
-
+func loadOrInitCmix(password []byte, storeDir, regCode string,
+	cmixParams xxdk.CMIXParams) *xxdk.Cmix {
 	// create a new client if none exist
 	if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
 		// Initialize from scratch
@@ -97,6 +95,12 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
 		jww.FATAL.Panicf("%+v", err)
 	}
 
+	return net
+}
+
+// loadOrInitReceptionIdentity will build a new xxdk.ReceptionIdentity from existing storage
+// or from a new storage that it will create if none already exists
+func loadOrInitReceptionIdentity(forceLegacy bool, net *xxdk.Cmix) xxdk.ReceptionIdentity {
 	// Load or initialize xxdk.ReceptionIdentity storage
 	identity, err := xxdk.LoadReceptionIdentity(identityStorageKey, net)
 	if err != nil {
@@ -115,8 +119,34 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
 			jww.FATAL.Panicf("%+v", err)
 		}
 	}
+	return identity
+}
+
+// loadOrInitMessenger will build a new xxdk.E2e from existing storage
+// or from a new storage that it will create if none already exists
+func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
+	jww.INFO.Printf("Using normal sender")
+
+	net := loadOrInitCmix(password, storeDir, regCode, cmixParams)
+	identity := loadOrInitReceptionIdentity(forceLegacy, net)
+
+	messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
+	if err != nil {
+		jww.FATAL.Panicf("%+v", err)
+	}
+	return messenger
+}
+
+// loadOrInitEphemeral will build a new ephemeral xxdk.E2e.
+func loadOrInitEphemeral(forceLegacy bool, password []byte, storeDir, regCode string,
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
+	jww.INFO.Printf("Using ephemeral sender")
+
+	net := loadOrInitCmix(password, storeDir, regCode, cmixParams)
+	identity := loadOrInitReceptionIdentity(forceLegacy, net)
 
-	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
+	messenger, err := xxdk.LoginEphemeral(net, cbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
@@ -126,7 +156,7 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
 // loadOrInitVanity will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
-	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
 	jww.INFO.Printf("Using Vanity sender")
 
 	// create a new client if none exist
@@ -163,7 +193,7 @@ func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
 		}
 	}
 
-	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
diff --git a/cmd/precan.go b/cmd/precan.go
index 3c00f106a95ca0149de171c68581b3f4ae83f618..e6993d993fbe051ef0031b2994e414b02debffa3 100644
--- a/cmd/precan.go
+++ b/cmd/precan.go
@@ -24,7 +24,7 @@ import (
 // loadOrInitPrecan will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
-	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
 	jww.INFO.Printf("Using Precanned sender")
 
 	// create a new client if none exist
@@ -60,7 +60,7 @@ func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
 		}
 	}
 
-	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
diff --git a/cmd/proto.go b/cmd/proto.go
index 6ab109c5ad15dd5dbaf1497706c0b02507c0ae6f..e5677a55e113ab0be105b654ec026255566f9e0b 100644
--- a/cmd/proto.go
+++ b/cmd/proto.go
@@ -22,7 +22,7 @@ import (
 // loadOrInitProto will build a new xxdk.E2e from existing storage
 // or from a new storage that it will create if none already exists
 func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
-	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+	cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
 	jww.INFO.Printf("Using Proto sender")
 
 	// create a new client if none exist
@@ -70,7 +70,7 @@ func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
 		}
 	}
 
-	messenger, err := xxdk.Login(net, authCbs, identity, e2eParams)
+	messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
 	if err != nil {
 		jww.FATAL.Panicf("%+v", err)
 	}
diff --git a/cmd/root.go b/cmd/root.go
index 3456033a720c399337467a912de78f45283c951a..c5a83d0329e6cc623d0590bdac661c9d2539d16b 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -42,8 +42,6 @@ import (
 // Key used for storing xxdk.ReceptionIdentity objects
 const identityStorageKey = "identityStorageKey"
 
-var authCbs *authCallbacks
-
 // Execute adds all child commands to the root command and sets flags
 // appropriately.  This is called by main.main(). It only needs to
 // happen once to the rootCmd.
@@ -71,7 +69,9 @@ var rootCmd = &cobra.Command{
 
 		cmixParams, e2eParams := initParams()
 
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		jww.INFO.Printf("Client Initialized...")
 
@@ -420,7 +420,8 @@ func initParams() (xxdk.CMIXParams, xxdk.E2EParams) {
 }
 
 // initE2e returns a fully-formed xxdk.E2e object
-func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
+func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams,
+	callbacks *authCallbacks) *xxdk.E2e {
 	initLog(viper.GetUint("logLevel"), viper.GetString("log"))
 	jww.INFO.Printf(Version())
 
@@ -436,22 +437,18 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
 	forceLegacy := viper.GetBool(forceLegacyFlag)
 	jww.DEBUG.Printf("sessionDir: %v", storeDir)
 
-	// TODO: This probably shouldn't be initialized globally.
-	authCbs = makeAuthCallbacks(
-		viper.GetBool(unsafeChannelCreationFlag), e2eParams)
-
 	// Initialize the client of the proper type
 	var messenger *xxdk.E2e
 	if precanId != 0 {
-		messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams, callbacks)
 	} else if protoUserPath != "" {
-		messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams, callbacks)
 	} else if userIdPrefix != "" {
-		messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams)
+		messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams, callbacks)
 	} else if backupPath != "" {
-		messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams)
+		messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams, callbacks)
 	} else {
-		messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams)
+		messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams, callbacks)
 	}
 
 	// Handle protoUser output
diff --git a/cmd/single.go b/cmd/single.go
index d23a5be52475b2fc3e7119c965a9c304d9518c26..fb5cd10305bb878d2e28f5decf90c89c23f0a755 100644
--- a/cmd/single.go
+++ b/cmd/single.go
@@ -34,7 +34,9 @@ var singleCmd = &cobra.Command{
 	Run: func(cmd *cobra.Command, args []string) {
 
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		// Write user contact to file
 		user := client.GetReceptionIdentity()
diff --git a/cmd/ud.go b/cmd/ud.go
index 06707a6f52d224d3f661c6dc664dc7d3a2238b69..d7f79831d623aa883d0d18b5eca4d739ee5bb551 100644
--- a/cmd/ud.go
+++ b/cmd/ud.go
@@ -35,7 +35,9 @@ var udCmd = &cobra.Command{
 	Args:  cobra.NoArgs,
 	Run: func(cmd *cobra.Command, args []string) {
 		cmixParams, e2eParams := initParams()
-		client := initE2e(cmixParams, e2eParams)
+		authCbs := makeAuthCallbacks(
+			viper.GetBool("unsafe-channel-creation"), e2eParams)
+		client := initE2e(cmixParams, e2eParams, authCbs)
 
 		// get user and save contact to file
 		user := client.GetReceptionIdentity()
diff --git a/connect/authenticated.go b/connect/authenticated.go
index 11f0d2de9d92cb2b42e34dab9618b61d48d77328..7e16fd0f822c7aae8b758c978ac868f23ce8dfd1 100644
--- a/connect/authenticated.go
+++ b/connect/authenticated.go
@@ -71,8 +71,8 @@ func ConnectWithAuthentication(recipient contact.Contact, messenger *xxdk.E2e,
 	if err != nil {
 		return nil, err
 	}
-	return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, privKey,
-		messenger.GetRng(), messenger.GetCmix(), p)
+	return connectWithAuthentication(conn, timeStart, recipient,
+		identity.Salt, privKey, messenger.GetRng(), messenger.GetCmix(), p)
 }
 
 // connectWithAuthentication builds and sends an IdentityAuthentication to
@@ -175,7 +175,7 @@ func connectWithAuthentication(conn Connection, timeStart time.Time,
 // authenticate themselves. An established AuthenticatedConnection will
 // be passed via the callback.
 func StartAuthenticatedServer(identity xxdk.ReceptionIdentity,
-	cb AuthenticatedCallback, net *xxdk.Cmix, p xxdk.E2EParams,
+	authCb AuthenticatedCallback, net *xxdk.Cmix, p xxdk.E2EParams,
 	clParams ConnectionListParams) (
 	*ConnectionServer, error) {
 
@@ -187,7 +187,7 @@ func StartAuthenticatedServer(identity xxdk.ReceptionIdentity,
 		// be passed along via the AuthenticatedCallback
 		_, err := connection.RegisterListener(
 			catalog.ConnectionAuthenticationRequest,
-			buildAuthConfirmationHandler(cb, connection))
+			buildAuthConfirmationHandler(authCb, connection))
 		if err != nil {
 			jww.ERROR.Printf(
 				"Failed to register listener on connection with %s: %+v",
diff --git a/connect/client.go b/connect/client.go
index a916bdca352da2e7aee21d0b2549702acfeebfdf..809c5da3017ba707dd9037ce624ae1045f3f252f 100644
--- a/connect/client.go
+++ b/connect/client.go
@@ -21,21 +21,11 @@ func buildClientAuthRequest(newPartner partner.Manager,
 	rng *fastRNG.StreamGenerator, rsaPrivKey *rsa.PrivateKey,
 	salt []byte) ([]byte, error) {
 
-	// The connection fingerprint (hashed) will be used as a nonce
+	// Create signature
 	connectionFp := newPartner.ConnectionFingerprint().Bytes()
-	opts := rsa.NewDefaultOptions()
-	h := opts.Hash.New()
-	h.Write(connectionFp)
-	nonce := h.Sum(nil)
-
-	// Sign the connection fingerprint
 	stream := rng.GetStream()
 	defer stream.Close()
-	signature, err := rsa.Sign(stream, rsaPrivKey,
-		opts.Hash, nonce, opts)
-	if err != nil {
-		return nil, errors.Errorf("failed to sign nonce: %+v", err)
-	}
+	signature, err := sign(stream, rsaPrivKey, connectionFp)
 
 	// Construct message
 	pemEncodedRsaPubKey := rsa.CreatePublicKeyPem(rsaPrivKey.GetPublic())
@@ -44,11 +34,12 @@ func buildClientAuthRequest(newPartner partner.Manager,
 		RsaPubKey: pemEncodedRsaPubKey,
 		Salt:      salt,
 	}
+
+	// Marshal message
 	payload, err := proto.Marshal(iar)
 	if err != nil {
 		return nil, errors.Errorf("failed to marshal identity request "+
 			"message: %+v", err)
 	}
-
 	return payload, nil
 }
diff --git a/connect/crypto.go b/connect/crypto.go
new file mode 100644
index 0000000000000000000000000000000000000000..391aa1b2778dd936754182f78f57e5fa80854f39
--- /dev/null
+++ b/connect/crypto.go
@@ -0,0 +1,56 @@
+package connect
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/crypto/xx"
+	"gitlab.com/xx_network/primitives/id"
+	"io"
+)
+
+// Sign creates a signature authenticating an identity for a connection.
+func sign(rng io.Reader, rsaPrivKey *rsa.PrivateKey,
+	connectionFp []byte) ([]byte, error) {
+	// The connection fingerprint (hashed) will be used as a nonce
+	opts := rsa.NewDefaultOptions()
+	h := opts.Hash.New()
+	h.Write(connectionFp)
+	nonce := h.Sum(nil)
+
+	// Sign the connection fingerprint
+	return rsa.Sign(rng, rsaPrivKey,
+		opts.Hash, nonce, opts)
+
+}
+
+// Verify takes a signature for an authentication attempt
+// and verifies the information.
+func verify(partnerId *id.ID, partnerPubKey *rsa.PublicKey,
+	signature, connectionFp, salt []byte) error {
+
+	// Verify the partner's known ID against the information passed
+	// along the wire
+	partnerWireId, err := xx.NewID(partnerPubKey, salt, id.User)
+	if err != nil {
+		return err
+	}
+
+	if !partnerId.Cmp(partnerWireId) {
+		return errors.New("Failed confirm partner's ID over the wire")
+	}
+
+	// Hash the connection fingerprint
+	opts := rsa.NewDefaultOptions()
+	h := opts.Hash.New()
+	h.Write(connectionFp)
+	nonce := h.Sum(nil)
+
+	// Verify the signature
+	err = rsa.Verify(partnerPubKey, opts.Hash, nonce, signature, opts)
+	if err != nil {
+		return err
+	}
+
+	return nil
+
+}
diff --git a/connect/crypto_test.go b/connect/crypto_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..633e47a700e98034df89df6f51192a4c6117a790
--- /dev/null
+++ b/connect/crypto_test.go
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 xx network SEZC                                                       //
+//                                                                                        //
+// Use of this source code is governed by a license that can be found in the LICENSE file //
+////////////////////////////////////////////////////////////////////////////////////////////
+
+package connect
+
+import (
+	"bytes"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/crypto/xx"
+	"gitlab.com/xx_network/primitives/id"
+	"testing"
+)
+
+var expectedSig = []byte{139, 67, 63, 6, 185, 76, 60, 217, 163, 84, 251, 231,
+	197, 6, 33, 179, 53, 66, 88, 75, 105, 191, 16, 71, 126, 4, 16, 11, 41,
+	237, 34, 245, 242, 97, 44, 58, 154, 120, 58, 235, 240, 140, 223, 80, 232,
+	51, 94, 247, 226, 217, 79, 194, 215, 46, 187, 157, 55, 167, 180, 179, 12,
+	228, 205, 98, 132, 200, 146, 180, 142, 0, 230, 79, 0, 129, 39, 205, 67,
+	79, 252, 62, 187, 125, 130, 232, 125, 41, 99, 63, 106, 79, 234, 131, 109,
+	103, 189, 149, 45, 169, 227, 85, 164, 121, 103, 254, 19, 224, 236, 28, 187,
+	38, 240, 132, 192, 227, 145, 140, 56, 196, 91, 48, 228, 242, 123, 142, 123,
+	221, 159, 160}
+
+type CountingReader struct {
+	count uint8
+}
+
+// Read just counts until 254 then starts over again
+func (c *CountingReader) Read(b []byte) (int, error) {
+	for i := 0; i < len(b); i++ {
+		c.count = (c.count + 1) % 255
+		b[i] = c.count
+	}
+	return len(b), nil
+}
+
+func TestSignVerify_Consistency(t *testing.T) {
+	// use insecure seeded rng to reproduce key
+	notRand := &CountingReader{count: uint8(0)}
+
+	privKey, err := rsa.GenerateKey(notRand, 1024)
+	if err != nil {
+		t.Fatalf("SignVerify error: "+
+			"Could not generate key: %v", err.Error())
+	}
+
+	connFp := []byte("connFp")
+
+	signature, err := sign(notRand, privKey, connFp)
+	if err != nil {
+		t.Logf("Sign error: %v", err)
+	}
+
+	salt := make([]byte, 32)
+	copy(salt, "salt")
+
+	partnerId, err := xx.NewID(privKey.GetPublic(), salt, id.User)
+	if err != nil {
+		t.Fatalf("NewId error: %v", err)
+	}
+
+	err = verify(partnerId, privKey.GetPublic(), signature, connFp, salt)
+	if err != nil {
+		t.Fatalf("Verify error: %v", err)
+	}
+
+	if !bytes.Equal(signature, expectedSig) {
+		t.Errorf("Consistency test failed."+
+			"\nExpected: %v"+
+			"\nReceived: %v", expectedSig, signature)
+	}
+}
diff --git a/connect/server.go b/connect/server.go
index 78e22eed6fedfbe965ac89dcd8cbdf15579d4a26..b9f77b28b05b5f9af692fce2f532808a82b02e99 100644
--- a/connect/server.go
+++ b/connect/server.go
@@ -9,11 +9,9 @@ package connect
 
 import (
 	"github.com/golang/protobuf/proto"
-	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/e2e/receive"
 	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/crypto/xx"
 	"gitlab.com/xx_network/primitives/id"
 )
 
@@ -41,7 +39,7 @@ type serverListener struct {
 // buildAuthConfirmationHandler returns a serverListener object.
 // This will handle incoming identity authentication confirmations
 // via the serverListener.Hear method. A successful AuthenticatedConnection
-// will be passed along via the serverListener.connectionCallback
+// will be passed along via the serverListener.connectionCallback.
 func buildAuthConfirmationHandler(cb AuthenticatedCallback,
 	connection Connection) server {
 	return &serverListener{
@@ -62,41 +60,19 @@ func (a serverListener) Hear(item receive.Message) {
 		return
 	}
 
-	// Process the PEM encoded public key to an rsa.PublicKey object
-	partnerPubKey, err := rsa.LoadPublicKeyFromPem(iar.RsaPubKey)
-	if err != nil {
-		a.handleAuthConfirmationErr(err, item.Sender)
-		return
-	}
-
-	// Get the new partner
+	// Get the new partner's connection fingerprint
 	newPartner := a.conn.GetPartner()
+	connectionFp := newPartner.ConnectionFingerprint().Bytes()
 
-	// Verify the partner's known ID against the information passed
-	// along the wire
-	partnerWireId, err := xx.NewID(partnerPubKey, iar.Salt, id.User)
+	// Process the PEM encoded public key to an rsa.PublicKey object
+	partnerPubKey, err := rsa.LoadPublicKeyFromPem(iar.RsaPubKey)
 	if err != nil {
 		a.handleAuthConfirmationErr(err, item.Sender)
-		return
 	}
 
-	if !newPartner.PartnerId().Cmp(partnerWireId) {
-		err = errors.New("Failed confirm partner's ID over the wire")
-		a.handleAuthConfirmationErr(err, item.Sender)
-		return
-	}
-
-	// The connection fingerprint (hashed) will be used as a nonce
-	connectionFp := newPartner.ConnectionFingerprint().Bytes()
-
-	// Hash the connection fingerprint
-	opts := rsa.NewDefaultOptions()
-	h := opts.Hash.New()
-	h.Write(connectionFp)
-	nonce := h.Sum(nil)
-
-	// Verify the signature
-	err = rsa.Verify(partnerPubKey, opts.Hash, nonce, iar.Signature, opts)
+	// Verify the signature within the message
+	err = verify(newPartner.PartnerId(), partnerPubKey,
+		iar.Signature, connectionFp, iar.Salt)
 	if err != nil {
 		a.handleAuthConfirmationErr(err, item.Sender)
 		return