diff --git a/bindings/client.go b/bindings/client.go
index 28f4eabc26255827e1f274b930c979f00d87c617..72ade2fbf508df8d97b67a8e39174d0dd4fe0069 100644
--- a/bindings/client.go
+++ b/bindings/client.go
@@ -70,7 +70,7 @@ type Listener interface {
 // If you pass the zero type (just zero) to Listen() you will hear messages of
 // all types.
 func (cl *Client) Listen(userId []byte, messageType int32, newListener Listener) string {
-	typedUserId := new(id.User).SetBytes(userId)
+	typedUserId := id.NewUserFromBytes(userId)
 
 	listener := &listenerProxy{proxy: newListener}
 
@@ -155,7 +155,7 @@ func (cl *Client) Register(preCan bool, registrationCode, nick,
 // This should only ever be used for testing purposes
 func (cl *Client) Login(UID []byte, email, addr string,
 	tlsCert string) (string, error) {
-	userID := new(id.User).SetBytes(UID)
+	userID := id.NewUserFromBytes(UID)
 	var err error
 	var nick string
 	if tlsCert == "default" {
@@ -170,8 +170,8 @@ func (cl *Client) Login(UID []byte, email, addr string,
 // Automatically serializes the message type before the rest of the payload
 // Returns an error if either sender or recipient are too short
 func (cl *Client) Send(m Message, encrypt bool) error {
-	sender := new(id.User).SetBytes(m.GetSender())
-	recipient := new(id.User).SetBytes(m.GetRecipient())
+	sender := id.NewUserFromBytes(m.GetSender())
+	recipient := id.NewUserFromBytes(m.GetRecipient())
 
 	var cryptoType format.CryptoType
 	if encrypt {
@@ -245,7 +245,7 @@ func (ncp *nickCallbackProxy) Callback(nick string, err error) {
 func (cl *Client) LookupNick(user []byte,
 	cb NickLookupCallback) {
 	proxy := &nickCallbackProxy{cb}
-	userID := new(id.User).SetBytes(user)
+	userID := id.NewUserFromBytes(user)
 	cl.client.LookupNick(userID, proxy)
 }
 
diff --git a/bots/bots.go b/bots/bots.go
index e7d54b89587af40ca53802c22ccd0c4da034ce3f..4f241e4e2f62a67dd07be2b80d09d29b961bc7fc 100644
--- a/bots/bots.go
+++ b/bots/bots.go
@@ -49,7 +49,7 @@ var nicknameRequestListener nickReqListener
 
 // InitBots is called internally by the Login API
 func InitBots(s user.Session,m io.Communications) {
-	UdbID = new(id.User).SetUints(&[4]uint64{0, 0, 0, 3})
+	UdbID = id.NewUserFromUints(&[4]uint64{0, 0, 0, 3})
 
 	pushKeyResponseListener = make(channelResponseListener)
 	getKeyResponseListener = make(channelResponseListener)
diff --git a/bots/bots_test.go b/bots/bots_test.go
index beb10ab9346f8d079ce7ac4b9190dbf9986254f0..a39eae0294d39abc37a503540503600d1a9ca93f 100644
--- a/bots/bots_test.go
+++ b/bots/bots_test.go
@@ -57,7 +57,7 @@ var pubKey []byte
 
 func TestMain(m *testing.M) {
 	u := &user.User{
-		User: new(id.User).SetUints(&[4]uint64{0, 0, 0, 18}),
+		User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}),
 		Nick: "Bernie",
 	}
 	fakeSession := user.NewSession(&globals.RamStorage{},
diff --git a/bots/userDiscovery.go b/bots/userDiscovery.go
index c87475002ea4ba480735035b3f834851832906c2..255ae73ab9ff966fe4607ad52a87f60a38758497 100644
--- a/bots/userDiscovery.go
+++ b/bots/userDiscovery.go
@@ -112,7 +112,7 @@ func parseSearch(msg string) (*id.User, string) {
 	if err != nil {
 		return id.ZeroID, fmt.Sprintf("Couldn't parse search cMix UID: %s", msg)
 	}
-	cMixUID := new(id.User).SetBytes(cMixUIDBytes)
+	cMixUID := id.NewUserFromBytes(cMixUIDBytes)
 
 	return cMixUID, resParts[4]
 }
diff --git a/cmd/root.go b/cmd/root.go
index 762dba741036d35ab9a92eedc6834aafdeb6863f..e96ea2587e569dd9bfcb56cf560afc459e734ee7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -141,7 +141,7 @@ func sessionInitialization() *id.User {
 		regCode := registrationCode
 		// If precanned user, use generated code instead
 		if userId != 0 {
-			regCode = new(id.User).SetUints(&[4]uint64{0, 0, 0, userId}).RegistrationCode()
+			regCode = id.NewUserFromUints(&[4]uint64{0, 0, 0, userId}).RegistrationCode()
 		}
 
 		globals.Log.INFO.Printf("Attempting to register with code %s...", regCode)
@@ -158,7 +158,7 @@ func sessionInitialization() *id.User {
 	} else {
 		// hack for session persisting with cmd line
 		// doesn't support non pre canned users
-		uid = new(id.User).SetUints(&[4]uint64{0, 0, 0, userId})
+		uid = id.NewUserFromUints(&[4]uint64{0, 0, 0, userId})
 		// clear userEmail if it was defined, since login was previously done
 		userEmail = ""
 	}
@@ -285,7 +285,7 @@ func (l *ChannelListener) Hear(item switchboard.Item, isHeardElsewhere bool) {
 	fmt.Printf("Message from channel %v, %v: ",
 		new(big.Int).SetBytes(message.Sender[:]).Text(10), senderNick)
 	typedBody, _ := parse.Parse(result.Message)
-	speakerId := new(id.User).SetBytes(result.SpeakerID)
+	speakerId := id.NewUserFromBytes(result.SpeakerID)
 	client.GetSwitchboard().Speak(&parse.Message{
 		TypedBody: *typedBody,
 		Sender:    speakerId,
@@ -345,7 +345,7 @@ var rootCmd = &cobra.Command{
 		}
 
 		// Only send a message if we have a message to send (except dummy messages)
-		recipientId := new(id.User).SetUints(&[4]uint64{0, 0, 0, destinationUserId})
+		recipientId := id.NewUserFromUints(&[4]uint64{0, 0, 0, destinationUserId})
 		if message != "" {
 			// Get the recipient's nick
 			recipientNick := ""
diff --git a/cmd/udb.go b/cmd/udb.go
index 8972fe89266533614102f44cabe4700036363acf..9c04d14095dbf96654c9be980cf0fa955845f9e2 100644
--- a/cmd/udb.go
+++ b/cmd/udb.go
@@ -23,7 +23,7 @@ func (cs callbackSearch) Callback(userID, pubKey []byte, err error) {
 		fmt.Printf("Public Key returned is empty\n")
 	} else {
 		fmt.Printf("UDB search successful. Returned user %v\n",
-			*new(id.User).SetBytes(userID))
+			*id.NewUserFromBytes(userID))
 	}
 }
 
diff --git a/crypto/encryptdecrypt_test.go b/crypto/encryptdecrypt_test.go
index 253c7aac5f4b47a3a55e804288ee8537afef9d22..9476a225cd3a9797218dce1d3827f16727523178 100644
--- a/crypto/encryptdecrypt_test.go
+++ b/crypto/encryptdecrypt_test.go
@@ -57,7 +57,7 @@ func setup() {
 
 	grp := cyclic.NewGroup(p, g, q)
 
-	UID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 18})
+	UID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 18})
 	u, _ := user.Users.GetUser(UID)
 
 	nk := make([]user.NodeKeys, 5)
diff --git a/glide.yaml b/glide.yaml
index cd36fb8e9a314ea2a6885c69f2010a5cc4e2d2cf..f597c158b752a039ec5b80abf301bf040350e95a 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -4,7 +4,7 @@ import:
   version: master
   vcs: git
 - package: gitlab.com/elixxir/crypto
-  version: master
+  version: immutableUserNodeId-xx-1185
   repo: git@gitlab.com:elixxir/crypto
   vcs: git
 - package: gitlab.com/elixxir/comms
diff --git a/rekey/rekey_test.go b/rekey/rekey_test.go
index 77aeba9b80a4aa8159671d480fe93009f6193ec0..2ad233daedae10a381f6a6f3b7439428fb86ff3c 100644
--- a/rekey/rekey_test.go
+++ b/rekey/rekey_test.go
@@ -55,13 +55,13 @@ func TestMain(m *testing.M) {
 		grp.GetQ())
 	rng := csprng.NewSystemRNG()
 	u := &user.User{
-		User: new(id.User).SetUints(&[4]uint64{0, 0, 0, 18}),
+		User: id.NewUserFromUints(&[4]uint64{0, 0, 0, 18}),
 		Nick: "Bernie",
 	}
 	myPrivKey := params.PrivateKeyGen(rng)
 	myPrivKeyCyclic := grp.NewIntFromLargeInt(myPrivKey.GetKey())
 	myPubKey := myPrivKey.PublicKeyGen()
-	partnerID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 12})
+	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
 	partnerPrivKey := params.PrivateKeyGen(rng)
 	partnerPubKey := partnerPrivKey.PublicKeyGen()
 	partnerPubKeyCyclic := grp.NewIntFromLargeInt(partnerPubKey.GetKey())
@@ -114,7 +114,7 @@ func TestMain(m *testing.M) {
 
 // Test RekeyTrigger
 func TestRekeyTrigger(t *testing.T) {
-	partnerID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 12})
+	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
 	km := session.GetKeyStore().GetRecvManager(partnerID)
 	partnerPubKey := km.GetPubKey()
 	// Test receiving a RekeyTrigger message
@@ -168,7 +168,7 @@ func TestRekeyTrigger(t *testing.T) {
 
 // Test RekeyConfirm
 func TestRekeyConfirm(t *testing.T) {
-	partnerID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 12})
+	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
 	rekeyCtx := session.GetRekeyManager().GetCtx(partnerID)
 	baseKey := rekeyCtx.BaseKey
 	// Test receiving a RekeyConfirm message with wrong H(baseKey)
@@ -236,7 +236,7 @@ func TestRekeyConfirm(t *testing.T) {
 
 // Test Rekey
 func TestRekey(t *testing.T) {
-	partnerID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 12})
+	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
 	km := session.GetKeyStore().GetSendManager(partnerID)
 	// Generate new partner public key
 	grp := globals.InitCrypto()
@@ -296,7 +296,7 @@ func TestRekey(t *testing.T) {
 
 // Test Rekey errors
 func TestRekey_Errors(t *testing.T) {
-	partnerID := new(id.User).SetUints(&[4]uint64{0, 0, 0, 12})
+	partnerID := id.NewUserFromUints(&[4]uint64{0, 0, 0, 12})
 	km := session.GetKeyStore().GetRecvManager(partnerID)
 	partnerPubKey := km.GetPubKey()
 	// Delete RekeyKeys so that RekeyTrigger and rekey error out
diff --git a/user/session_test.go b/user/session_test.go
index b901767c96228810c470179ff94f8e887c4acaef..23375add1f5da0aafd05934f0c04c6abde878c3f 100644
--- a/user/session_test.go
+++ b/user/session_test.go
@@ -10,8 +10,8 @@ import (
 	"crypto/sha256"
 	"gitlab.com/elixxir/client/globals"
 	"gitlab.com/elixxir/crypto/cyclic"
-	"gitlab.com/elixxir/crypto/signature"
 	"gitlab.com/elixxir/crypto/large"
+	"gitlab.com/elixxir/crypto/signature"
 	"gitlab.com/elixxir/primitives/id"
 	"math/rand"
 	"reflect"
@@ -70,7 +70,7 @@ func TestUserSession(t *testing.T) {
 	} else {
 		pass++
 	}
-	
+
 	_, err = LoadSession(storage,
 		id.NewUserFromUint(10002, t))
 
diff --git a/user/user.go b/user/user.go
index a65640cb12631b4a223fa89a3f735eee86f0d411..9b4da05e6fb569a61b0d6fa4d15b7ab545cd58d7 100644
--- a/user/user.go
+++ b/user/user.go
@@ -62,7 +62,7 @@ func newRegistry() Registry {
 	// Deterministically create NUM_DEMO_USERS users
 	// TODO Replace this with real user registration/discovery
 	for i := uint64(1); i <= NUM_DEMO_USERS; i++ {
-		currentID := new(id.User).SetUints(&[4]uint64{0, 0, 0, i})
+		currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, i})
 		t := new(User)
 		k := new(NodeKeys)
 
@@ -91,12 +91,12 @@ func newRegistry() Registry {
 
 	// Channels have been hardcoded to users starting with 31
 	for i := 0; i < len(DemoUserNicks); i++ {
-		currentID := new(id.User).SetUints(&[4]uint64{0, 0, 0, uint64(i) + 1})
+		currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 1})
 		uc[*currentID].Nick = DemoUserNicks[i]
 	}
 
 	for i := 0; i < len(DemoChannelNames); i++ {
-		currentID := new(id.User).SetUints(&[4]uint64{0, 0, 0, uint64(i) + 31})
+		currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 31})
 		uc[*currentID].Nick = DemoChannelNames[i]
 	}
 
diff --git a/user/user_test.go b/user/user_test.go
index 5ee814ba093e517ff94296338b9fb0f25b6e5181..2bd573b94b30717656bdc31a4a7da105d64aad10 100644
--- a/user/user_test.go
+++ b/user/user_test.go
@@ -15,7 +15,7 @@ import (
 )
 
 // InitGroup sets up the cryptographic constants for cMix
-func InitGroup() *cyclic.Group{
+func InitGroup() *cyclic.Group {
 
 	base := 16