diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go
index 7c53e2389b5fd1526c02a928e1c8acd9e28b4df5..8d921698d0687bd93e32ef1ee9ed2f46d68fce57 100644
--- a/api/authenticatedChannel.go
+++ b/api/authenticatedChannel.go
@@ -1,12 +1,15 @@
 package api
 
-import jww "github.com/spf13/jwalterweatherman"
+import (
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/interfaces/contact"
+)
 
 // CreateAuthenticatedChannel creates a 1-way authenticated channel
 // so this user can send messages to the desired recipient Contact.
 // To receive confirmation from the remote user, clients must
 // register a listener to do that.
-func (c *Client) CreateAuthenticatedChannel(recipient Contact,
+func (c *Client) CreateAuthenticatedChannel(recipient contact.Contact,
 	payload []byte) error {
 	jww.INFO.Printf("CreateAuthenticatedChannel(%v, %v)",
 		recipient, payload)
@@ -15,14 +18,14 @@ func (c *Client) CreateAuthenticatedChannel(recipient Contact,
 
 // RegisterAuthConfirmationCb registers a callback for channel
 // authentication confirmation events.
-func (c *Client) RegisterAuthConfirmationCb(cb func(contact Contact,
+func (c *Client) RegisterAuthConfirmationCb(cb func(contact contact.Contact,
 	payload []byte)) {
 	jww.INFO.Printf("RegisterAuthConfirmationCb(...)")
 }
 
 // RegisterAuthRequestCb registers a callback for channel
 // authentication request events.
-func (c *Client) RegisterAuthRequestCb(cb func(contact Contact,
+func (c *Client) RegisterAuthRequestCb(cb func(contact contact.Contact,
 	payload []byte)) {
 	jww.INFO.Printf("RegisterAuthRequestCb(...)")
 }
diff --git a/api/client.go b/api/client.go
index b4748878c2150d67a60e792d7b94acd2650cfc5a..a5a132cc121a0b2009a1c81feb9446777767d32b 100644
--- a/api/client.go
+++ b/api/client.go
@@ -11,6 +11,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces"
 	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/client/interfaces/user"
 	"gitlab.com/elixxir/client/keyExchange"
 	"gitlab.com/elixxir/client/network"
 	"gitlab.com/elixxir/client/permissioning"
@@ -70,9 +71,8 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
 
 	// Create Storage
 	passwordStr := string(password)
-	storageSess, err := storage.New(storageDir, passwordStr,
-		protoUser.UID, protoUser.Salt, protoUser.RSAKey, protoUser.IsPrecanned,
-		protoUser.CMixKey, protoUser.E2EKey, cmixGrp, e2eGrp, rngStreamGen)
+	storageSess, err := storage.New(storageDir, passwordStr, protoUser,
+		cmixGrp, e2eGrp, rngStreamGen)
 	if err != nil {
 		return nil, err
 	}
@@ -115,9 +115,8 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [
 
 	// Create Storage
 	passwordStr := string(password)
-	storageSess, err := storage.New(storageDir, passwordStr,
-		protoUser.UID, protoUser.Salt, protoUser.RSAKey, protoUser.IsPrecanned,
-		protoUser.CMixKey, protoUser.E2EKey, cmixGrp, e2eGrp, rngStreamGen)
+	storageSess, err := storage.New(storageDir, passwordStr, protoUser,
+		cmixGrp, e2eGrp, rngStreamGen)
 	if err != nil {
 		return nil, err
 	}
@@ -223,6 +222,8 @@ func loadClient(session *storage.Session, rngStreamGen *fastRNG.StreamGenerator)
 // state and stopping those threads.
 // Call this when returning from sleep and close when going back to
 // sleep.
+// These threads may become a significant drain on battery when offline, ensure
+// they are stopped if there is no internet access
 // Threads Started:
 //   - Network Follower (/network/follow.go)
 //   	tracks the network events and hands them off to workers for handling
@@ -291,27 +292,43 @@ func (c *Client) StopNetworkFollower(timeout time.Duration) error {
 	return nil
 }
 
-//gets the state of the network follower
+// Gets the state of the network follower. Returns:
+// Stopped 	- 0
+// Starting - 1000
+// Running	- 2000
+// Stopping	- 3000
 func (c *Client) NetworkFollowerStatus() Status {
+	jww.INFO.Printf("NetworkFollowerStatus()")
 	return c.status.get()
 }
 
-// Returns the switchboard for Registration
-func (c *Client) GetSwitchboard() interfaces.Switchboard {
-	return c.switchboard
-}
-
 // Returns the health tracker for registration and polling
 func (c *Client) GetHealth() interfaces.HealthTracker {
+	jww.INFO.Printf("GetHealth()")
 	return c.network.GetHealthTracker()
 }
 
 // RegisterRoundEventsCb registers a callback for round
 // events.
 func (c *Client) GetRoundEvents() interfaces.RoundEvents {
+	jww.INFO.Printf("GetRoundEvents()")
 	return c.network.GetInstance().GetRoundEvents()
 }
 
+
+// Returns the switchboard for Registration
+func (c *Client) GetSwitchboard() interfaces.Switchboard {
+	jww.INFO.Printf("GetSwitchboard()")
+	return c.switchboard
+}
+
+// GetUser returns the current user Identity for this client. This
+// can be serialized into a byte stream for out-of-band sharing.
+func (c *Client) GetUser() user.User {
+	jww.INFO.Printf("GetUser()")
+	return c.storage.GetUser()
+}
+
 // ----- Utility Functions -----
 // parseNDF parses the initial ndf string for the client. do not check the
 // signature, it is deprecated.
diff --git a/api/contact.go b/api/contact.go
deleted file mode 100644
index 151245d5f2c350505872957d756e9148586f9b19..0000000000000000000000000000000000000000
--- a/api/contact.go
+++ /dev/null
@@ -1,78 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2019 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
-package api
-
-import jww "github.com/spf13/jwalterweatherman"
-
-import (
-	"gitlab.com/xx_network/crypto/signature/rsa"
-	"gitlab.com/xx_network/primitives/id"
-)
-
-// GetUser returns the current user Identity for this client. This
-// can be serialized into a byte stream for out-of-band sharing.
-func (c *Client) GetUser() (Contact, error) {
-	jww.INFO.Printf("GetUser()")
-	return Contact{}, nil
-}
-
-// MakeContact creates a contact from a byte stream (i.e., unmarshal's a
-// Contact object), allowing out-of-band import of identities.
-func (c *Client) MakeContact(contactBytes []byte) (Contact, error) {
-	jww.INFO.Printf("MakeContact(%s)", contactBytes)
-	return Contact{}, nil
-}
-
-// GetContact returns a Contact object for the given user id, or
-// an error
-func (c *Client) GetContact(uid []byte) (Contact, error) {
-	jww.INFO.Printf("GetContact(%s)", uid)
-	return Contact{}, nil
-}
-
-
-// Contact implements the Contact interface defined in bindings/interfaces.go,
-type Contact struct {
-	ID            id.ID
-	PubKey        rsa.PublicKey
-	Salt          []byte
-	Authenticated bool
-	Confirmed     bool
-}
-
-// GetID returns the user ID for this user.
-func (c Contact) GetID() []byte {
-	return c.ID.Bytes()
-}
-
-// GetPublicKey returns the publickey bytes for this user.
-func (c Contact) GetPublicKey() []byte {
-	return rsa.CreatePublicKeyPem(&c.PubKey)
-}
-
-// GetSalt returns the salt used to initiate an authenticated channel
-func (c Contact) GetSalt() []byte {
-	return c.Salt
-}
-
-// IsAuthenticated returns true if an authenticated channel exists for
-// this user so we can begin to send messages.
-func (c Contact) IsAuthenticated() bool {
-	return c.Authenticated
-}
-
-// IsConfirmed returns true if the user has confirmed the authenticated
-// channel on their end.
-func (c Contact) IsConfirmed() bool {
-	return c.Confirmed
-}
-
-// Marshal creates a serialized representation of a contact for
-// out-of-band contact exchange.
-func (c Contact) Marshal() ([]byte, error) {
-	return nil, nil
-}
diff --git a/api/user.go b/api/user.go
index 7151a88437b2ad1006459733bb79a65c31bfca81..da54da2aaafefa528ae01cdb0ae80579897a906d 100644
--- a/api/user.go
+++ b/api/user.go
@@ -1,37 +1,23 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2019 Privategrity Corporation                                   /
-//                                                                             /
-// All rights reserved.                                                        /
-////////////////////////////////////////////////////////////////////////////////
-
 package api
 
 import (
 	"encoding/binary"
-	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/interfaces/user"
 	"gitlab.com/elixxir/crypto/csprng"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/xx"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/id"
+	jww "github.com/spf13/jwalterweatherman"
 )
 
-type user struct {
-	UID         *id.ID
-	Salt        []byte
-	RSAKey      *rsa.PrivateKey
-	CMixKey     *cyclic.Int
-	E2EKey      *cyclic.Int
-	IsPrecanned bool
-}
-
 const (
 	// SaltSize size of user salts
 	SaltSize = 32
 )
 
 // createNewUser generates an identity for cMix
-func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user {
+func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user.User {
 	// RSA Keygen (4096 bit defaults)
 	rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen)
 	if err != nil {
@@ -70,19 +56,19 @@ func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user {
 		jww.FATAL.Panicf(err.Error())
 	}
 
-	return user{
-		UID:         userID,
-		Salt:        salt,
-		RSAKey:      rsaKey,
-		CMixKey:     cmix.NewIntFromBytes(cMixKeyBytes),
-		E2EKey:      e2e.NewIntFromBytes(e2eKeyBytes),
-		IsPrecanned: false,
+	return user.User{
+		ID:               userID.DeepCopy(),
+		Salt:             salt,
+		RSA:              rsaKey,
+		Precanned:        false,
+		CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes),
+		E2eDhPrivateKey:  cmix.NewIntFromBytes(e2eKeyBytes),
 	}
 }
 
 // TODO: Add precanned user code structures here.
 // creates a precanned user
-func createPrecannedUser(precannedID uint, rng csprng.Source, cmix, e2e *cyclic.Group) user {
+func createPrecannedUser(precannedID uint, rng csprng.Source, cmix, e2e *cyclic.Group) user.User {
 	// DH Keygen
 	// FIXME: Why 256 bits? -- this is spec but not explained, it has
 	// to do with optimizing operations on one side and still preserves
@@ -99,12 +85,10 @@ func createPrecannedUser(precannedID uint, rng csprng.Source, cmix, e2e *cyclic.
 	binary.BigEndian.PutUint64(userID[:], uint64(precannedID))
 	userID.SetType(id.User)
 
-	return user{
-		UID:         &userID,
-		Salt:        salt,
-		RSAKey:      &rsa.PrivateKey{},
-		CMixKey:     cmix.NewInt(1),
-		E2EKey:      e2e.NewIntFromBytes(e2eKeyBytes),
-		IsPrecanned: true,
+	return user.User{
+		ID:              userID.DeepCopy(),
+		Salt:            salt,
+		Precanned:       false,
+		E2eDhPrivateKey: cmix.NewIntFromBytes(e2eKeyBytes),
 	}
-}
\ No newline at end of file
+}
diff --git a/api/userDiscovery.go b/api/userDiscovery.go
index 3da6d21fd9aa3f7d59ff2154c9a901cdff2e86a2..680ed4facb5c14e091b963daf1617fe2c8e904bd 100644
--- a/api/userDiscovery.go
+++ b/api/userDiscovery.go
@@ -1,6 +1,9 @@
 package api
 
-import jww "github.com/spf13/jwalterweatherman"
+import (
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/interfaces/contact"
+)
 
 // Returns true if the cryptographic identity has been registered with
 // the CMIX user discovery agent.
@@ -48,7 +51,7 @@ func (c *Client) ConfirmRegistration(token, code []byte) error {
 // Search accepts a "separator" separated list of search elements with
 // an associated list of searchTypes. It returns a ContactList which
 // allows you to iterate over the found contact objects.
-func (c *Client) Search(data, separator string, searchTypes []byte) []Contact {
+func (c *Client) Search(data, separator string, searchTypes []byte) []contact.Contact {
 	jww.INFO.Printf("Search(%s, %s, %s)", data, separator, searchTypes)
 	return nil
 }
@@ -56,14 +59,14 @@ func (c *Client) Search(data, separator string, searchTypes []byte) []Contact {
 // SearchWithHandler is a non-blocking search that also registers
 // a callback interface for user disovery events.
 func (c *Client) SearchWithCallback(data, separator string, searchTypes []byte,
-	cb func(results []Contact)) {
-	resultCh := make(chan []Contact, 1)
-	go func(out chan []Contact, data, separator string, srchTypes []byte) {
+	cb func(results []contact.Contact)) {
+	resultCh := make(chan []contact.Contact, 1)
+	go func(out chan []contact.Contact, data, separator string, srchTypes []byte) {
 		out <- c.Search(data, separator, srchTypes)
 		close(out)
 	}(resultCh, data, separator, searchTypes)
 
-	go func(in chan []Contact, cb func(results []Contact)) {
+	go func(in chan []contact.Contact, cb func(results []contact.Contact)) {
 		select {
 		case contacts := <-in:
 			cb(contacts)
diff --git a/bindings/api.go b/bindings/client.go
similarity index 87%
rename from bindings/api.go
rename to bindings/client.go
index 3195423f109913a399747e46fc2ba985dc4fc461..679c4acd58f7cdb117ba120a6fd3510ee13693d7 100644
--- a/bindings/api.go
+++ b/bindings/client.go
@@ -8,15 +8,16 @@ package bindings
 
 import (
 	"gitlab.com/elixxir/client/api"
+	"time"
 )
 
 // BindingsClient wraps the api.Client, implementing additional functions
 // to support the gomobile Client interface
 type BindingsClient struct {
-	api.Client
+	api api.Client
 }
 
-// NewClient connects and registers to the network using a json encoded
+/*// NewClient connects and registers to the network using a json encoded
 // network information string and then creates a new client at the specified
 // storageDir using the specified password. This function will fail
 // when:
@@ -58,7 +59,48 @@ func LoadClient(storageDir string, password []byte) (Client, error) {
 	}
 	bindingsClient := &BindingsClient{*client}
 	return bindingsClient, nil
+}*/
+
+func (b *BindingsClient) StartNetworkFollower() error {
+	return b.api.StartNetworkFollower()
+}
+
+func (b *BindingsClient) StopNetworkFollower(timeoutMS int) error {
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	return b.api.StopNetworkFollower(timeout)
+}
+
+func (b *BindingsClient) NetworkFollowerStatus() int {
+	return int(b.api.NetworkFollowerStatus())
+}
+
+func (b *BindingsClient) IsNetworkHealthy() bool {
+	return b.api.GetHealth().IsHealthy()
 }
+
+func (b *BindingsClient) RegisterNetworkHealthCB(cb func(bool)) {
+	b.api.GetHealth().AddFunc(cb)
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 // RegisterListener records and installs a listener for messages
 // matching specific uid, msgType, and/or username
diff --git a/bindings/interfaces.go b/bindings/interfaces.go
index a4fd23c45cff5af5f4d3597afd8f233828e2faeb..a9d19c181381e767652bb20605152b96d934cdd7 100644
--- a/bindings/interfaces.go
+++ b/bindings/interfaces.go
@@ -7,7 +7,7 @@
 package bindings
 
 import (
-	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/interfaces"
 	"gitlab.com/xx_network/primitives/id"
 )
 
@@ -15,7 +15,41 @@ import (
 // functionality defined here. A Client handles all network connectivity, key
 // generation, and storage for a given cryptographic identity on the cmix
 // network.
+// These threads may become a significant drain on battery when offline, ensure
+// they are stopped if there is no internet access
 type Client interface {
+	// ----- Network -----
+	// StartNetworkFollower kicks off the tracking of the network. It starts
+	// long running network client threads and returns an object for checking
+	// state and stopping those threads.
+	// Call this when returning from sleep and close when going back to
+	// sleep.
+	StartNetworkFollower() error
+
+	// StopNetworkFollower stops the network follower if it is running.
+	// It returns errors if the Follower is in the wrong status to stop or if it
+	// fails to stop it.
+	// if the network follower is running and this fails, the client object will
+	// most likely be in an unrecoverable state and need to be trashed.
+	StopNetworkFollower(timeoutMS int) error
+
+	// NetworkFollowerStatus gets the state of the network follower.
+	// Returns:
+	// 	Stopped 	- 0
+	// 	Starting	- 1000
+	// 	Running		- 2000
+	// 	Stopping	- 3000
+	NetworkFollowerStatus() int
+
+	// Returns true if the following of the network is in a state where messages
+	// can be sent, false otherwise
+	IsNetworkHealthy() bool
+
+	// Registers a callback which gets triggered every time network health
+	// changes
+	RegisterNetworkHealthCB(func(bool))
+
+	RegisterRoundEventCallback(rid int, hdlr RoundEventHandler, )
 
 	// ----- Reception -----
 
@@ -85,13 +119,7 @@ type Client interface {
 
 	// GetUser returns the current user Identity for this client. This
 	// can be serialized into a byte stream for out-of-band sharing.
-	GetUser() (api.Contact, error)
-	// MakeContact creates a contact from a byte stream (i.e., unmarshal's a
-	// Contact object), allowing out-of-band import of identities.
-	MakeContact(contactBytes []byte) (api.Contact, error)
-	// GetContact returns a Contact object for the given user id, or
-	// an error
-	GetContact(uid []byte) (api.Contact, error)
+	GetUser() (interfaces.Contact, error)
 
 	// ----- User Discovery -----
 
@@ -110,22 +138,16 @@ type Client interface {
 	// so this user can send messages to the desired recipient Contact.
 	// To receive confirmation from the remote user, clients must
 	// register a listener to do that.
-	CreateAuthenticatedChannel(recipient api.Contact, payload []byte) error
+	CreateAuthenticatedChannel(recipient interfaces.Contact, payload []byte) error
 	// RegierAuthEventsHandler registers a callback interface for channel
 	// authentication events.
 	RegisterAuthEventsHandler(hdlr AuthEventHandler)
 
 	// ----- Network -----
 
-	// StartNetworkRunner kicks off the longrunning network client threads
-	// and returns an object for checking state and stopping those threads.
-	// Call this when returning from sleep and close when going back to
-	// sleep.
-	StartNetworkFollower() error
-
 	// RegisterRoundEventsHandler registers a callback interface for round
 	// events.
-	RegisterRoundEventsHandler(hdlr RoundEventHandler)
+	RegisterRoundEventsHandler()
 }
 
 // ContactList contains a list of contacts
@@ -133,7 +155,7 @@ type ContactList interface {
 	// GetLen returns the number of contacts in the list
 	GetLen() int
 	// GetContact returns the contact at index i
-	GetContact(i int) api.Contact
+	GetContact(i int) interfaces.Contact
 }
 
 // ----- Callback interfaces -----
@@ -154,13 +176,13 @@ type AuthEventHandler interface {
 	// the client has called CreateAuthenticatedChannel for
 	// the provided contact. Payload is typically empty but
 	// may include a small introductory message.
-	HandleConfirmation(contact api.Contact, payload []byte)
+	HandleConfirmation(contact interfaces.Contact, payload []byte)
 	// HandleRequest handles AuthEvents received before
 	// the client has called CreateAuthenticatedChannel for
 	// the provided contact. It should prompt the user to accept
 	// the channel creation "request" and, if approved,
 	// call CreateAuthenticatedChannel for this Contact.
-	HandleRequest(contact api.Contact, payload []byte)
+	HandleRequest(contact interfaces.Contact, payload []byte)
 }
 
 // RoundList contains a list of contacts
@@ -171,18 +193,10 @@ type RoundList interface {
 	GetRoundID(i int) int
 }
 
-// RoundEvent contains event information for a given round.
-// TODO: This is a half-baked interface and will be filled out later.
-type RoundEvent interface {
-	// GetID returns the round ID for this round.
-	GetID() int
-	// GetStatus returns the status of this round.
-	GetStatus() int
-}
 
 // RoundEventHandler handles round events happening on the cMix network.
 type RoundEventHandler interface {
-	HandleEvent(re RoundEvent)
+	HandleEvent(id int, state byte)
 }
 
 // UserDiscoveryHandler handles search results against the user discovery agent.
@@ -213,4 +227,4 @@ type Message interface {
 	GetTimestamp() int64
 	// Returns the message's timestamp in ns since unix epoc
 	GetTimestampNano() int64
-}
+}
\ No newline at end of file
diff --git a/cmd/root.go b/cmd/root.go
index 480077b6289e8b88c8bd6d2f48d58a33f1d1a049..cd7cdd197415b7a8bfd641d7cec766a86ca83119 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -201,11 +201,8 @@ var rootCmd = &cobra.Command{
 			}
 		}
 
-		user, err := client.GetUser()
-		if err != nil {
-			jww.FATAL.Panicf("%+v", err)
-		}
-		jww.INFO.Printf("%v", user.ID)
+		user := client.GetUser()
+		jww.INFO.Printf("%s", user.ID)
 
 	},
 }
diff --git a/go.sum b/go.sum
index cc835da946f25c491687e78561d33e5a867c7c34..76966418b77c1e86585f62d3aaebb816ade88081 100644
--- a/go.sum
+++ b/go.sum
@@ -33,7 +33,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -194,7 +193,6 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -215,12 +213,6 @@ github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/cobra v0.0.4/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -229,9 +221,6 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I=
-github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
-github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
 github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
@@ -257,8 +246,6 @@ github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN
 github.com/zeebo/blake3 v0.0.4 h1:vtZ4X8B2lKXZFg2Xyg6Wo36mvmnJvc2VQYTtA4RDCkI=
 github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny2i34=
 github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E=
-gitlab.com/elixxir/client v1.5.0/go.mod h1:/uVTzYDhKaGgN8LGGh1sSsxbh+BrpVi1X8VToAT3DfA=
-gitlab.com/elixxir/comms v0.0.0-20200707210150-b8ebd0951d23/go.mod h1:OsWMZ1O/R9fOkm+PoHnR3rkXfFtipGoPs73FuKuurHY=
 gitlab.com/elixxir/comms v0.0.0-20200810165153-3039323b5656 h1:A5S3E7EPL95s3+PGhgAiwnMaa7VcWj8/RtBur3lxdOw=
 gitlab.com/elixxir/comms v0.0.0-20200810165153-3039323b5656/go.mod h1:EeS1z5wXKrnWOvR0dJlVNVv8OzuiGJz7fa6LyUeN6Q0=
 gitlab.com/elixxir/comms v0.0.0-20200813225502-e879259ca741 h1:yIjgre8xSDpnhJkDzTr1lgR7NC1bPWCk2Sgn8udiS2A=
@@ -285,23 +272,14 @@ gitlab.com/elixxir/comms v0.0.0-20200916212207-60e7bd5b0913 h1:p4TLPPaMysV//lOJU
 gitlab.com/elixxir/comms v0.0.0-20200916212207-60e7bd5b0913/go.mod h1:yBEsOZSPyJQJvDbtlQ5L8ydy1JRgVlRoNgMDy9koQcE=
 gitlab.com/elixxir/comms v0.0.0-20200917172539-929fc227eb0c h1:go7/RknV7646Ie+nmQXZAa/aJ5wZBn5bpAYRB+tPens=
 gitlab.com/elixxir/comms v0.0.0-20200917172539-929fc227eb0c/go.mod h1:yBEsOZSPyJQJvDbtlQ5L8ydy1JRgVlRoNgMDy9koQcE=
-gitlab.com/elixxir/comms v0.0.0-20200917221445-8a509560122a/go.mod h1:L2Va13j2AbQkpkveOQmNzrQD37uI5NKeBhYH+LWMOx0=
 gitlab.com/elixxir/comms v0.0.0-20200921200427-5955a0a798b9 h1:skzHNWCMh+T7Cn58/88Mikg2R8KnSWfzLV0w7SnerOs=
 gitlab.com/elixxir/comms v0.0.0-20200921200427-5955a0a798b9/go.mod h1:uRr8j6yTjCslxZxbRe6k4ixACu9gAeF61JZH36OFFa0=
 gitlab.com/elixxir/comms v0.0.0-20200922163657-3e723b7170f6 h1:dFgfdATZuiPybonCBh0s4HeLB8Qw3Zm9EoLDRh2Eaaw=
 gitlab.com/elixxir/comms v0.0.0-20200922163657-3e723b7170f6/go.mod h1:yBEsOZSPyJQJvDbtlQ5L8ydy1JRgVlRoNgMDy9koQcE=
 gitlab.com/elixxir/comms v0.0.0-20200924072138-2e2709483d89 h1:PQalM7pnCRzZRKvdzJ6Jwz6e8bPR9H4CURzAwqYnJPE=
 gitlab.com/elixxir/comms v0.0.0-20200924072138-2e2709483d89/go.mod h1:uRr8j6yTjCslxZxbRe6k4ixACu9gAeF61JZH36OFFa0=
-gitlab.com/elixxir/comms v0.0.0-20200924172854-724244a10032 h1:0RLZM1fBzp7IRrjoCQANQfXMBDr1Hmjbynme564zXG8=
-gitlab.com/elixxir/comms v0.0.0-20200924172854-724244a10032/go.mod h1:9+Jj7K8HOTgBjPuiP69VtTKTv7GvAK6bWlh4lgMAqrk=
-gitlab.com/elixxir/comms v0.0.0-20200924204623-c1ce13fac604 h1:EOvvtQDA/ZGHYH13xcI8WaSCuLeZaEZHGDo4qJvZOQQ=
-gitlab.com/elixxir/comms v0.0.0-20200924204623-c1ce13fac604/go.mod h1:3i4o6ie4LFC+EVN68l9tdt9JxJlAd3+pNNnKBFubKSg=
 gitlab.com/elixxir/comms v0.0.0-20200924210331-d7903c023fa6 h1:ctVsHyiabgRls3esApbBemDwmQ/a0CramEmZt9RCQb8=
 gitlab.com/elixxir/comms v0.0.0-20200924210331-d7903c023fa6/go.mod h1:9+Jj7K8HOTgBjPuiP69VtTKTv7GvAK6bWlh4lgMAqrk=
-gitlab.com/elixxir/comms v0.0.0-20200924225440-76e02f95fb92 h1:KwqVzHpqYg1l1/KG6uRqnl7HBgvrzuknMVCeEvRsbow=
-gitlab.com/elixxir/comms v0.0.0-20200924225440-76e02f95fb92/go.mod h1:3i4o6ie4LFC+EVN68l9tdt9JxJlAd3+pNNnKBFubKSg=
-gitlab.com/elixxir/crypto v0.0.0-20200707005343-97f868cbd930/go.mod h1:LHBAaEf48a0/AjU118rjoworH0LgXifhAqmNX3ZRvME=
-gitlab.com/elixxir/crypto v0.0.0-20200731174640-0503cf80524a/go.mod h1:LHBAaEf48a0/AjU118rjoworH0LgXifhAqmNX3ZRvME=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
 gitlab.com/elixxir/crypto v0.0.0-20200805174804-bdf909f2a16d/go.mod h1:cu6uNoANVLV0J6HyTL6KqVtVyh9SHU1RjJhytYlsbVQ=
@@ -343,8 +321,6 @@ gitlab.com/elixxir/ekv v0.1.1 h1:Em3rF8sv+tNbQGXbcpYzAS2blWRAP708JGhYlkN74Kg=
 gitlab.com/elixxir/ekv v0.1.1/go.mod h1:bXY0kgbV5BHYda4YY5/hiG5bjimGK+R3PYub5yM9C/s=
 gitlab.com/elixxir/ekv v0.1.3 h1:OE+LBMIhjGUMwc6hHJzYvEPNJQV7t1vMnJyIgxUMUo8=
 gitlab.com/elixxir/ekv v0.1.3/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
-gitlab.com/elixxir/primitives v0.0.0-20200706165052-9fe7a4fb99a3/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
-gitlab.com/elixxir/primitives v0.0.0-20200708185800-a06e961280e6/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
 gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8=
 gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
@@ -370,13 +346,8 @@ gitlab.com/xx_network/comms v0.0.0-20200910173932-bd179f5fee4f h1:ExTCqEoro7VuS1
 gitlab.com/xx_network/comms v0.0.0-20200910173932-bd179f5fee4f/go.mod h1:+jEkDQKoK51WLl2ZZuxfAZkz6YFbUQ+oZfH0dt2wIF0=
 gitlab.com/xx_network/comms v0.0.0-20200915154643-d533291041b7 h1:lPx1wpkjNpwLaZ0pyd7/iCcdITjT+eCMmb0HXCVoIkk=
 gitlab.com/xx_network/comms v0.0.0-20200915154643-d533291041b7/go.mod h1:+jEkDQKoK51WLl2ZZuxfAZkz6YFbUQ+oZfH0dt2wIF0=
-gitlab.com/xx_network/comms v0.0.0-20200916172635-6ab807c3c820/go.mod h1:J+GJ6fn71a4xnYVvbcrhtvWSOQIqqhaGcaej5xB3/JY=
 gitlab.com/xx_network/comms v0.0.0-20200924172734-1124191b69ee h1:dPRaW0OxcoBlWALd5H6VUYnL/ALvT7j14kWJNBi0K7A=
 gitlab.com/xx_network/comms v0.0.0-20200924172734-1124191b69ee/go.mod h1:jECvMkoYKZFooCudoZxxaf2bo1DzpWP0gCahXHdlqUM=
-gitlab.com/xx_network/comms v0.0.0-20200924192723-aa0577a6d899 h1:dGDcAnQm43ihDUaP82XyiwWzLnE+ejJBizycRgx2XCo=
-gitlab.com/xx_network/comms v0.0.0-20200924192723-aa0577a6d899/go.mod h1:wDPZABTOhqz+uFM75CzpGplQBRIsCQcS1EYXwker6nw=
-gitlab.com/xx_network/comms v0.0.0-20200924225518-0c867207b1e6 h1:8rNFHiwKJvcfN89FAmp4RyfjD/rknp4tNm9sI/Nos0g=
-gitlab.com/xx_network/comms v0.0.0-20200924225518-0c867207b1e6/go.mod h1:jECvMkoYKZFooCudoZxxaf2bo1DzpWP0gCahXHdlqUM=
 gitlab.com/xx_network/crypto v0.0.0-20200805231039-4aa0e350ed0a h1:BlfWGPokU6yU69O+PGGsgc5iA/P9gERbHzYUvjoYbgM=
 gitlab.com/xx_network/crypto v0.0.0-20200806202113-978fa1984bbf/go.mod h1:i0df/q6dDCBiscgD51fMoS2U2TBrm6LcyN822JmB5Tw=
 gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce h1:gypNBUl2guESEv4MDgH+miwYqR4jPoWM8dLt2Zs5gIs=
@@ -448,7 +419,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -528,7 +498,6 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
 google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200514193133-8feb7f20f2a2/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3 h1:JwLN1jVnmIsfE4HkDVe2AblFAbo0Z+4cjteDSOnv6oE=
 google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
diff --git a/interfaces/contact.go b/interfaces/contact.go
new file mode 100644
index 0000000000000000000000000000000000000000..d9890553979d9e8faefbe7fc9a8f74210f2ea229
--- /dev/null
+++ b/interfaces/contact.go
@@ -0,0 +1,15 @@
+package interfaces
+
+type Contact interface {
+	GetID() []byte
+	GetDHPublicKey() []byte
+	AddFact(Fact) Contact
+	NumFacts() int
+	GetFact(int) (Fact, error)
+	Marshal() ([]byte, error)
+}
+
+type Fact interface {
+	Get() string
+	GetType() int
+}
diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go
new file mode 100644
index 0000000000000000000000000000000000000000..145363b192185a8ab8dbaa69219040a0c9a16123
--- /dev/null
+++ b/interfaces/contact/contact.go
@@ -0,0 +1,71 @@
+package contact
+
+import (
+	"encoding/json"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/interfaces"
+	"gitlab.com/elixxir/client/interfaces/contact/fact"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/xx_network/primitives/id"
+)
+
+// Contact implements the Contact interface defined in interface/contact.go,
+// in go, the structure is meant to be edited directly, the functions are for
+// bindings compatibility
+type Contact struct {
+	ID       *id.ID
+	DhPubKey *cyclic.Int
+	Facts    []fact.Fact
+}
+
+// GetID returns the user ID for this user.
+func (c Contact) GetID() []byte {
+	return c.ID.Bytes()
+}
+
+// GetPublicKey returns the publickey bytes for this user.
+func (c Contact) GetDHPublicKey() []byte {
+	return c.DhPubKey.Bytes()
+}
+
+// Adds a fact to the contact. Because the contact is pass by value, this makes
+// a new copy with the fact
+func (c Contact) AddFact(f interfaces.Fact) interfaces.Contact {
+	fNew := fact.Fact{
+		Fact: f.Get(),
+		T:    fact.Type(f.GetType()),
+	}
+	c.Facts = append(c.Facts, fNew)
+	return c
+}
+
+func (c Contact) NumFacts() int {
+	return len(c.Facts)
+}
+
+func (c Contact) GetFact(i int) (interfaces.Fact, error) {
+	if i >= len(c.Facts) || i < 0 {
+		return nil, errors.Errorf("Cannot get a a fact at position %v, "+
+			"only %v facts", i, len(c.Facts))
+	}
+	return c.Facts[i], nil
+}
+
+func (c Contact) Marshal() ([]byte, error) {
+	return json.Marshal(&c)
+}
+
+func Unmarshal(b []byte) (Contact, error) {
+	c := Contact{}
+	err := json.Unmarshal(b, &c)
+	if err != nil {
+		return c, err
+	}
+	for i, fact := range c.Facts {
+		if !fact.T.IsValid() {
+			return Contact{}, errors.Errorf("Fact %v/%v has invalid "+
+				"type: %s", i, len(c.Facts), fact.T)
+		}
+	}
+	return c, nil
+}
diff --git a/interfaces/contact/fact/fact.go b/interfaces/contact/fact/fact.go
new file mode 100644
index 0000000000000000000000000000000000000000..9aa96742fcbcc28623939d37d6de088577a7e24f
--- /dev/null
+++ b/interfaces/contact/fact/fact.go
@@ -0,0 +1,51 @@
+package fact
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/interfaces"
+)
+
+type Fact struct {
+	Fact string
+	T    Type
+}
+
+func (f Fact) Get() string {
+	return f.Fact
+}
+
+func (f Fact) GetType() int {
+	return int(f.T)
+}
+
+func (f Fact) Copy() interfaces.Fact {
+	f2 := Fact{
+		Fact: f.Fact,
+		T:    f.T,
+	}
+	return &f2
+}
+
+// marshal is for transmission for UDB, not a part of the fact interface
+func (f Fact) Marshal() []byte {
+	serial := []byte(f.Fact)
+	b := make([]byte, len(serial)+1)
+	b[0] = byte(f.T)
+
+	copy(b[1:len(serial)-1], serial)
+	return b
+}
+
+func Unmarshal(b []byte) (Fact, error) {
+	t := Type(b[0])
+	if !t.IsValid() {
+		return Fact{}, errors.Errorf("Fact is not a valid type: %s", t)
+	}
+
+	f := string(b[1:])
+
+	return Fact{
+		Fact: f,
+		T:    t,
+	}, nil
+}
diff --git a/interfaces/contact/fact/type.go b/interfaces/contact/fact/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..cc0ff89334bf031db54139d57c006539f54e8bbd
--- /dev/null
+++ b/interfaces/contact/fact/type.go
@@ -0,0 +1,28 @@
+package fact
+
+import "fmt"
+
+type Type uint8
+
+const (
+	Username Type = 0
+	Email    Type = 1
+	Phone    Type = 2
+)
+
+func (t Type) String() string {
+	switch t {
+	case Username:
+		return "Username"
+	case Email:
+		return "Email"
+	case Phone:
+		return "Phone"
+	default:
+		return fmt.Sprintf("Unknown Fact Type: %d", t)
+	}
+}
+
+func (t Type) IsValid() bool {
+	return t == Username || t == Email || t == Phone
+}
diff --git a/interfaces/user.go b/interfaces/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..4819783a50f87b5374d1da89af8e980870249672
--- /dev/null
+++ b/interfaces/user.go
@@ -0,0 +1,14 @@
+package interfaces
+
+type User interface {
+	GetID() []byte
+	GetSalt() []byte
+	GetRSAPrivateKeyPem() []byte
+	GetRSAPublicKeyPem() []byte
+	IsPrecanned() bool
+	GetCmixDhPrivateKey() []byte
+	GetCmixDhPublicKey() []byte
+	GetE2EDhPrivateKey() []byte
+	GetE2EDhPublicKey() []byte
+	GetContact() Contact
+}
diff --git a/interfaces/user/user.go b/interfaces/user/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..d84f406b5ca3d7a70fd1b2ac0873728958cc5fef
--- /dev/null
+++ b/interfaces/user/user.go
@@ -0,0 +1,69 @@
+package user
+
+import (
+	"gitlab.com/elixxir/client/interfaces"
+	"gitlab.com/elixxir/client/interfaces/contact"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+)
+
+type User struct {
+	//General Identity
+	ID        *id.ID
+	Salt      []byte
+	RSA       *rsa.PrivateKey
+	Precanned bool
+
+	//cmix Identity
+	CmixDhPrivateKey *cyclic.Int
+	CmixDhPublicKey  *cyclic.Int
+
+	//e2e Identity
+	E2eDhPrivateKey *cyclic.Int
+	E2eDhPublicKey  *cyclic.Int
+}
+
+func (u User) GetID() []byte {
+	return u.ID.Marshal()
+}
+
+func (u User) GetSalt() []byte {
+	return u.Salt
+}
+
+func (u User) GetRSAPrivateKeyPem() []byte {
+	return rsa.CreatePrivateKeyPem(u.RSA)
+}
+
+func (u User) GetRSAPublicKeyPem() []byte {
+	return rsa.CreatePublicKeyPem(u.RSA.GetPublic())
+}
+
+func (u User) IsPrecanned() bool {
+	return u.Precanned
+}
+
+func (u User) GetCmixDhPrivateKey() []byte {
+	return u.CmixDhPrivateKey.Bytes()
+}
+
+func (u User) GetCmixDhPublicKey() []byte {
+	return u.CmixDhPublicKey.Bytes()
+}
+
+func (u User) GetE2EDhPrivateKey() []byte {
+	return u.E2eDhPrivateKey.Bytes()
+}
+
+func (u User) GetE2EDhPublicKey() []byte {
+	return u.E2eDhPublicKey.Bytes()
+}
+
+func (u User) GetContact() interfaces.Contact {
+	return contact.Contact{
+		ID:       u.ID.DeepCopy(),
+		DhPubKey: u.E2eDhPublicKey,
+		Facts:    nil,
+	}
+}
diff --git a/permissioning/permissioning.go b/permissioning/permissioning.go
index 3d28dca1b7da5cd75548b463e52f6e8127fe0b03..51d8803a97275e541b90a824dfc995c41cdf5336 100644
--- a/permissioning/permissioning.go
+++ b/permissioning/permissioning.go
@@ -22,9 +22,11 @@ func Init(comms *client.Comms, def *ndf.NetworkDefinition) (*Permissioning, erro
 
 	var err error
 	//add the permissioning host to comms
+	hParam := connect.GetDefaultHostParams()
+	hParam.AuthEnabled = false
+
 	perm.host, err = comms.AddHost(&id.Permissioning, def.Registration.Address,
-		[]byte(def.Registration.TlsCertificate),
-		connect.GetDefaultHostParams())
+		[]byte(def.Registration.TlsCertificate), hParam)
 
 	if err != nil {
 		return nil, errors.WithMessage(err, "failed to create permissioning")
diff --git a/stoppable/bindings.go b/stoppable/bindings.go
new file mode 100644
index 0000000000000000000000000000000000000000..73e879f557a5b91a3cbc96d88c7c28f0269d6131
--- /dev/null
+++ b/stoppable/bindings.go
@@ -0,0 +1,30 @@
+package stoppable
+
+import "time"
+
+type Bindings interface {
+	Close(timeoutMS int) error
+	IsRunning() bool
+	Name() string
+}
+
+func WrapForBindings(s Stoppable) Bindings {
+	return &bindingsStoppable{s: s}
+}
+
+type bindingsStoppable struct {
+	s Stoppable
+}
+
+func (bs *bindingsStoppable) Close(timeoutMS int) error {
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	return bs.s.Close(timeout)
+}
+
+func (bs *bindingsStoppable) IsRunning() bool {
+	return bs.s.IsRunning()
+}
+
+func (bs *bindingsStoppable) Name() string {
+	return bs.s.Name()
+}
diff --git a/storage/session.go b/storage/session.go
index 884b0e3e8ff81602aa8bbe475b904c74ce46bc1d..97f896e693b15b4e9449401c70790e972d6dc04b 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -28,6 +28,7 @@ import (
 	"gitlab.com/xx_network/primitives/ndf"
 	"sync"
 	"testing"
+	userInterface "gitlab.com/elixxir/client/interfaces/user"
 )
 
 // Number of rounds to store in the CheckedRound buffer
@@ -70,8 +71,8 @@ func initStore(baseDir, password string) (*Session, error) {
 }
 
 // Creates new UserData in the session
-func New(baseDir, password string, uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey,
-	isPrecanned bool, cmixDHPrivKey, e2eDHPrivKey *cyclic.Int, cmixGrp,
+
+func New(baseDir, password string, u userInterface.User, cmixGrp,
 	e2eGrp *cyclic.Group, rng *fastRNG.StreamGenerator) (*Session, error) {
 
 	s, err := initStore(baseDir, password)
@@ -85,17 +86,17 @@ func New(baseDir, password string, uid *id.ID, salt []byte, rsaKey *rsa.PrivateK
 			"Create new session")
 	}
 
-	s.user, err = user.NewUser(s.kv, uid, salt, rsaKey, isPrecanned)
+	s.user, err = user.NewUser(s.kv, u.ID, u.Salt, u.RSA, u.Precanned)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to create session")
 	}
 
-	s.cmix, err = cmix.NewStore(cmixGrp, s.kv, cmixDHPrivKey)
+	s.cmix, err = cmix.NewStore(cmixGrp, s.kv, u.CmixDhPrivateKey)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to create session")
 	}
 
-	s.e2e, err = e2e.NewStore(e2eGrp, s.kv, e2eDHPrivKey, rng)
+	s.e2e, err = e2e.NewStore(e2eGrp, s.kv, u.E2eDhPrivateKey, rng)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to create session")
 	}
diff --git a/storage/user.go b/storage/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..a4fb8742b9bacc16a254168ce643bff5473010d9
--- /dev/null
+++ b/storage/user.go
@@ -0,0 +1,26 @@
+package storage
+
+import "gitlab.com/elixxir/client/interfaces/user"
+
+func (s *Session) GetUser() user.User {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	ci := s.user.GetCryptographicIdentity()
+	return user.User{
+		ID:               ci.GetUserID().DeepCopy(),
+		Salt:             copySlice(ci.GetSalt()),
+		RSA:              ci.GetRSA(),
+		Precanned:        ci.IsPrecanned(),
+		CmixDhPrivateKey: s.cmix.GetDHPrivateKey().DeepCopy(),
+		CmixDhPublicKey:  s.cmix.GetDHPublicKey().DeepCopy(),
+		E2eDhPrivateKey:  s.e2e.GetDHPrivateKey().DeepCopy(),
+		E2eDhPublicKey:   s.e2e.GetDHPublicKey().DeepCopy(),
+	}
+
+}
+
+func copySlice(s []byte) []byte {
+	n := make([]byte, len(s))
+	copy(n, s)
+	return n
+}