diff --git a/api/client.go b/api/client.go
index 2a07d1743783e8a22dff5bc4d7c384b5e092a772..c47a4eb5f7e495ca3a24c5c66264c80a1f74e86e 100644
--- a/api/client.go
+++ b/api/client.go
@@ -346,7 +346,7 @@ func (c *Client) GetHealth() interfaces.HealthTracker {
 	return c.network.GetHealthTracker()
 }
 
-// Returns the switchboard for Registration
+// Returns the switchboard for Identity
 func (c *Client) GetSwitchboard() interfaces.Switchboard {
 	jww.INFO.Printf("GetSwitchboard()")
 	return c.switchboard
diff --git a/api/send.go b/api/send.go
index 84256b206d71db926818cc5c93b8e0269ce14eef..19d6a54b853f911e47af7d2d9bcafa46e2b7bd4d 100644
--- a/api/send.go
+++ b/api/send.go
@@ -15,6 +15,7 @@ import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 )
 
 //This holds all functions to send messages over the network
@@ -45,23 +46,21 @@ func (c *Client) SendUnsafe(m message.Send, param params.Unsafe) ([]id.Round,
 // recipient. Note that both SendE2E and SendUnsafe call SendCMIX.
 // Returns the round ID of the round the payload was sent or an error
 // if it fails.
-func (c *Client) SendCMIX(msg format.Message, param params.CMIX) (id.Round,
-	error) {
+func (c *Client) SendCMIX(msg format.Message, recipientID *id.ID,
+	param params.CMIX) (id.Round, ephemeral.Id, error) {
 	jww.INFO.Printf("SendCMIX(%s)", string(msg.GetContents()))
-	return c.network.SendCMIX(msg, param)
+	return c.network.SendCMIX(msg, recipientID, param)
 }
 
 // NewCMIXMessage Creates a new cMix message with the right properties
 // for the current cMix network.
 // FIXME: this is weird and shouldn't be necessary, but it is.
-func (c *Client) NewCMIXMessage(recipient *id.ID,
-	contents []byte) (format.Message, error) {
+func (c *Client) NewCMIXMessage(contents []byte) (format.Message, error) {
 	primeSize := len(c.storage.Cmix().GetGroup().GetPBytes())
 	msg := format.NewMessage(primeSize)
 	if len(contents) > msg.ContentsSize() {
 		return format.Message{}, errors.New("Contents to long for cmix")
 	}
 	msg.SetContents(contents)
-	msg.SetRecipientID(recipient)
 	return msg, nil
 }
diff --git a/auth/confirm.go b/auth/confirm.go
index a58306c2da8dce6017c96af1d10888652f67ea73..4a1d27cdea37d86bc8e59305daffca7c9cc78216 100644
--- a/auth/confirm.go
+++ b/auth/confirm.go
@@ -99,7 +99,6 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader,
 	cmixMsg.SetKeyFP(fp)
 	cmixMsg.SetMac(mac)
 	cmixMsg.SetContents(baseFmt.Marshal())
-	cmixMsg.SetRecipientID(partner.ID)
 
 	// fixme: channel can get into a bricked state if the first save occurs and
 	// the second does not or the two occur and the storage into critical
@@ -127,7 +126,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader,
 	storage.GetCriticalRawMessages().AddProcessing(cmixMsg)
 
 	/*send message*/
-	round, err := net.SendCMIX(cmixMsg, params.GetDefaultCMIX())
+	round, _, err := net.SendCMIX(cmixMsg, partner.ID, params.GetDefaultCMIX())
 	if err != nil {
 		// if the send fails just set it to failed, it will but automatically
 		// retried
diff --git a/auth/request.go b/auth/request.go
index dd8ba152500b192591a58aab863df4c14a462c26..d0e20a44b2f09707a4d456c99c5ced2cacd65551 100644
--- a/auth/request.go
+++ b/auth/request.go
@@ -132,7 +132,6 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader,
 	cmixMsg.SetKeyFP(requestfp)
 	cmixMsg.SetMac(mac)
 	cmixMsg.SetContents(baseFmt.Marshal())
-	cmixMsg.SetRecipientID(partner.ID)
 	jww.INFO.Printf("PARTNER ID: %s", partner.ID)
 
 	/*store state*/
@@ -149,11 +148,11 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader,
 
 	//jww.INFO.Printf("CMIX MESSAGE 1: %s, %v, %v, %v", cmixMsg.GetRecipientID(),
 	//	cmixMsg.GetKeyFP(), cmixMsg.GetMac(), cmixMsg.GetContents())
-	jww.INFO.Printf("CMIX MESSAGE FP: %s, %v", cmixMsg.GetRecipientID(),
+	jww.INFO.Printf("CMIX MESSAGE FP: %s, %v", partner.ID,
 		cmixMsg.GetKeyFP())
 
 	/*send message*/
-	round, err := net.SendCMIX(cmixMsg, params.GetDefaultCMIX())
+	round, _, err := net.SendCMIX(cmixMsg, partner.ID, params.GetDefaultCMIX())
 	if err != nil {
 		// if the send fails just set it to failed, it will but automatically
 		// retried
diff --git a/bindings/send.go b/bindings/send.go
index 605fddd26d2ceace3a7081e73a0a17b0d007d87a..a7e35873447758c22cb9ddfc8eddeaf86fe1bb73 100644
--- a/bindings/send.go
+++ b/bindings/send.go
@@ -43,13 +43,13 @@ func (c *Client) SendCmix(recipient, contents []byte, parameters string) (int, e
 			err))
 	}
 
-	msg, err := c.api.NewCMIXMessage(u, contents)
+	msg, err := c.api.NewCMIXMessage(contents)
 	if err != nil {
 		return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v",
 			err))
 	}
 
-	rid, err := c.api.SendCMIX(msg, p)
+	rid, _, err := c.api.SendCMIX(msg, u, p)
 	if err != nil {
 		return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v",
 			err))
diff --git a/bindings/ud.go b/bindings/ud.go
index bae84a46f6b040a7a366cd51396f0c433278da0a..643066a2ad2417ab444698c63b717101454ea53c 100644
--- a/bindings/ud.go
+++ b/bindings/ud.go
@@ -44,7 +44,7 @@ func NewUserDiscovery(client *Client)(*UserDiscovery, error){
 // network signatures are malformed or if the username is taken. Usernames
 // cannot be changed after registration at this time. Will fail if the user is
 // already registered.
-// Registration does not go over cmix, it occurs over normal communications
+// Identity does not go over cmix, it occurs over normal communications
 func (ud *UserDiscovery)Register(username string)error{
 	return ud.ud.Register(username)
 }
diff --git a/cmd/root.go b/cmd/root.go
index 7fcc9a5b00cfb05a121441bff85f74349abbbc67..ca88cd9bf72b9054afc7023367c5d54f751772ed 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -565,7 +565,7 @@ func init() {
 	viper.BindPFlag("log", rootCmd.PersistentFlags().Lookup("log"))
 
 	rootCmd.Flags().StringP("regcode", "", "",
-		"Registration code (optional)")
+		"Identity code (optional)")
 	viper.BindPFlag("regcode", rootCmd.Flags().Lookup("regcode"))
 
 	rootCmd.Flags().StringP("message", "m", "", "Message to send")
diff --git a/globals/statusEvents.go b/globals/statusEvents.go
index 9695871da46a8252d42bd838996b1bb7a30330c2..fdf8d6ff99f6ac0c5cbc155eebe1a9c645c0ab8f 100644
--- a/globals/statusEvents.go
+++ b/globals/statusEvents.go
@@ -7,9 +7,9 @@
 
 package globals
 
-//Registration
+//Identity
 const REG_KEYGEN = 1       //Generating Cryptographic Keys
-const REG_PRECAN = 2       //Doing a Precanned Registration (Not Secure)
+const REG_PRECAN = 2       //Doing a Precanned Identity (Not Secure)
 const REG_UID_GEN = 3      //Generating User ID
 const REG_PERM = 4         //Validating User Identity With Permissioning Server
 const REG_NODE = 5         //Registering with Nodes
diff --git a/go.mod b/go.mod
index 6176f5edda53c1f4f99c6289e28f15280496e803..cff0e768391d7579628b29049b954625e5b4b577 100644
--- a/go.mod
+++ b/go.mod
@@ -19,14 +19,14 @@ require (
 	github.com/spf13/viper v1.7.1
 	github.com/ugorji/go v1.1.4 // indirect
 	github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 // indirect
-	gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228
-	gitlab.com/elixxir/comms v0.0.4-0.20210114174157-1306832d440b
-	gitlab.com/elixxir/crypto v0.0.7-0.20210107184400-5c3e52a35758
+	gitlab.com/elixxir/bloomfilter v0.0.0-20210120224144-ac046983a17a
+	gitlab.com/elixxir/comms v0.0.4-0.20210208181740-1ad1139f7170
+	gitlab.com/elixxir/crypto v0.0.7-0.20210208181828-64b4b57e23d6
 	gitlab.com/elixxir/ekv v0.1.4
-	gitlab.com/elixxir/primitives v0.0.3-0.20210107183456-9cf6fe2de1e5
-	gitlab.com/xx_network/comms v0.0.4-0.20210112233928-eac8db03c397
-	gitlab.com/xx_network/crypto v0.0.5-0.20210107183440-804e0f8b7d22
-	gitlab.com/xx_network/primitives v0.0.4-0.20210114170718-1549f24d462c
+	gitlab.com/elixxir/primitives v0.0.3-0.20210127201240-6a42ad925e8a
+	gitlab.com/xx_network/comms v0.0.4-0.20210121204701-7a1eb0542424
+	gitlab.com/xx_network/crypto v0.0.5-0.20210121204626-b251b926e4f7
+	gitlab.com/xx_network/primitives v0.0.4-0.20210208183356-ee1e9ec13f8f
 	golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
 	golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
 	golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect
diff --git a/go.sum b/go.sum
index f5f678113615e8cdda98594645a7827210c2d71a..7d36eea12e9b2f59707b7674b4a09b0c68330d9e 100644
--- a/go.sum
+++ b/go.sum
@@ -265,6 +265,9 @@ github.com/zeebo/pcg v1.0.0 h1:dt+dx+HvX8g7Un32rY9XWoYnd0NmKmrIzpHF7qiTDj0=
 github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 h1:Gi6rj4mAlK0BJIk1HIzBVMjWNjIUfstrsXC2VqLYPcA=
 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k=
+gitlab.com/elixxir/bloomfilter v0.0.0-20210120224144-ac046983a17a h1:0vLmGrqRDlaru89aKQPk3MyRPUInFujpqnVspBA6QTQ=
+gitlab.com/elixxir/bloomfilter v0.0.0-20210120224144-ac046983a17a/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k=
+gitlab.com/elixxir/comms v0.0.3/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU=
 gitlab.com/elixxir/comms v0.0.4-0.20201217200754-6259dc49e6f1 h1:4iuAA/I8/aQ1Jn3gBguuR1u+LVy3YyShxpoNcqApaVg=
 gitlab.com/elixxir/comms v0.0.4-0.20201217200754-6259dc49e6f1/go.mod h1:2sNUHm725vQG4pG1RtvMd7kJ5CNqFb7Rl9cenuQCa2c=
 gitlab.com/elixxir/comms v0.0.4-0.20201229200853-c403d72e877c h1:YjTlUbZiNiJdL7Fy4TIUoWlHNK4dFOtuJ40YgsG7fac=
@@ -279,10 +282,22 @@ gitlab.com/elixxir/comms v0.0.4-0.20210112234945-18c36b2d908f h1:EsCG5+sB1ZapIBY
 gitlab.com/elixxir/comms v0.0.4-0.20210112234945-18c36b2d908f/go.mod h1:R2Ank04m99uGRhKOssWzITqN47AT+EOyG2OiCHLGroE=
 gitlab.com/elixxir/comms v0.0.4-0.20210114174157-1306832d440b h1:LdlL28odDDoQbhpgF7jUR3x2TXG1P4TzGfVBg2Md6Ek=
 gitlab.com/elixxir/comms v0.0.4-0.20210114174157-1306832d440b/go.mod h1:R2Ank04m99uGRhKOssWzITqN47AT+EOyG2OiCHLGroE=
+gitlab.com/elixxir/comms v0.0.4-0.20210115185903-5dba75967ad3 h1:QJLHqjl35tV/BmFqY+auK6wrmjTdRh+IO/fXQA56XIg=
+gitlab.com/elixxir/comms v0.0.4-0.20210115185903-5dba75967ad3/go.mod h1:s+wIMGLQWeIiOY+LYmGciAkcM9whr+CWQNzf8qb+Oao=
+gitlab.com/elixxir/comms v0.0.4-0.20210121204920-12c3111eff14 h1:/5w3IE06wUF35/h8x6SHM8zZUcrQw2VgBjhmAcJjDow=
+gitlab.com/elixxir/comms v0.0.4-0.20210121204920-12c3111eff14/go.mod h1:oJPQZEobUQwmype16+Hl9s2l+k3luL4ViUKxj0S4Dp8=
+gitlab.com/elixxir/comms v0.0.4-0.20210121222442-b714136536e9 h1:9jQb6bynSFVw9jDKX8t71V7EEwKkDtxzDxMaxw7+hYc=
+gitlab.com/elixxir/comms v0.0.4-0.20210121222442-b714136536e9/go.mod h1:oJPQZEobUQwmype16+Hl9s2l+k3luL4ViUKxj0S4Dp8=
+gitlab.com/elixxir/comms v0.0.4-0.20210126185553-8ccfd64bf81b h1:ENB2YHpF72bbVHA6GG8BrMXEb+si9JHhO39vx7vk7hA=
+gitlab.com/elixxir/comms v0.0.4-0.20210126185553-8ccfd64bf81b/go.mod h1:5hxGwa/8BEpo4cZrbxhxyXPpXmwzMPunKE/H141+rPU=
+gitlab.com/elixxir/comms v0.0.4-0.20210208181740-1ad1139f7170 h1:YD0QgSP5puQXn3bMOJuA7sT7DXLCVgHBW//PSESU45o=
+gitlab.com/elixxir/comms v0.0.4-0.20210208181740-1ad1139f7170/go.mod h1:fWuPOszadMhHLOywy2+mMSMH00k9sh/zw/povSWurn4=
 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.3 h1:znCt/x2bL4y8czTPaaFkwzdgSgW3BJc/1+dxyf1jqVw=
 gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
+gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
+gitlab.com/elixxir/crypto v0.0.6 h1:c94CGzBTV7LgInGHfmeJHrqq9nIc/WEOLUd9OeQBN74=
 gitlab.com/elixxir/crypto v0.0.7-0.20201217200352-0ba771a66932/go.mod h1:nqSNe486j6ua96nv1et6x2ESl/qXevkx7f31GowMRh4=
 gitlab.com/elixxir/crypto v0.0.7-0.20201222203132-9b4cc1ae3da6 h1:Vyf2wJ1/CoHLznATpI+z84OJQ+sgAbpVLT9P1CNjSVI=
 gitlab.com/elixxir/crypto v0.0.7-0.20201222203132-9b4cc1ae3da6/go.mod h1:NsIzH+TN592lMcmJGVzxUE64dObXuci7jo0qajyGahI=
@@ -290,6 +305,18 @@ gitlab.com/elixxir/crypto v0.0.7-0.20210104223925-7dfd3ad55d5c h1:/iLLZvu5mbFXxc
 gitlab.com/elixxir/crypto v0.0.7-0.20210104223925-7dfd3ad55d5c/go.mod h1:cEn3ghYlk7Fhz1dOu3OEw9v9nIZNYH6hqnjHlTLxFiA=
 gitlab.com/elixxir/crypto v0.0.7-0.20210107184400-5c3e52a35758 h1:h2l8SZbdgcyMVwgcMqBgAoJSqI1CC23MChB5k7xqqRI=
 gitlab.com/elixxir/crypto v0.0.7-0.20210107184400-5c3e52a35758/go.mod h1:JDC7EFs5V97qourZyiSHBiiXHGUoKWX9XtJVhfEvpC4=
+gitlab.com/elixxir/crypto v0.0.7-0.20210113224347-cc4926b30fba h1:GtjhegVf6L9MZ6gp2oeBo/oVYUVB/IO91xBycF/jcNo=
+gitlab.com/elixxir/crypto v0.0.7-0.20210113224347-cc4926b30fba/go.mod h1:JDC7EFs5V97qourZyiSHBiiXHGUoKWX9XtJVhfEvpC4=
+gitlab.com/elixxir/crypto v0.0.7-0.20210114172156-b576829ba7d8 h1:KhhsuPn+aPzZ66jdbbRF55SurogvQ/X9KuMWkXtmq+U=
+gitlab.com/elixxir/crypto v0.0.7-0.20210114172156-b576829ba7d8/go.mod h1:4AumkGNppiEaMo6bIpFBrV6wZtaIjpbvkpA5+FBisA8=
+gitlab.com/elixxir/crypto v0.0.7-0.20210115231025-5d9b0dbc6985 h1:Csf3dIhwA6D293aURIHKuvwZr4HgIRzJ4FpCklmXEmA=
+gitlab.com/elixxir/crypto v0.0.7-0.20210115231025-5d9b0dbc6985/go.mod h1:JDC7EFs5V97qourZyiSHBiiXHGUoKWX9XtJVhfEvpC4=
+gitlab.com/elixxir/crypto v0.0.7-0.20210121204803-2caab60ff687 h1:tBlYA/jUOquWpe7bGZBQtvngbfbHsyt11aKZ761++8k=
+gitlab.com/elixxir/crypto v0.0.7-0.20210121204803-2caab60ff687/go.mod h1:7egP0+qiVyZnqcBlRr4rL0FhGNkqDCNEygungCAp7NM=
+gitlab.com/elixxir/crypto v0.0.7-0.20210125231257-b52a556be893 h1:0NjQOwdGO/xBvgBMzRLSFXpSpnluzjT16obl5AcGfmI=
+gitlab.com/elixxir/crypto v0.0.7-0.20210125231257-b52a556be893/go.mod h1:BoYrgHnTJPvvd4f/f4A+y22wwgZ7IxkYtGC8x9WiwxA=
+gitlab.com/elixxir/crypto v0.0.7-0.20210208181828-64b4b57e23d6 h1:Q1Ldvj70eM60MLaHgSXE7C95uTkn5utCq+bMCY2pyrA=
+gitlab.com/elixxir/crypto v0.0.7-0.20210208181828-64b4b57e23d6/go.mod h1:JDC7EFs5V97qourZyiSHBiiXHGUoKWX9XtJVhfEvpC4=
 gitlab.com/elixxir/ekv v0.1.4-0.20201217220111-9c7e8be21577 h1:qT3ZO9GbKv7PcmakATsXsUdzn/hlm817ETOT/csDIak=
 gitlab.com/elixxir/ekv v0.1.4-0.20201217220111-9c7e8be21577/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
 gitlab.com/elixxir/ekv v0.1.4 h1:NLVMwsFEKArWcsDHu2DbXlm9374iSgn7oIA3rVSsvjc=
@@ -299,6 +326,7 @@ gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0Vel
 gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
 gitlab.com/elixxir/primitives v0.0.1 h1:q61anawANlNAExfkeQEE1NCsNih6vNV1FFLoUQX6txQ=
 gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE=
+gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc=
 gitlab.com/elixxir/primitives v0.0.3-0.20201217193438-8ebfc882f1de/go.mod h1:H1OZ6ZXzTB3G4nOEdJzBJ7BySRnivpJTkTphxazFCl4=
 gitlab.com/elixxir/primitives v0.0.3-0.20201222171449-bdfe30389bb5 h1:BUV1ouY+9NA5+ZF+QfTpIBL1vO5zk31I68N7DX9bKj8=
 gitlab.com/elixxir/primitives v0.0.3-0.20201222171449-bdfe30389bb5/go.mod h1:5Z8fce94mks0aFhMvzftx2jJpDx4/pzDU20G2oTiU9w=
@@ -310,7 +338,17 @@ gitlab.com/elixxir/primitives v0.0.3-0.20210106014507-bf3dfe228fa6 h1:sUqEla1uUI
 gitlab.com/elixxir/primitives v0.0.3-0.20210106014507-bf3dfe228fa6/go.mod h1:Ph6isHUDVjmRUd9DioyKpd8W9J52gKBiDeue4DCygXA=
 gitlab.com/elixxir/primitives v0.0.3-0.20210107183456-9cf6fe2de1e5 h1:50HbCJWirpX2Q+NNhIHcs0M9f45H1UJ/7LNMu81Bnn0=
 gitlab.com/elixxir/primitives v0.0.3-0.20210107183456-9cf6fe2de1e5/go.mod h1:Ph6isHUDVjmRUd9DioyKpd8W9J52gKBiDeue4DCygXA=
+gitlab.com/elixxir/primitives v0.0.3-0.20210121204717-e15ada7f0a73 h1:9h+pCc1ceIWDR1CM5sdoV7KHvNYzKQRJjeIfc26fyDU=
+gitlab.com/elixxir/primitives v0.0.3-0.20210121204717-e15ada7f0a73/go.mod h1:bGYfAGerVVZhNzh+PxOMZVG7iYAUfInYvtdAkAqgiY8=
+gitlab.com/elixxir/primitives v0.0.3-0.20210122185056-ad244787d961 h1:BUN6bUBmTeebwYvTQ5yVi1iJlNAhjR7kEndcsV339dE=
+gitlab.com/elixxir/primitives v0.0.3-0.20210122185056-ad244787d961/go.mod h1:bGYfAGerVVZhNzh+PxOMZVG7iYAUfInYvtdAkAqgiY8=
+gitlab.com/elixxir/primitives v0.0.3-0.20210125225949-9469ce6b08fc/go.mod h1:bGYfAGerVVZhNzh+PxOMZVG7iYAUfInYvtdAkAqgiY8=
+gitlab.com/elixxir/primitives v0.0.3-0.20210126180712-bfbfb725c75a h1:3jq90Nmn8Ew9vfUuizV4mvj6py5LOmX3wkuBc+ywJ0w=
+gitlab.com/elixxir/primitives v0.0.3-0.20210126180712-bfbfb725c75a/go.mod h1:bGYfAGerVVZhNzh+PxOMZVG7iYAUfInYvtdAkAqgiY8=
+gitlab.com/elixxir/primitives v0.0.3-0.20210127201240-6a42ad925e8a h1:ZQncDfITNE12EdJK+shh6UzHlALhNU4Zjvv4hid2krs=
+gitlab.com/elixxir/primitives v0.0.3-0.20210127201240-6a42ad925e8a/go.mod h1:Ph6isHUDVjmRUd9DioyKpd8W9J52gKBiDeue4DCygXA=
 gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
+gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8=
 gitlab.com/xx_network/comms v0.0.4-0.20201130190834-365ddae56e7b/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8=
 gitlab.com/xx_network/comms v0.0.4-0.20201217200138-87075d5b4ffd h1:4LjS3UuBNA/AaglIJ+k1IBoxYgCWt+FM1MPYxjAFfaQ=
 gitlab.com/xx_network/comms v0.0.4-0.20201217200138-87075d5b4ffd/go.mod h1:/vIk6tSrDqk/7HZOdrbSXZT+kEL43HIoz60AoZTzTXg=
@@ -322,6 +360,10 @@ gitlab.com/xx_network/comms v0.0.4-0.20210107184305-7bb439c08ded h1:VHAQcap/+jcF
 gitlab.com/xx_network/comms v0.0.4-0.20210107184305-7bb439c08ded/go.mod h1:12OZe2Ol9lEk7JTm48GQ4zj1O01SH0ygfLqOb8EHrtU=
 gitlab.com/xx_network/comms v0.0.4-0.20210112233928-eac8db03c397 h1:E7p5lGX+nTAIKB6Wno3mRxBfC+SX5ZY2FKp8JEMzdSM=
 gitlab.com/xx_network/comms v0.0.4-0.20210112233928-eac8db03c397/go.mod h1:12OZe2Ol9lEk7JTm48GQ4zj1O01SH0ygfLqOb8EHrtU=
+gitlab.com/xx_network/comms v0.0.4-0.20210115175102-ad5814bff11c h1:MRxHypL++mTDzVJq503ePBW3aGHE5FTG1ybac8rGK0A=
+gitlab.com/xx_network/comms v0.0.4-0.20210115175102-ad5814bff11c/go.mod h1:12OZe2Ol9lEk7JTm48GQ4zj1O01SH0ygfLqOb8EHrtU=
+gitlab.com/xx_network/comms v0.0.4-0.20210121204701-7a1eb0542424 h1:zhfkbutYEY7PQuC1kcugCt4am/oRAyla6u4xDc5PqWs=
+gitlab.com/xx_network/comms v0.0.4-0.20210121204701-7a1eb0542424/go.mod h1:MNkja6iUsM2yjBQicwLUGYctZmAU/D4AMpDD04vfBg8=
 gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE=
 gitlab.com/xx_network/crypto v0.0.4 h1:lpKOL5mTJ2awWMfgBy30oD/UvJVrWZzUimSHlOdZZxo=
 gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk=
@@ -334,6 +376,8 @@ gitlab.com/xx_network/crypto v0.0.5-0.20210106014410-0554a33a7124 h1:G2fNW7uPzJE
 gitlab.com/xx_network/crypto v0.0.5-0.20210106014410-0554a33a7124/go.mod h1:tTYlvAZNUFMtndcijM37iujkM4gP8kUwGiS9n7NA5Ck=
 gitlab.com/xx_network/crypto v0.0.5-0.20210107183440-804e0f8b7d22 h1:SQga1vOuAGzbYURnBjG0f37r7WmWKZRdiqmdopaNMb4=
 gitlab.com/xx_network/crypto v0.0.5-0.20210107183440-804e0f8b7d22/go.mod h1:tTYlvAZNUFMtndcijM37iujkM4gP8kUwGiS9n7NA5Ck=
+gitlab.com/xx_network/crypto v0.0.5-0.20210121204626-b251b926e4f7 h1:eraxUmI0EFDtfqTV4Ojndoh8Bv8PBUbZaT27VLU1yhc=
+gitlab.com/xx_network/crypto v0.0.5-0.20210121204626-b251b926e4f7/go.mod h1:61fEAGI2+JD6CbT5PMzxy1SBMvgiFxE4MyiQghzoOVg=
 gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
@@ -347,8 +391,25 @@ gitlab.com/xx_network/primitives v0.0.4-0.20201229212313-fe33d9809f27 h1:JGpYRKk
 gitlab.com/xx_network/primitives v0.0.4-0.20201229212313-fe33d9809f27/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=
 gitlab.com/xx_network/primitives v0.0.4-0.20210106014326-691ebfca3b07 h1:ZxGp7Q0Vyx2mWM84GIPPT3PZK2TLfwycSIk7EgNMIws=
 gitlab.com/xx_network/primitives v0.0.4-0.20210106014326-691ebfca3b07/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=
-gitlab.com/xx_network/primitives v0.0.4-0.20210114170718-1549f24d462c h1:RjDklUt70MgcVqBoJvWdBoygkizoByv6Q6DsZSqcFSI=
 gitlab.com/xx_network/primitives v0.0.4-0.20210114170718-1549f24d462c/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210118193646-93176e2e6925 h1:n40/5N6aXnye+QmkqKCnEEEepYw4lN9uQ/mhAyCyA3o=
+gitlab.com/xx_network/primitives v0.0.4-0.20210118193646-93176e2e6925/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=
+gitlab.com/xx_network/primitives v0.0.4-0.20210121203635-8a771fc14f8a h1:ZDv8RHUsl9pjIkgqd8u6y00P+6TXEASwBg9dpvHSsT0=
+gitlab.com/xx_network/primitives v0.0.4-0.20210121203635-8a771fc14f8a/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210127181825-f9178f9d19b5 h1:dI/3SkJie/Twy4ZZnsNncyiLI6KHJboaRagSU5V96YY=
+gitlab.com/xx_network/primitives v0.0.4-0.20210127181825-f9178f9d19b5/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210129181607-5b719add9171 h1:9nvaBYeOH/f8Ev/1b3IhoJdrxXaQZ5Lb/tFe1GzqH00=
+gitlab.com/xx_network/primitives v0.0.4-0.20210129181607-5b719add9171/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201174745-f294e495260d h1:tXEJOJq6rIizJyo/fgs6G17isq9UMahHx6BPtXgheLg=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201174745-f294e495260d/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201180649-48711cee9127 h1:DYYHQeNyh/6Cj3swZYy8bAYFL4yqxedu2dFZMDt8D3M=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201180649-48711cee9127/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201180820-639f0a366d52 h1:gZk8XTQOAFt3IUd2LUsWWYpQQz5ktQF5uD+gV4pu4e8=
+gitlab.com/xx_network/primitives v0.0.4-0.20210201180820-639f0a366d52/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210202001929-8bf8bf35a234 h1:OXR+c++r+IsFu4OKEMY9pJrZFCTp/qt8irEdCgNj4Hw=
+gitlab.com/xx_network/primitives v0.0.4-0.20210202001929-8bf8bf35a234/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
+gitlab.com/xx_network/primitives v0.0.4-0.20210208183356-ee1e9ec13f8f h1:21mljvQ0ZPNZbOP0BG5JNGlDgiC/vg9NZ/AaseXSxBI=
+gitlab.com/xx_network/primitives v0.0.4-0.20210208183356-ee1e9ec13f8f/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
 gitlab.com/xx_network/ring v0.0.2 h1:TlPjlbFdhtJrwvRgIg4ScdngMTaynx/ByHBRZiXCoL0=
 gitlab.com/xx_network/ring v0.0.2/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -524,6 +585,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
diff --git a/interfaces/bloom.go b/interfaces/bloom.go
new file mode 100644
index 0000000000000000000000000000000000000000..abd84fcb8ebb590ead20b20ebcb6f62b9827d329
--- /dev/null
+++ b/interfaces/bloom.go
@@ -0,0 +1,4 @@
+package interfaces
+
+const BloomFilterSize = 904 // In Bits
+const BloomFilterHashes = 10
diff --git a/interfaces/contact/contact_test.go b/interfaces/contact/contact_test.go
index 97af5f2f40d6072f696b584c88ebd6710481e24c..b87f983ca8d055de6da893d23f9d8ab8382c01a8 100644
--- a/interfaces/contact/contact_test.go
+++ b/interfaces/contact/contact_test.go
@@ -11,6 +11,7 @@ import (
 	"crypto"
 	"encoding/base64"
 	"encoding/json"
+	"fmt"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/primitives/fact"
 	"gitlab.com/xx_network/crypto/csprng"
@@ -37,6 +38,8 @@ func TestContact_Marshal_Unmarshal(t *testing.T) {
 
 	buff := expectedContact.Marshal()
 
+	fmt.Println(string(buff))
+
 	testContact, err := Unmarshal(buff)
 	if err != nil {
 		t.Errorf("Unmarshal() produced an error: %+v", err)
diff --git a/interfaces/message/receiveMessage.go b/interfaces/message/receiveMessage.go
index faa61d61f0a375eae5506c55b10dfb7b99b83a32..f5373e716513a10a85d8a168b690b8a8beefbbf9 100644
--- a/interfaces/message/receiveMessage.go
+++ b/interfaces/message/receiveMessage.go
@@ -10,6 +10,7 @@ package message
 import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 	"time"
 )
 
@@ -18,6 +19,8 @@ type Receive struct {
 	Payload     []byte
 	MessageType Type
 	Sender      *id.ID
+	RecipientID	*id.ID
+	EphemeralID ephemeral.Id
 	Timestamp   time.Time
 	Encryption  EncryptionType
 }
diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go
index 541dc5b147d64440b3507ec28f72f735086cd37b..b7ff3a886346a0d23934b6ef359db4e872101415 100644
--- a/interfaces/networkManager.go
+++ b/interfaces/networkManager.go
@@ -15,12 +15,13 @@ import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 )
 
 type NetworkManager interface {
 	SendE2E(m message.Send, p params.E2E) ([]id.Round, e2e.MessageID, error)
 	SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error)
-	SendCMIX(message format.Message, p params.CMIX) (id.Round, error)
+	SendCMIX(message format.Message, recipient *id.ID, p params.CMIX) (id.Round, ephemeral.Id, error)
 	GetInstance() *network.Instance
 	GetHealthTracker() HealthTracker
 	Follow() (stoppable.Stoppable, error)
diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go
index 4fc72a604e50891d56c748a9c84272b7e7c1b2aa..c11728b1afd66ace0983fce8dcf2134978f35150 100644
--- a/keyExchange/utils_test.go
+++ b/keyExchange/utils_test.go
@@ -26,6 +26,7 @@ import (
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 	"gitlab.com/xx_network/primitives/ndf"
 	"testing"
 	"time"
@@ -76,9 +77,9 @@ func (t *testNetworkManagerGeneric) SendUnsafe(m message.Send, p params.Unsafe)
 	return nil, nil
 }
 
-func (t *testNetworkManagerGeneric) SendCMIX(message format.Message, p params.CMIX) (id.Round, error) {
+func (t *testNetworkManagerGeneric) SendCMIX(message format.Message, rid *id.ID, p params.CMIX) (id.Round, ephemeral.Id, error) {
 
-	return id.Round(0), nil
+	return id.Round(0), ephemeral.Id{}, nil
 
 }
 
@@ -183,9 +184,9 @@ func (t *testNetworkManagerFullExchange) SendUnsafe(m message.Send, p params.Uns
 	return nil, nil
 }
 
-func (t *testNetworkManagerFullExchange) SendCMIX(message format.Message, p params.CMIX) (id.Round, error) {
+func (t *testNetworkManagerFullExchange) SendCMIX(message format.Message, eid *id.ID, p params.CMIX) (id.Round, ephemeral.Id, error) {
 
-	return id.Round(0), nil
+	return id.Round(0), ephemeral.Id{}, nil
 
 }
 
diff --git a/network/ephemeral/testutil.go b/network/ephemeral/testutil.go
new file mode 100644
index 0000000000000000000000000000000000000000..1691ae8bd450fd70cd03e0f8f8c00733c16ec828
--- /dev/null
+++ b/network/ephemeral/testutil.go
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package ephemeral
+
+import (
+	"gitlab.com/elixxir/client/globals"
+	"gitlab.com/elixxir/client/interfaces"
+	"gitlab.com/elixxir/client/interfaces/message"
+	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/client/stoppable"
+	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/comms/testkeys"
+	"gitlab.com/elixxir/crypto/e2e"
+	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"gitlab.com/xx_network/primitives/ndf"
+	"gitlab.com/xx_network/primitives/utils"
+	"testing"
+)
+
+// testNetworkManager is a test implementation of NetworkManager interface.
+type testNetworkManager struct {
+	instance *network.Instance
+	msg      message.Send
+}
+
+func (t *testNetworkManager) SendE2E(m message.Send, _ params.E2E) ([]id.Round,
+	e2e.MessageID, error) {
+	rounds := []id.Round{
+		id.Round(0),
+		id.Round(1),
+		id.Round(2),
+	}
+
+	t.msg = m
+
+	return rounds, e2e.MessageID{}, nil
+}
+
+func (t *testNetworkManager) SendUnsafe(m message.Send, _ params.Unsafe) ([]id.Round, error) {
+	rounds := []id.Round{
+		id.Round(0),
+		id.Round(1),
+		id.Round(2),
+	}
+
+	t.msg = m
+
+	return rounds, nil
+}
+
+func (t *testNetworkManager) SendCMIX(format.Message, *id.ID, params.CMIX) (id.Round, ephemeral.Id, error) {
+	return 0, ephemeral.Id{}, nil
+}
+
+func (t *testNetworkManager) GetInstance() *network.Instance {
+	return t.instance
+}
+
+func (t *testNetworkManager) GetHealthTracker() interfaces.HealthTracker {
+	return nil
+}
+
+func (t *testNetworkManager) Follow() (stoppable.Stoppable, error) {
+	return nil, nil
+}
+
+func (t *testNetworkManager) CheckGarbledMessages() {}
+
+func NewTestNetworkManager(i interface{}) interfaces.NetworkManager {
+	switch i.(type) {
+	case *testing.T, *testing.M, *testing.B:
+		break
+	default:
+		globals.Log.FATAL.Panicf("initTesting is restricted to testing only."+
+			"Got %T", i)
+	}
+
+	commsManager := connect.NewManagerTesting(i)
+
+	cert, err := utils.ReadFile(testkeys.GetNodeCertPath())
+	if err != nil {
+		globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err)
+	}
+
+	commsManager.AddHost(&id.Permissioning, "", cert, connect.GetDefaultHostParams())
+	instanceComms := &connect.ProtoComms{
+		Manager: commsManager,
+	}
+
+	thisInstance, err := network.NewInstanceTesting(instanceComms, getNDF(), getNDF(), nil, nil, i)
+	if err != nil {
+		globals.Log.FATAL.Panicf("Failed to create new test Instance: %v", err)
+	}
+
+	thisManager := &testNetworkManager{instance: thisInstance}
+
+	return thisManager
+}
+
+func getNDF() *ndf.NetworkDefinition {
+	return &ndf.NetworkDefinition{
+		E2E: ndf.Group{
+			Prime: "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B" +
+				"7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE" +
+				"DF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861575E745D31F" +
+				"8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC718DD2A3E041" +
+				"023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FFB1BC51DADDF45" +
+				"3B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBCA23EAC5ACE9209" +
+				"6EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD161C7738F32BF29" +
+				"A841698978825B4111B4BC3E1E198455095958333D776D8B2BEEED3A1A1A221A6E" +
+				"37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F2" +
+				"78DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696" +
+				"015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E" +
+				"6319BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC35873" +
+				"847AEF49F66E43873",
+			Generator: "2",
+		},
+		CMIX: ndf.Group{
+			Prime: "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
+				"C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
+				"FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
+				"B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
+				"35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
+				"F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
+				"92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
+				"3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B",
+			Generator: "5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
+				"D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
+				"6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
+				"085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
+				"AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
+				"3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
+				"BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
+				"DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7",
+		},
+	}
+}
diff --git a/network/ephemeral/tracker.go b/network/ephemeral/tracker.go
new file mode 100644
index 0000000000000000000000000000000000000000..d9b4d029f7b2da3fba18b078e97404c11a66afe9
--- /dev/null
+++ b/network/ephemeral/tracker.go
@@ -0,0 +1,188 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package ephemeral
+
+import (
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/globals"
+	"gitlab.com/elixxir/client/stoppable"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/storage/reception"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
+)
+
+const validityGracePeriod = 5 * time.Minute
+const TimestampKey = "IDTrackingTimestamp"
+const ephemeralStoppable = "EphemeralCheck"
+
+// Track runs a thread which checks for past and present ephemeral ids
+func Track(session *storage.Session, instance *network.Instance, ourId *id.ID) stoppable.Stoppable {
+	stop := stoppable.NewSingle(ephemeralStoppable)
+
+	go track(session, instance, ourId, stop)
+
+	return stop
+}
+
+// track is a thread which continuously processes ephemeral ids.
+// If any error occurs, the thread crashes
+func track(session *storage.Session, instance *network.Instance, ourId *id.ID, stop *stoppable.Single) {
+	identityStore := session.Reception()
+
+	// Check that there is a timestamp in store at all
+	err := checkTimestampStore(session)
+	if err != nil {
+		jww.FATAL.Panicf("Could not store timestamp "+
+			"for ephemeral ID tracking: %v", err)
+	}
+
+	// Get the latest timestamp from store
+	lastTimestampObj, err := session.Get(TimestampKey)
+	if err != nil {
+		globals.Log.FATAL.Panicf("Could not get timestamp: %v", err)
+	}
+
+	lastCheck, err := unmarshalTimestamp(lastTimestampObj)
+	if err != nil {
+		globals.Log.FATAL.Panicf("Could not parse stored timestamp: %v", err)
+	}
+
+	for true {
+		now := time.Now()
+
+		// Generates the IDs since the last track
+		protoIds, err := ephemeral.GetIdsByRange(ourId, session.Reception().GetIDSize(),
+			now.UnixNano(), now.Sub(lastCheck))
+
+		if err != nil {
+			globals.Log.FATAL.Panicf("Could not generate "+
+				"upcoming IDs: %v", err)
+		}
+
+		// Generate identities off of that list
+		identities := generateIdentities(protoIds, ourId)
+
+		// Add identities to storage if unique
+		for _, identity := range identities {
+			// Track if identity has been generated already
+			if identity.StartValid.After(lastCheck) {
+				// If not not, insert identity into store
+				if err = identityStore.AddIdentity(identity); err != nil {
+					globals.Log.FATAL.Panicf("Could not insert "+
+						"identity: %v", err)
+				}
+			}
+
+		}
+
+		// Generate the time stamp for storage
+		vo, err := marshalTimestamp(now)
+		if err != nil {
+			globals.Log.FATAL.Panicf("Could not marshal "+
+				"timestamp for storage: %v", err)
+
+		}
+
+		// Store the timestamp
+		if err = session.Set(TimestampKey, vo); err != nil {
+			globals.Log.FATAL.Panicf("Could not store timestamp: %v", err)
+		}
+
+		// Sleep until the last Id has expired
+		timeToSleep := calculateTickerTime(protoIds)
+		t := time.NewTimer(timeToSleep)
+		select {
+		case <-t.C:
+		case <-stop.Quit():
+			return
+		}
+	}
+}
+
+// generateIdentities is a constructor which generates a list of
+// identities off of the list of protoIdentities passed in
+func generateIdentities(protoIds []ephemeral.ProtoIdentity,
+	ourId *id.ID) []reception.Identity {
+
+	identities := make([]reception.Identity, 0)
+
+	// Add identities for every ephemeral id
+	for _, eid := range protoIds {
+		// Expand the grace period for both start and end
+		eid.End.Add(validityGracePeriod)
+		eid.Start.Add(-validityGracePeriod)
+		identities = append(identities, reception.Identity{
+			EphId:      eid.Id,
+			Source:     ourId,
+			End:        eid.End,
+			StartValid: eid.Start,
+			EndValid:   eid.End,
+			Ephemeral:  false,
+		})
+
+	}
+
+	return identities
+}
+
+// Sanitation check of timestamp store. If a value has not been stored yet
+// then the current time is stored
+func checkTimestampStore(session *storage.Session) error {
+	if _, err := session.Get(TimestampKey); err != nil {
+		now, err := marshalTimestamp(time.Now())
+		if err != nil {
+			return errors.Errorf("Could not marshal new timestamp for storage: %v", err)
+		}
+		return session.Set(TimestampKey, now)
+	}
+
+	return nil
+}
+
+// Takes the stored timestamp and unmarshal into a time object
+func unmarshalTimestamp(lastTimestampObj *versioned.Object) (time.Time, error) {
+	if lastTimestampObj == nil || lastTimestampObj.Data == nil {
+		return time.Now(), nil
+	}
+
+	lastTimestamp := time.Time{}
+	err := lastTimestamp.UnmarshalBinary(lastTimestampObj.Data)
+	return lastTimestamp, err
+}
+
+// Marshals the timestamp for ekv storage. Generates a storable object
+func marshalTimestamp(timeToStore time.Time) (*versioned.Object, error) {
+	data, err := timeToStore.MarshalBinary()
+
+	return &versioned.Object{
+		Version:   0,
+		Timestamp: time.Now(),
+		Data:      data,
+	}, err
+}
+
+// Helper function which calculates the time for the ticker based
+// off of the last ephemeral ID to expire
+func calculateTickerTime(baseIDs []ephemeral.ProtoIdentity) time.Duration {
+	// Get the last identity in the list
+	index := 0
+	if len(baseIDs)-1 > 0 {
+		index = len(baseIDs) - 1
+	}
+	lastIdentity := baseIDs[index]
+
+	// Factor out the grace period previously expanded upon.
+	// Calculate and return that duration
+	gracePeriod := lastIdentity.End.Add(-validityGracePeriod)
+	return lastIdentity.End.Sub(gracePeriod)
+}
diff --git a/network/ephemeral/tracker_test.go b/network/ephemeral/tracker_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..b61d78841afb804fd62be71c0cb786ed382518b2
--- /dev/null
+++ b/network/ephemeral/tracker_test.go
@@ -0,0 +1,149 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package ephemeral
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/interfaces"
+	"gitlab.com/elixxir/client/stoppable"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/comms/testkeys"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/xx_network/comms/signature"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"gitlab.com/xx_network/primitives/utils"
+	"testing"
+	"time"
+)
+
+// Smoke test for Track function
+func TestCheck(t *testing.T) {
+	session := storage.InitTestingSession(t)
+	instance := NewTestNetworkManager(t)
+	if err := setupInstance(instance); err != nil {
+		t.Errorf("Could not set up instance: %v", err)
+	}
+
+	/// Store a mock initial timestamp the store
+	now := time.Now()
+	twoDaysAgo := now.Add(-2 * 24 * time.Hour)
+	twoDaysTimestamp, err := marshalTimestamp(twoDaysAgo)
+	if err != nil {
+		t.Errorf("Could not marshal timestamp for test setup: %v", err)
+	}
+	err = session.Set(TimestampKey, twoDaysTimestamp)
+	if err != nil {
+		t.Errorf("Could not set mock timestamp for test setup: %v", err)
+	}
+
+	ourId := id.NewIdFromBytes([]byte("Sauron"), t)
+	stop := Track(session, instance.GetInstance(), ourId)
+
+	err = stop.Close(3 * time.Second)
+	if err != nil {
+		t.Errorf("Could not close thread: %v", err)
+	}
+
+}
+
+// Unit test for track
+func TestCheck_Thread(t *testing.T) {
+
+	session := storage.InitTestingSession(t)
+	instance := NewTestNetworkManager(t)
+	if err := setupInstance(instance); err != nil {
+		t.Errorf("Could not set up instance: %v", err)
+	}
+	ourId := id.NewIdFromBytes([]byte("Sauron"), t)
+	stop := stoppable.NewSingle(ephemeralStoppable)
+
+	/// Store a mock initial timestamp the store
+	now := time.Now()
+	yesterday := now.Add(-24 * time.Hour)
+	yesterdayTimestamp, err := marshalTimestamp(yesterday)
+	if err != nil {
+		t.Errorf("Could not marshal timestamp for test setup: %v", err)
+	}
+	err = session.Set(TimestampKey, yesterdayTimestamp)
+	if err != nil {
+		t.Errorf("Could not set mock timestamp for test setup: %v", err)
+	}
+
+	// Run the tracker
+	go func() {
+		track(session, instance.GetInstance(), ourId, stop)
+	}()
+
+	time.Sleep(1 * time.Second)
+
+	// Manually generate identities
+
+	eids, err := ephemeral.GetIdsByRange(ourId, 64, now.UnixNano(), now.Sub(yesterday))
+	if err != nil {
+		t.Errorf("Could not generate upcoming ids: %v", err)
+	}
+
+	identities := generateIdentities(eids, ourId)
+
+	rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
+
+	retrieved, err := session.Reception().GetIdentity(rngStreamGen.GetStream())
+	if err != nil {
+		t.Errorf("Could not retrieve identity: %v", err)
+	}
+
+	// Check if store has been updated for new identities
+	if identities[0].String() != retrieved.String() {
+		t.Errorf("Store was not updated for newly generated identies")
+	}
+
+	err = stop.Close(3 * time.Second)
+	if err != nil {
+		t.Errorf("Could not close thread: %v", err)
+	}
+
+}
+
+func setupInstance(instance interfaces.NetworkManager) error {
+	cert, err := utils.ReadFile(testkeys.GetNodeKeyPath())
+	if err != nil {
+		return errors.Errorf("Failed to read cert from from file: %v", err)
+	}
+	ri := &mixmessages.RoundInfo{
+		ID:               1,
+		AddressSpaceSize: 64,
+	}
+
+	testCert, err := rsa.LoadPrivateKeyFromPem(cert)
+	if err != nil {
+		return errors.Errorf("Failed to load cert from from file: %v", err)
+	}
+	if err = signature.Sign(ri, testCert); err != nil {
+		return errors.Errorf("Failed to sign round info: %v", err)
+	}
+	if err = instance.GetInstance().RoundUpdate(ri); err != nil {
+		return errors.Errorf("Failed to RoundUpdate from from file: %v", err)
+	}
+
+	ri = &mixmessages.RoundInfo{
+		ID:               2,
+		AddressSpaceSize: 64,
+	}
+	if err = signature.Sign(ri, testCert); err != nil {
+		return errors.Errorf("Failed to sign round info: %v", err)
+	}
+	if err = instance.GetInstance().RoundUpdate(ri); err != nil {
+		return errors.Errorf("Failed to RoundUpdate from from file: %v", err)
+	}
+
+	return nil
+}
diff --git a/network/follow.go b/network/follow.go
index 2c0d7bc615b1fb8351db09f53d3a5067ff9032af..bad43fe6bff4a923272c0ea6f74e15b55b59de21 100644
--- a/network/follow.go
+++ b/network/follow.go
@@ -25,8 +25,8 @@ package network
 import (
 	"bytes"
 	jww "github.com/spf13/jwalterweatherman"
-	bloom "gitlab.com/elixxir/bloomfilter"
 	"gitlab.com/elixxir/client/network/gateway"
+	"gitlab.com/elixxir/client/network/rounds"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/primitives/knownRounds"
 	"gitlab.com/elixxir/primitives/states"
@@ -36,9 +36,6 @@ import (
 	"time"
 )
 
-const bloomFilterSize = 71888 // In Bits
-const bloomFilterHashes = 8
-
 //comms interface makes testing easier
 type followNetworkComms interface {
 	GetHost(hostId *id.ID) (*connect.Host, bool)
@@ -71,6 +68,13 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 	jww.TRACE.Printf("follow: %d", followCnt)
 	followCnt++
 
+	//get the identity we will poll for
+	identity, err := m.Session.Reception().GetIdentity(rng)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to get an ideneity, this should be "+
+			"impossible: %+v", err)
+	}
+
 	//randomly select a gateway to poll
 	//TODO: make this more intelligent
 	gwHost, err := gateway.Get(m.Instance.GetPartialNdf().Get(), comms, rng)
@@ -84,8 +88,10 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 		Partial: &pb.NDFHash{
 			Hash: m.Instance.GetPartialNdf().GetHash(),
 		},
-		LastUpdate: uint64(m.Instance.GetLastUpdateID()),
-		ClientID:   m.Uid.Bytes(),
+		LastUpdate:     uint64(m.Instance.GetLastUpdateID()),
+		ReceptionID:    identity.EphId[:],
+		StartTimestamp: identity.StartRequest.UnixNano(),
+		EndTimestamp:   identity.EndRequest.UnixNano(),
 	}
 	jww.TRACE.Printf("Polling %s for NDF...", gwHost)
 	pollResp, err := comms.SendPoll(gwHost, &pollReq)
@@ -94,33 +100,13 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 		return
 	}
 
-	// ---- Process Update Data ----
-	lastTrackedRound := id.Round(pollResp.LastTrackedRound)
+	// ---- Process Network State Update Data ----
 	gwRoundsState := &knownRounds.KnownRounds{}
 	err = gwRoundsState.Unmarshal(pollResp.KnownRounds)
 	if err != nil {
 		jww.ERROR.Printf("Failed to unmarshal: %+v", err)
 		return
 	}
-	var filterList []*bloom.Ring
-	for _, f := range pollResp.BloomFilters {
-		jww.DEBUG.Printf("Bloom Filter size: %d, hashes: %d",
-			bloomFilterSize, bloomFilterHashes)
-		filter, err := bloom.InitByParameters(bloomFilterSize,
-			bloomFilterHashes)
-		if err != nil {
-			jww.INFO.Printf("Bloom Filter Data: %v", f)
-			jww.FATAL.Panicf("Unable to create a bloom filter: %+v",
-				err)
-		}
-		if err := filter.UnmarshalBinary(f); err != nil {
-			jww.WARN.Printf("Failed to unmarshal filter: %+v", err)
-			jww.INFO.Printf("Bloom Filter Unmarshal Data: %v", f)
-			continue
-		}
-		filterList = append(filterList, filter)
-	}
-	jww.INFO.Printf("Bloom filters found in response: %d", len(filterList))
 
 	// ---- Node Events ----
 	// NOTE: this updates the structure, AND sends events over the node
@@ -139,6 +125,9 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 		}
 	}
 
+	//check that the stored address space is correct
+	m.Session.Reception().UpdateIdSize(uint(m.Instance.GetPartialNdf().Get().AddressSpaceSize))
+
 	// NOTE: this updates rounds and updates the tracking of the health of the
 	// network
 	if pollResp.Updates != nil {
@@ -187,20 +176,37 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 		}
 	}
 
-	// ---- Round Processing -----
+	// ---- Identity Specific Round Processing -----
+	if identity.Fake {
+		return
+	}
+
+	//get the range fo filters which are valid for the identity
+	filtersStart, filtersEnd := rounds.ValidFilterRange(identity, pollResp.Filters)
+
+	//check if there are any valid filters returned
+	if !(filtersEnd > filtersStart) {
+		return
+	}
+
+	//prepare the filter objects for processing
+	filterList := make([]*rounds.RemoteFilter, filtersEnd-filtersStart)
+	for i := filtersStart; i < filtersEnd; i++ {
+		filterList[i-filtersStart] = rounds.NewRemoteFilter(pollResp.Filters.Filters[i])
+	}
+
+	jww.INFO.Printf("Bloom filters found in response: %d, num filters used: %d",
+		len(pollResp.Filters.Filters), len(filterList))
+
 	// check rounds using the round checker function which determines if there
 	// are messages waiting in rounds and then sends signals to the appropriate
 	// handling threads
 	roundChecker := func(rid id.Round) bool {
-		return m.round.Checker(rid, filterList)
+		return m.round.Checker(rid, filterList, identity)
 	}
 
 	// get the bit vector of rounds that have been checked
 	checkedRounds := m.Session.GetCheckedRounds()
-	// cleave off old state in the bit vector which is deprecated from the
-	// network
-	jww.DEBUG.Printf("lastCheckedRound: %v", lastTrackedRound)
-	checkedRounds.Forward(lastTrackedRound)
 
 	jww.TRACE.Printf("gwRoundState: %+v", gwRoundsState)
 	jww.TRACE.Printf("pollResp.KnownRounds: %s", string(pollResp.KnownRounds))
@@ -208,6 +214,7 @@ func (m *manager) follow(rng csprng.Source, comms followNetworkComms) {
 	// loop through all rounds the client does not know about and the gateway
 	// does, checking the bloom filter for the user to see if there are
 	// messages for the user (bloom not implemented yet)
-	checkedRounds.RangeUncheckedMasked(gwRoundsState, roundChecker,
+	checkedRounds.RangeUncheckedMaskedRange(gwRoundsState, roundChecker,
+		filterList[0].FirstRound(), filterList[len(filterList)-1].LastRound(),
 		int(m.param.MaxCheckedRounds))
 }
diff --git a/network/manager.go b/network/manager.go
index 39718e6d36185e72d5969ff7887ec6d8ff958ff2..592ee108b11fae5408c9f802c11c6874726e719f 100644
--- a/network/manager.go
+++ b/network/manager.go
@@ -7,13 +7,14 @@
 
 package network
 
-// manager.go controls access to network resources. Interprocess communications
+// tracker.go controls access to network resources. Interprocess communications
 // and intraclient state are accessible through the context object.
 
 import (
 	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/interfaces"
 	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/client/network/ephemeral"
 	"gitlab.com/elixxir/client/network/health"
 	"gitlab.com/elixxir/client/network/internal"
 	"gitlab.com/elixxir/client/network/message"
@@ -44,7 +45,6 @@ type manager struct {
 	//sub-managers
 	round   *rounds.Manager
 	message *message.Manager
-
 	//atomic denotes if the network is running
 	running *uint32
 }
@@ -96,6 +96,7 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard,
 //	 - Health Tracker (/network/health)
 //	 - Garbled Messages (/network/message/garbled.go)
 //	 - Critical Messages (/network/message/critical.go)
+//   - Ephemeral ID tracking (network/ephemeral/tracker.go)
 func (m *manager) Follow() (stoppable.Stoppable, error) {
 	if !atomic.CompareAndSwapUint32(m.running, 0, 1) {
 		return nil, errors.Errorf("network routines are already running")
@@ -127,6 +128,8 @@ func (m *manager) Follow() (stoppable.Stoppable, error) {
 	// Round processing
 	multi.Add(m.round.StartProcessors())
 
+	multi.Add(ephemeral.Track(m.Session, m.Instance, m.Comms.Id))
+
 	//set the running status back to 0 so it can be started again
 	closer := stoppable.NewCleanup(multi, func(time.Duration) error {
 		if !atomic.CompareAndSwapUint32(m.running, 1, 0) {
diff --git a/network/message/bundle.go b/network/message/bundle.go
index 84962ded31793e5600eefa1bb425a04cc3a5e881..56f1618d643641da6e9c2550e998a37a1269344c 100644
--- a/network/message/bundle.go
+++ b/network/message/bundle.go
@@ -8,6 +8,7 @@
 package message
 
 import (
+	"gitlab.com/elixxir/client/storage/reception"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 )
@@ -16,4 +17,5 @@ type Bundle struct {
 	Round    id.Round
 	Messages []format.Message
 	Finish   func()
+	Identity reception.IdentityUse
 }
diff --git a/network/message/critical.go b/network/message/critical.go
index e43cee7aa56684fcada1218136fb3549abd7e8ec..cb29ae3f3b19b18c75815f86f3c3c9df326b69d6 100644
--- a/network/message/critical.go
+++ b/network/message/critical.go
@@ -85,7 +85,7 @@ func (m *Manager) criticalMessages() {
 	for msg, has := critRawMsgs.Next(); has; msg, has = critRawMsgs.Next() {
 		go func(msg format.Message) {
 			//send the message
-			round, err := m.SendCMIX(msg, param)
+			round, _, err := m.SendCMIX(msg, m.Uid, param)
 			//if the message fail to send, notify the buffer so it can be handled
 			//in the future and exit
 			if err != nil {
diff --git a/network/message/handler.go b/network/message/handler.go
index 6a3d5bb2ae73e3806316e14f21b2db28a1fad2d2..6ff08e5d78254113fd379f36c2564fa04148ac52 100644
--- a/network/message/handler.go
+++ b/network/message/handler.go
@@ -10,7 +10,9 @@ package message
 import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
+	"gitlab.com/elixxir/client/storage/reception"
 	"gitlab.com/elixxir/crypto/e2e"
+	fingerprint2 "gitlab.com/elixxir/crypto/fingerprint"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
 	"time"
@@ -24,7 +26,7 @@ func (m *Manager) handleMessages(quitCh <-chan struct{}) {
 			done = true
 		case bundle := <-m.messageReception:
 			for _, msg := range bundle.Messages {
-				m.handleMessage(msg)
+				m.handleMessage(msg, bundle.Identity)
 			}
 			bundle.Finish()
 		}
@@ -32,7 +34,7 @@ func (m *Manager) handleMessages(quitCh <-chan struct{}) {
 
 }
 
-func (m *Manager) handleMessage(ecrMsg format.Message) {
+func (m *Manager) handleMessage(ecrMsg format.Message, identity reception.IdentityUse) {
 	// We've done all the networking, now process the message
 	fingerprint := ecrMsg.GetKeyFP()
 
@@ -44,6 +46,15 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 	var err error
 	var relationshipFingerprint []byte
 
+	//check if the identity fingerprint matches
+	forMe, err := fingerprint2.CheckIdentityFP(ecrMsg.GetIdentityFP(), ecrMsg.GetContents(), identity.Source)
+	if err != nil {
+		jww.FATAL.Panicf("Could not check IdentityFIngerprint: %+v", err)
+	}
+	if !forMe {
+		return
+	}
+
 	// try to get the key fingerprint, process as e2e encryption if
 	// the fingerprint is found
 	if key, isE2E := e2eKv.PopKey(fingerprint); isE2E {
@@ -72,12 +83,18 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 		// if it doesnt match any form of encrypted, hear it as a raw message
 		// and add it to garbled messages to be handled later
 		msg = ecrMsg
+		if err != nil {
+			jww.DEBUG.Printf("Failed to unmarshal ephemeral ID "+
+				"on unknown message: %+v", err)
+		}
 		raw := message.Receive{
 			Payload:     msg.Marshal(),
 			MessageType: message.Raw,
-			Sender:      msg.GetRecipientID(),
+			Sender:      nil,
+			EphemeralID: identity.EphId,
 			Timestamp:   time.Time{},
 			Encryption:  message.None,
+			RecipientID: identity.Source,
 		}
 		jww.INFO.Printf("Garbled/RAW Message: %v", msg.GetKeyFP())
 		m.Session.GetGarbledMessages().Add(msg)
@@ -89,6 +106,11 @@ func (m *Manager) handleMessage(ecrMsg format.Message) {
 	// we get a full message
 	xxMsg, ok := m.partitioner.HandlePartition(sender, encTy, msg.GetContents(),
 		relationshipFingerprint)
+
+	//Set the identities
+	xxMsg.RecipientID = identity.Source
+	xxMsg.EphemeralID = identity.EphId
+
 	// If the reception completed a message, hear it on the switchboard
 	if ok {
 		if xxMsg.MessageType == message.Raw {
diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go
index 4addcb7e8998f00301d0c8d9800e6e92b6c37fd8..0dae64e7e44a34da225414f2e5737f053ab20819 100644
--- a/network/message/sendCmix.go
+++ b/network/message/sendCmix.go
@@ -12,19 +12,34 @@ import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/params"
-	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/client/storage"
+	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/elixxir/crypto/fingerprint"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 	"strings"
 	"time"
 )
 
+// interface for sendcmix comms; allows mocking this in testing
+type sendCmixCommsInterface interface {
+	GetHost(hostId *id.ID) (*connect.Host, bool)
+	SendPutMessage(host *connect.Host, message *pb.GatewaySlot) (*pb.GatewaySlotResponse, error)
+}
+
 const sendTimeBuffer = uint64(100 * time.Millisecond)
 
 // WARNING: Potentially Unsafe
+// Public manager function to send a message over CMIX
+func (m *Manager) SendCMIX(msg format.Message, recipient *id.ID, param params.CMIX) (id.Round, ephemeral.Id, error) {
+	return sendCmixHelper(msg, recipient, param, m.Instance, m.Session, m.nodeRegistration, m.Rng, m.Uid, m.Comms)
+}
+
 // Payloads send are not End to End encrypted, MetaData is NOT protected with
 // this call, see SendE2E for End to End encryption and full privacy protection
 // Internal SendCmix which bypasses the network check, will attempt to send to
@@ -33,21 +48,24 @@ const sendTimeBuffer = uint64(100 * time.Millisecond)
 // If the message is successfully sent, the id of the round sent it is returned,
 // which can be registered with the network instance to get a callback on
 // its status
-func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, error) {
+func sendCmixHelper(msg format.Message, recipient *id.ID, param params.CMIX, instance *network.Instance,
+	session *storage.Session, nodeRegistration chan network.NodeGateway, rng *fastRNG.StreamGenerator, senderId *id.ID,
+	comms sendCmixCommsInterface) (id.Round, ephemeral.Id, error) {
 
 	timeStart := time.Now()
 	attempted := set.New()
 
 	for numRoundTries := uint(0); numRoundTries < param.RoundTries; numRoundTries++ {
 		elapsed := time.Now().Sub(timeStart)
+
 		jww.DEBUG.Printf("SendCMIX Send Attempt %d", numRoundTries+1)
 		if elapsed > param.Timeout {
-			return 0, errors.New("Sending cmix message timed out")
+			return 0, ephemeral.Id{}, errors.New("Sending cmix message timed out")
 		}
 		remainingTime := param.Timeout - elapsed
 		jww.TRACE.Printf("SendCMIX GetUpcommingRealtime")
 		//find the best round to send to, excluding attempted rounds
-		bestRound, _ := m.Instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted)
+		bestRound, _ := instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted)
 		if bestRound == nil {
 			continue
 		}
@@ -59,6 +77,32 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 			continue
 		}
 
+		//set the ephemeral ID
+		ephID, _, _, err := ephemeral.GetId(recipient,
+			uint(bestRound.AddressSpaceSize),
+			int64(bestRound.Timestamps[states.REALTIME]))
+		if err != nil {
+			jww.FATAL.Panicf("Failed to generate ephemeral ID: %+v", err)
+		}
+
+		stream := rng.GetStream()
+		ephID, err = ephID.Fill(uint(bestRound.AddressSpaceSize), stream)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to obviscate the ephemeralID: %+v", err)
+		}
+		stream.Close()
+
+		msg.SetEphemeralRID(ephID[:])
+
+		//set the identity fingerprint
+		ifp, err := fingerprint.IdentityFP(msg.GetContents(), recipient)
+		if err != nil {
+			jww.FATAL.Panicf("failed to generate the Identity "+
+				"fingerprint due to unrecoverable error: %+v", err)
+		}
+
+		msg.SetIdentityFP(ifp)
+
 		//build the topology
 		idList, err := id.NewIDListFromBytes(bestRound.Topology)
 		if err != nil {
@@ -69,9 +113,9 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 		jww.TRACE.Printf("SendCMIX GetRoundKeys")
 		//get they keys for the round, reject if any nodes do not have
 		//keying relationships
-		roundKeys, missingKeys := m.Session.Cmix().GetRoundKeys(topology)
+		roundKeys, missingKeys := session.Cmix().GetRoundKeys(topology)
 		if len(missingKeys) > 0 {
-			go handleMissingNodeKeys(m.Instance, m.nodeRegistration, missingKeys)
+			go handleMissingNodeKeys(instance, nodeRegistration, missingKeys)
 			time.Sleep(param.RetryDelay)
 			continue
 		}
@@ -80,7 +124,7 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 		firstGateway := topology.GetNodeAtIndex(0).DeepCopy()
 		firstGateway.SetType(id.Gateway)
 
-		transmitGateway, ok := m.Comms.GetHost(firstGateway)
+		transmitGateway, ok := comms.GetHost(firstGateway)
 		if !ok {
 			jww.ERROR.Printf("Failed to get host for gateway %s", transmitGateway)
 			time.Sleep(param.RetryDelay)
@@ -88,21 +132,21 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 		}
 
 		//encrypt the message
+		stream = rng.GetStream()
 		salt := make([]byte, 32)
-		stream := m.Rng.GetStream()
 		_, err = stream.Read(salt)
 		stream.Close()
 
 		if err != nil {
-			return 0, errors.WithMessage(err, "Failed to generate "+
-				"salt, this should never happen")
+			return 0, ephemeral.Id{}, errors.WithMessage(err,
+				"Failed to generate salt, this should never happen")
 		}
-		jww.INFO.Printf("RECIPIENTIDPRE_ENCRYPT: %s", msg.GetRecipientID())
+
 		encMsg, kmacs := roundKeys.Encrypt(msg, salt)
 
 		//build the message payload
-		msgPacket := &mixmessages.Slot{
-			SenderID: m.Uid.Bytes(),
+		msgPacket := &pb.Slot{
+			SenderID: senderId.Bytes(),
 			PayloadA: encMsg.GetPayloadA(),
 			PayloadB: encMsg.GetPayloadB(),
 			Salt:     salt,
@@ -110,18 +154,20 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 		}
 
 		//create the wrapper to the gateway
-		msg := &mixmessages.GatewaySlot{
+		wrappedMsg := &pb.GatewaySlot{
 			Message: msgPacket,
 			RoundID: bestRound.ID,
 		}
 		//Add the mac proving ownership
-		msg.MAC = roundKeys.MakeClientGatewayKey(salt, network.GenerateSlotDigest(msg))
+		wrappedMsg.MAC = roundKeys.MakeClientGatewayKey(salt,
+			network.GenerateSlotDigest(wrappedMsg))
 
 		//add the round on to the list of attempted so it is not tried again
 		attempted.Insert(bestRound)
+
 		jww.DEBUG.Printf("SendCMIX SendPutMessage")
 		//Send the payload
-		gwSlotResp, err := m.Comms.SendPutMessage(transmitGateway, msg)
+		gwSlotResp, err := comms.SendPutMessage(transmitGateway, wrappedMsg)
 		//if the comm errors or the message fails to send, continue retrying.
 		//return if it sends properly
 		if err != nil {
@@ -134,15 +180,14 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err
 			jww.ERROR.Printf("Failed to send message to %s: %s",
 				transmitGateway, err)
 		} else if gwSlotResp.Accepted {
-			return id.Round(bestRound.ID), nil
+			return id.Round(bestRound.ID), ephID, nil
 		}
 	}
-
-	return 0, errors.New("failed to send the message")
+	return 0, ephemeral.Id{}, errors.New("failed to send the message")
 }
 
 // Signals to the node registration thread to register a node if keys are
-// missing. Registration is triggered automatically when the node is first seen,
+// missing. Identity is triggered automatically when the node is first seen,
 // so this should on trigger on rare events.
 func handleMissingNodeKeys(instance *network.Instance,
 	newNodeChan chan network.NodeGateway, nodes []*id.ID) {
diff --git a/network/message/sendCmix_test.go b/network/message/sendCmix_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a623c77fa03842a62b3dddfb20a18b236bcceb22
--- /dev/null
+++ b/network/message/sendCmix_test.go
@@ -0,0 +1,150 @@
+package message
+
+import (
+	"gitlab.com/elixxir/client/interfaces/message"
+	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/client/network/internal"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/switchboard"
+	"gitlab.com/elixxir/comms/client"
+	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/comms/network"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/e2e"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/elixxir/primitives/states"
+	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/large"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/ndf"
+	"testing"
+	"time"
+)
+
+type MockSendCMIXComms struct {
+	t *testing.T
+}
+
+func (mc *MockSendCMIXComms) GetHost(hostId *id.ID) (*connect.Host, bool) {
+	nid1 := id.NewIdFromString("zezima", id.Node, mc.t)
+	gwid := nid1.DeepCopy()
+	gwid.SetType(id.Gateway)
+	h, _ := connect.NewHost(gwid, "0.0.0.0", []byte(""), connect.HostParams{
+		MaxRetries:  0,
+		AuthEnabled: false,
+	})
+	return h, true
+}
+func (mc *MockSendCMIXComms) SendPutMessage(host *connect.Host, message *mixmessages.GatewaySlot) (*mixmessages.GatewaySlotResponse, error) {
+	return &mixmessages.GatewaySlotResponse{
+		Accepted: true,
+		RoundID:  3,
+	}, nil
+}
+
+func Test_attemptSendCmix(t *testing.T) {
+	sess1 := storage.InitTestingSession(t)
+
+	sess2 := storage.InitTestingSession(t)
+
+	sw := switchboard.New()
+	l := TestListener{
+		ch: make(chan bool),
+	}
+	sw.RegisterListener(sess2.GetUser().TransmissionID, message.Raw, l)
+	comms, err := client.NewClientComms(sess1.GetUser().TransmissionID, nil, nil, nil)
+	if err != nil {
+		t.Errorf("Failed to start client comms: %+v", err)
+	}
+	inst, err := network.NewInstanceTesting(comms.ProtoComms, getNDF(), nil, nil, nil, t)
+	if err != nil {
+		t.Errorf("Failed to start instance: %+v", err)
+	}
+	now := uint64(time.Now().UnixNano())
+	nid1 := id.NewIdFromString("zezima", id.Node, t)
+	nid2 := id.NewIdFromString("jakexx360", id.Node, t)
+	nid3 := id.NewIdFromString("westparkhome", id.Node, t)
+	grp := cyclic.NewGroup(large.NewInt(7), large.NewInt(13))
+	sess1.Cmix().Add(nid1, grp.NewInt(1))
+	sess1.Cmix().Add(nid2, grp.NewInt(2))
+	sess1.Cmix().Add(nid3, grp.NewInt(3))
+	inst.GetWaitingRounds().Insert(&mixmessages.RoundInfo{
+		ID:                         3,
+		UpdateID:                   0,
+		State:                      uint32(states.QUEUED),
+		BatchSize:                  0,
+		Topology:                   [][]byte{nid1.Marshal(), nid2.Marshal(), nid3.Marshal()},
+		Timestamps:                 []uint64{now - 30, now - 15, now, now + 15, 0},
+		Errors:                     nil,
+		ClientErrors:               nil,
+		ResourceQueueTimeoutMillis: 0,
+		Signature:                  nil,
+		AddressSpaceSize:           0,
+	})
+	i := internal.Internal{
+		Session:          sess1,
+		Switchboard:      sw,
+		Rng:              fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG),
+		Comms:            comms,
+		Health:           nil,
+		Uid:              sess1.GetUser().TransmissionID,
+		Instance:         inst,
+		NodeRegistration: nil,
+	}
+	m := NewManager(i, params.Messages{
+		MessageReceptionBuffLen:        20,
+		MessageReceptionWorkerPoolSize: 20,
+		MaxChecksGarbledMessage:        20,
+		GarbledMessageWait:             time.Hour,
+	}, nil)
+	msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen())
+	msgCmix.SetContents([]byte("test"))
+	e2e.SetUnencrypted(msgCmix, m.Session.User().GetCryptographicIdentity().GetTransmissionID())
+	_, _, err = sendCmixHelper(msgCmix, sess2.GetUser().ReceptionID, params.GetDefaultCMIX(),
+		m.Instance, m.Session, m.nodeRegistration, m.Rng,
+		m.Uid, &MockSendCMIXComms{t: t})
+	if err != nil {
+		t.Errorf("Failed to sendcmix: %+v", err)
+	}
+}
+
+func getNDF() *ndf.NetworkDefinition {
+	return &ndf.NetworkDefinition{
+		E2E: ndf.Group{
+			Prime: "E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B" +
+				"7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE" +
+				"DF6C01C94764DAB937935AA83BE36E67760713AB44A6337C20E7861575E745D31F" +
+				"8B9E9AD8412118C62A3E2E29DF46B0864D0C951C394A5CBBDC6ADC718DD2A3E041" +
+				"023DBB5AB23EBB4742DE9C1687B5B34FA48C3521632C4A530E8FFB1BC51DADDF45" +
+				"3B0B2717C2BC6669ED76B4BDD5C9FF558E88F26E5785302BEDBCA23EAC5ACE9209" +
+				"6EE8A60642FB61E8F3D24990B8CB12EE448EEF78E184C7242DD161C7738F32BF29" +
+				"A841698978825B4111B4BC3E1E198455095958333D776D8B2BEEED3A1A1A221A6E" +
+				"37E664A64B83981C46FFDDC1A45E3D5211AAF8BFBC072768C4F50D7D7803D2D4F2" +
+				"78DE8014A47323631D7E064DE81C0C6BFA43EF0E6998860F1390B5D3FEACAF1696" +
+				"015CB79C3F9C2D93D961120CD0E5F12CBB687EAB045241F96789C38E89D796138E" +
+				"6319BE62E35D87B1048CA28BE389B575E994DCA755471584A09EC723742DC35873" +
+				"847AEF49F66E43873",
+			Generator: "2",
+		},
+		CMIX: ndf.Group{
+			Prime: "9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
+				"C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
+				"FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
+				"B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
+				"35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
+				"F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
+				"92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
+				"3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B",
+			Generator: "5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
+				"D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
+				"6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
+				"085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
+				"AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
+				"3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
+				"BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
+				"DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7",
+		},
+	}
+}
diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go
index 04e24e8e435d7871c6512b0a90abb329c2efa101..fbb2e910f399a249060eac085d5a8c0f393cad3e 100644
--- a/network/message/sendE2E.go
+++ b/network/message/sendE2E.go
@@ -51,7 +51,6 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M
 		//create the cmix message
 		msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen())
 		msgCmix.SetContents(p)
-		msgCmix.SetRecipientID(msg.Recipient)
 
 		//get a key to end to end encrypt
 		key, err := partner.GetKeyForSending(param.Type)
@@ -67,7 +66,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, e2e.M
 		wg.Add(1)
 		go func(i int) {
 			var err error
-			roundIds[i], err = m.SendCMIX(msgEnc, param.CMIX)
+			roundIds[i], _, err = m.SendCMIX(msgEnc, msg.Recipient, param.CMIX)
 			if err != nil {
 				errCh <- err
 			}
diff --git a/network/message/sendUnsafe.go b/network/message/sendUnsafe.go
index 8975309dc25b884b35b599c56f88ce53e9fadcea..956a50f544c5524fe6820f9d3429c1af93b48639 100644
--- a/network/message/sendUnsafe.go
+++ b/network/message/sendUnsafe.go
@@ -51,12 +51,11 @@ func (m *Manager) SendUnsafe(msg message.Send, param params.Unsafe) ([]id.Round,
 	for i, p := range partitions {
 		msgCmix := format.NewMessage(m.Session.Cmix().GetGroup().GetP().ByteLen())
 		msgCmix.SetContents(p)
-		msgCmix.SetRecipientID(msg.Recipient)
 		e2e.SetUnencrypted(msgCmix, m.Session.User().GetCryptographicIdentity().GetTransmissionID())
 		wg.Add(1)
 		go func(i int) {
 			var err error
-			roundIds[i], err = m.SendCMIX(msgCmix, param.CMIX)
+			roundIds[i], _, err = m.SendCMIX(msgCmix, msg.Recipient, param.CMIX)
 			if err != nil {
 				errCh <- err
 			}
diff --git a/network/rounds/check.go b/network/rounds/check.go
index 72d31bed5d1840f6d2b5f7b00f8b24607a7963a8..b84676f5bf91ce8cbc24211310225ddf8dd730d0 100644
--- a/network/rounds/check.go
+++ b/network/rounds/check.go
@@ -11,6 +11,7 @@ import (
 	"encoding/binary"
 	jww "github.com/spf13/jwalterweatherman"
 	bloom "gitlab.com/elixxir/bloomfilter"
+	"gitlab.com/elixxir/client/storage/reception"
 	"gitlab.com/xx_network/primitives/id"
 )
 
@@ -25,7 +26,7 @@ import (
 // if the information about that round is already present, if it is the data is
 // sent to Message Retrieval Workers, otherwise it is sent to Historical Round
 // Retrieval
-func (m *Manager) Checker(roundID id.Round, filters []*bloom.Ring) bool {
+func (m *Manager) Checker(roundID id.Round, filters []*RemoteFilter, identity reception.IdentityUse) bool {
 	jww.DEBUG.Printf("Checker(roundID: %d)", roundID)
 	// Set round to processing, if we can
 	processing, count := m.p.Process(roundID)
@@ -43,14 +44,24 @@ func (m *Manager) Checker(roundID id.Round, filters []*bloom.Ring) bool {
 		return true
 	}
 
-	//check if the round is in the bloom filters
-	hasRound := false
-	serialRid := serializeRound(roundID)
+	//find filters that could have the round
+	var potentialFilters []*bloom.Bloom
 
 	for _, filter := range filters {
-		hasRound = filter.Test(serialRid)
-		if hasRound {
-			break
+		if filter.FirstRound() <= roundID && filter.LastRound() >= roundID {
+			potentialFilters = append(potentialFilters, filter.GetFilter())
+		}
+	}
+
+	hasRound := false
+	//check if the round is in any of the potential filters
+	if len(potentialFilters) > 0 {
+		serialRid := serializeRound(roundID)
+		for _, f := range potentialFilters {
+			if f.Test(serialRid) {
+				hasRound = true
+				break
+			}
 		}
 	}
 
@@ -66,11 +77,17 @@ func (m *Manager) Checker(roundID id.Round, filters []*bloom.Ring) bool {
 	if err != nil {
 		jww.DEBUG.Printf("HistoricalRound <- %d", roundID)
 		// If we didn't find it, send to Historical Rounds Retrieval
-		m.historicalRounds <- roundID
+		m.historicalRounds <- historicalRoundRequest{
+			rid:      roundID,
+			identity: identity,
+		}
 	} else {
 		jww.DEBUG.Printf("lookupRoundMessages <- %d", roundID)
 		// IF found, send to Message Retrieval Workers
-		m.lookupRoundMessages <- ri
+		m.lookupRoundMessages <- roundLookup{
+			roundInfo: ri,
+			identity:  identity,
+		}
 	}
 
 	return false
diff --git a/network/rounds/historical.go b/network/rounds/historical.go
index 6b8fd8a53b2101b47b817bc3ec0341a1986ca9ef..5d5868028477e2a3c8f5dc61fb12193a51a474f1 100644
--- a/network/rounds/historical.go
+++ b/network/rounds/historical.go
@@ -10,6 +10,7 @@ package rounds
 import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/network/gateway"
+	"gitlab.com/elixxir/client/storage/reception"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/primitives/id"
@@ -31,6 +32,12 @@ type historicalRoundsComms interface {
 		message *pb.HistoricalRounds) (*pb.HistoricalRoundsResponse, error)
 }
 
+//structure which contains a historical round lookup
+type historicalRoundRequest struct {
+	rid      id.Round
+	identity reception.IdentityUse
+}
+
 // Long running thread which process historical rounds
 // Can be killed by sending a signal to the quit channel
 // takes a comms interface to aid in testing
@@ -39,7 +46,7 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c
 	timerCh := make(<-chan time.Time)
 
 	rng := m.Rng.GetStream()
-	var rounds []uint64
+	var roundRequests []historicalRoundRequest
 
 	done := false
 	for !done {
@@ -48,28 +55,28 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c
 		select {
 		case <-quitCh:
 			rng.Close()
-			// return all rounds in the queue to the input channel so they can
+			// return all roundRequests in the queue to the input channel so they can
 			// be checked in the future. If the queue is full, disable them as
 			// processing so they are picked up from the beginning
-			for _, rid := range rounds {
+			for _, r := range roundRequests {
 				select {
-				case m.historicalRounds <- id.Round(rid):
+				case m.historicalRounds <- r:
 				default:
-					m.p.NotProcessing(id.Round(rid))
+					m.p.NotProcessing(r.rid)
 				}
 			}
 			done = true
-		// if the timer elapses process rounds to ensure the delay isn't too long
+		// if the timer elapses process roundRequests to ensure the delay isn't too long
 		case <-timerCh:
-			if len(rounds) > 0 {
+			if len(roundRequests) > 0 {
 				shouldProcess = true
 			}
 		// get new round to lookup and force a lookup if
-		case rid := <-m.historicalRounds:
-			rounds = append(rounds, uint64(rid))
-			if len(rounds) > int(m.params.MaxHistoricalRounds) {
+		case r := <-m.historicalRounds:
+			roundRequests = append(roundRequests, r)
+			if len(roundRequests) > int(m.params.MaxHistoricalRounds) {
 				shouldProcess = true
-			} else if len(rounds) == 1 {
+			} else if len(roundRequests) == 1 {
 				//if this is the first round, start the timeout
 				timerCh = time.NewTimer(m.params.HistoricalRoundsPeriod).C
 			}
@@ -78,21 +85,26 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c
 			continue
 		}
 
-		//find a gateway to request about the rounds
+		//find a gateway to request about the roundRequests
 		gwHost, err := gateway.Get(m.Instance.GetPartialNdf().Get(), comm, rng)
 		if err != nil {
 			jww.FATAL.Panicf("Failed to track network, NDF has corrupt "+
 				"data: %s", err)
 		}
 
-		//send the historical rounds request
+		rounds := make([]uint64, len(roundRequests))
+		for i, rr := range roundRequests {
+			rounds[i] = uint64(rr.rid)
+		}
+
+		//send the historical roundRequests request
 		hr := &pb.HistoricalRounds{
 			Rounds: rounds,
 		}
 
 		response, err := comm.RequestHistoricalRounds(gwHost, hr)
 		if err != nil {
-			jww.ERROR.Printf("Failed to request historical rounds "+
+			jww.ERROR.Printf("Failed to request historical roundRequests "+
 				"data: %s", response)
 			// if the check fails to resolve, break the loop and so they will be
 			// checked again
@@ -100,20 +112,24 @@ func (m *Manager) processHistoricalRounds(comm historicalRoundsComms, quitCh <-c
 			continue
 		}
 
-		// process the returned historical rounds.
+		// process the returned historical roundRequests.
 		for i, roundInfo := range response.Rounds {
-			// The interface has missing returns returned as nil, such rounds
+			// The interface has missing returns returned as nil, such roundRequests
 			// need be be removes as processing so the network follower will
 			// pick them up in the future.
 			if roundInfo == nil {
 				jww.ERROR.Printf("could not retreive "+
-					"historical round %d", rounds[i])
-				m.p.Fail(id.Round(rounds[i]))
+					"historical round %d", roundRequests[i].rid)
+				m.p.Fail(roundRequests[i].rid)
 				continue
 			}
-			// Successfully retrieved rounds are sent to the Message
+			// Successfully retrieved roundRequests are sent to the Message
 			// Retrieval Workers
-			m.lookupRoundMessages <- roundInfo
+			rl := roundLookup{
+				roundInfo: roundInfo,
+				identity:  roundRequests[i].identity,
+			}
+			m.lookupRoundMessages <- rl
 		}
 	}
 }
diff --git a/network/rounds/manager.go b/network/rounds/manager.go
index 3c3221474d3124b9de4ab1e688c7eeda118e8a52..9fe5ce57a34f342aaf1fb2b1055442e08f802d0a 100644
--- a/network/rounds/manager.go
+++ b/network/rounds/manager.go
@@ -13,8 +13,6 @@ import (
 	"gitlab.com/elixxir/client/network/internal"
 	"gitlab.com/elixxir/client/network/message"
 	"gitlab.com/elixxir/client/stoppable"
-	"gitlab.com/elixxir/comms/mixmessages"
-	"gitlab.com/xx_network/primitives/id"
 )
 
 type Manager struct {
@@ -24,8 +22,8 @@ type Manager struct {
 
 	internal.Internal
 
-	historicalRounds    chan id.Round
-	lookupRoundMessages chan *mixmessages.RoundInfo
+	historicalRounds    chan historicalRoundRequest
+	lookupRoundMessages chan roundLookup
 	messageBundles      chan<- message.Bundle
 }
 
@@ -35,8 +33,8 @@ func NewManager(internal internal.Internal, params params.Rounds,
 		params: params,
 		p:      newProcessingRounds(),
 
-		historicalRounds:    make(chan id.Round, params.HistoricalRoundsBufferLen),
-		lookupRoundMessages: make(chan *mixmessages.RoundInfo, params.LookupRoundsBufferLen),
+		historicalRounds:    make(chan historicalRoundRequest, params.HistoricalRoundsBufferLen),
+		lookupRoundMessages: make(chan roundLookup, params.LookupRoundsBufferLen),
 		messageBundles:      bundles,
 	}
 
diff --git a/network/rounds/remoteFilters.go b/network/rounds/remoteFilters.go
new file mode 100644
index 0000000000000000000000000000000000000000..3209a8261008dde0004319198d80e43e823b73c4
--- /dev/null
+++ b/network/rounds/remoteFilters.go
@@ -0,0 +1,55 @@
+package rounds
+
+import (
+	bloom "gitlab.com/elixxir/bloomfilter"
+	"gitlab.com/elixxir/client/interfaces"
+	"gitlab.com/elixxir/client/storage/reception"
+	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/xx_network/primitives/id"
+	"time"
+)
+
+func NewRemoteFilter(data *mixmessages.ClientBloom) *RemoteFilter {
+	return &RemoteFilter{
+		data: data,
+	}
+}
+
+type RemoteFilter struct {
+	data   *mixmessages.ClientBloom
+	filter *bloom.Bloom
+}
+
+func (rf *RemoteFilter) GetFilter() *bloom.Bloom {
+
+	if rf.filter == nil {
+		var err error
+		rf.filter, err = bloom.InitByParameters(interfaces.BloomFilterSize,
+			interfaces.BloomFilterHashes)
+		if err != nil {
+			return nil
+		}
+	}
+	return rf.filter
+}
+
+func (rf *RemoteFilter) FirstRound() id.Round {
+	return id.Round(rf.data.FirstRound)
+}
+
+func (rf *RemoteFilter) LastRound() id.Round {
+	return id.Round(rf.data.FirstRound + uint64(rf.data.RoundRange))
+}
+
+// ValidFilterRange calculates which of the returned filters are valid for the identity
+func ValidFilterRange(identity reception.IdentityUse, filters *mixmessages.ClientBlooms) (start int, end int) {
+	firstFilterStart := time.Unix(0, filters.FirstTimestamp)
+	filterDelta := time.Duration(filters.Period)
+
+	deltaFromStart := int(identity.StartValid.Sub(firstFilterStart) / filterDelta)
+	deltaFromEnd := int((identity.EndValid.Sub(firstFilterStart) + filterDelta - 1) / filterDelta)
+	if deltaFromEnd > (len(filters.Filters) - 1) {
+		deltaFromEnd = len(filters.Filters)
+	}
+	return deltaFromStart, deltaFromEnd + 1
+}
diff --git a/network/rounds/retrieve.go b/network/rounds/retrieve.go
index 0762c3a197061273993e5a57ff056f6c041d51f0..05a03821118b95e7c34f984b24b4601ca9bb697c 100644
--- a/network/rounds/retrieve.go
+++ b/network/rounds/retrieve.go
@@ -12,6 +12,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/network/gateway"
 	"gitlab.com/elixxir/client/network/message"
+	"gitlab.com/elixxir/client/storage/reception"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/comms/connect"
@@ -24,6 +25,11 @@ type messageRetrievalComms interface {
 		message *pb.GetMessages) (*pb.GetMessagesResponse, error)
 }
 
+type roundLookup struct {
+	roundInfo *pb.RoundInfo
+	identity  reception.IdentityUse
+}
+
 func (m *Manager) processMessageRetrieval(comms messageRetrievalComms,
 	quitCh <-chan struct{}) {
 
@@ -32,13 +38,15 @@ func (m *Manager) processMessageRetrieval(comms messageRetrievalComms,
 		select {
 		case <-quitCh:
 			done = true
-		case ri := <-m.lookupRoundMessages:
+		case rl := <-m.lookupRoundMessages:
+			ri := rl.roundInfo
 			bundle, err := m.getMessagesFromGateway(ri, comms)
 			if err != nil {
 				jww.WARN.Printf("Failed to get messages for round %v: %s",
 					ri.ID, err)
 				break
 			}
+			bundle.Identity = rl.identity
 			if len(bundle.Messages) != 0 {
 				m.messageBundles <- bundle
 			}
diff --git a/network/send.go b/network/send.go
index cd3d13da43cd97ab8a610dd05e12e7776645dd49..0e3e9020aa187716e3a7dd7da9f538bff47ba3e9 100644
--- a/network/send.go
+++ b/network/send.go
@@ -15,19 +15,20 @@ import (
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 )
 
 // SendCMIX sends a "raw" CMIX message payload to the provided
 // recipient. Note that both SendE2E and SendUnsafe call SendCMIX.
 // Returns the round ID of the round the payload was sent or an error
 // if it fails.
-func (m *manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, error) {
+func (m *manager) SendCMIX(msg format.Message, recipient *id.ID, param params.CMIX) (id.Round, ephemeral.Id, error) {
 	if !m.Health.IsHealthy() {
-		return 0, errors.New("Cannot send cmix message when the " +
+		return 0, ephemeral.Id{}, errors.New("Cannot send cmix message when the " +
 			"network is not healthy")
 	}
 
-	return m.message.SendCMIX(msg, param)
+	return m.message.SendCMIX(msg, recipient, param)
 }
 
 // SendUnsafe sends an unencrypted payload to the provided recipient
diff --git a/permissioning/register.go b/permissioning/register.go
index f013fbd94f4e4f5af599689b07a410c02453d3dc..1a64e54798560b270ab0d62267f7b2704a2c8ae1 100644
--- a/permissioning/register.go
+++ b/permissioning/register.go
@@ -36,7 +36,7 @@ func register(comms registrationMessageSender, host *connect.Host,
 				ClientReceptionRSAPubKey: string(rsa.CreatePublicKeyPem(receptionPublicKey)),
 			})
 	if err != nil {
-		err = errors.Wrap(err, "sendRegistrationMessage: Unable to contact Registration Server!")
+		err = errors.Wrap(err, "sendRegistrationMessage: Unable to contact Identity Server!")
 		return nil, nil, err
 	}
 	if response.Error != "" {
diff --git a/storage/e2e/session.go b/storage/e2e/session.go
index bcea1ff782e45d742dd1a7429e7df4f9a90983f6..1fd729e013a093eb706ec7cc8de220255cb9167c 100644
--- a/storage/e2e/session.go
+++ b/storage/e2e/session.go
@@ -16,9 +16,10 @@ import (
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
 	dh "gitlab.com/elixxir/crypto/diffieHellman"
-	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/crypto/hash"
+	"gitlab.com/xx_network/crypto/randomness"
 	"gitlab.com/xx_network/primitives/id"
+	"math/big"
 	"sync"
 	"testing"
 	"time"
@@ -547,15 +548,12 @@ func (s *Session) generate(kv *versioned.KV) *versioned.KV {
 	kv = kv.Prefix(makeSessionPrefix(s.GetID()))
 
 	//generate ttl and keying info
-	keysTTL, numKeys := e2e.GenerateKeyTTL(s.baseKey.GetLargeInt(),
-		s.params.MinKeys, s.params.MaxKeys, s.params.TTLParams)
+	h, _ := hash.NewCMixHash()
 
-	//ensure that enough keys are remaining to rekey
-	if numKeys-uint32(keysTTL) < uint32(s.params.NumRekeys) {
-		numKeys = uint32(keysTTL + s.params.NumRekeys)
-	}
+	numKeys := uint32(randomness.RandInInterval(big.NewInt(int64(s.params.MaxKeys-s.params.MinKeys)),
+		s.baseKey.Bytes(), h).Int64() + int64(s.params.MinKeys))
 
-	s.ttl = uint32(keysTTL)
+	s.ttl = uint32(s.params.NumRekeys)
 
 	//create the new state vectors. This will cause disk operations storing them
 
diff --git a/storage/reception/IdentityUse.go b/storage/reception/IdentityUse.go
new file mode 100644
index 0000000000000000000000000000000000000000..4bbbc4ee4b7f9819b75aaf3efa093ddfb8f2a032
--- /dev/null
+++ b/storage/reception/IdentityUse.go
@@ -0,0 +1,61 @@
+package reception
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/crypto/hash"
+	"gitlab.com/elixxir/primitives/knownRounds"
+	"gitlab.com/xx_network/crypto/randomness"
+	"gitlab.com/xx_network/primitives/id"
+	"io"
+	"math/big"
+	"time"
+)
+
+type IdentityUse struct {
+	Identity
+
+	// Randomly generated time to poll between
+	StartRequest time.Time // Timestamp to request the start of bloom filters
+	EndRequest   time.Time // Timestamp to request the End of bloom filters
+
+	// Denotes if the identity is fake, in which case we do not process messages
+	Fake bool
+
+	// rounds data
+	KR KnownRounds
+}
+
+// setSamplingPeriod add the Request mask as a random buffer around the sampling
+// time to obfuscate it.
+func (iu IdentityUse) setSamplingPeriod(rng io.Reader) (IdentityUse, error) {
+
+	// Generate the seed
+	seed := make([]byte, 32)
+	if _, err := rng.Read(seed); err != nil {
+		return IdentityUse{}, errors.WithMessage(err, "Failed to choose ID "+
+			"due to rng failure")
+	}
+
+	h, err := hash.NewCMixHash()
+	if err != nil {
+		return IdentityUse{}, err
+	}
+
+	// Calculate the period offset
+	periodOffset := randomness.RandInInterval(
+		big.NewInt(iu.RequestMask.Nanoseconds()), seed, h).Int64()
+	iu.StartRequest = iu.StartValid.Add(-time.Duration(periodOffset))
+	iu.EndRequest = iu.EndValid.Add(iu.RequestMask - time.Duration(periodOffset))
+	return iu, nil
+}
+
+type KnownRounds interface {
+	Checked(rid id.Round) bool
+	Check(rid id.Round)
+	Forward(rid id.Round)
+	RangeUnchecked(newestRid id.Round, roundCheck func(id id.Round) bool)
+	RangeUncheckedMasked(mask *knownRounds.KnownRounds,
+		roundCheck knownRounds.RoundCheckFunc, maxChecked int)
+	RangeUncheckedMaskedRange(mask *knownRounds.KnownRounds,
+		roundCheck knownRounds.RoundCheckFunc, start, end id.Round, maxChecked int)
+}
diff --git a/storage/reception/fake.go b/storage/reception/fake.go
new file mode 100644
index 0000000000000000000000000000000000000000..38cb63a241cc25122b98ff8b5a1762da0f3994a5
--- /dev/null
+++ b/storage/reception/fake.go
@@ -0,0 +1,45 @@
+package reception
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"io"
+	"time"
+)
+
+// generateFakeIdentity generates a fake identity of the given size with the
+// given random number generator
+func generateFakeIdentity(rng io.Reader, idSize uint, now time.Time) (IdentityUse, error) {
+	// Randomly generate an identity
+	randIdBytes := make([]byte, id.ArrIDLen-1)
+	if _, err := rng.Read(randIdBytes); err != nil {
+		return IdentityUse{}, errors.WithMessage(err, "failed to "+
+			"generate a random identity when none is available")
+	}
+
+	randID := &id.ID{}
+	copy(randID[:id.ArrIDLen-1], randIdBytes)
+	randID.SetType(id.User)
+
+	// Generate the current ephemeral ID from the random identity
+	ephID, start, end, err := ephemeral.GetId(randID, idSize, now.UnixNano())
+	if err != nil {
+		return IdentityUse{}, errors.WithMessage(err, "failed to generate an "+
+			"ephemeral ID for random identity when none is available")
+	}
+
+	return IdentityUse{
+		Identity: Identity{
+			EphId:       ephID,
+			Source:      randID,
+			End:         end,
+			ExtraChecks: 0,
+			StartValid:  start,
+			EndValid:    end,
+			RequestMask: 24 * time.Hour,
+			Ephemeral:   true,
+		},
+		Fake: true,
+	}, nil
+}
diff --git a/storage/reception/fake_test.go b/storage/reception/fake_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..babf46ec2361207bf1872a21ca326e7b556dd209
--- /dev/null
+++ b/storage/reception/fake_test.go
@@ -0,0 +1,66 @@
+package reception
+
+import (
+	"encoding/json"
+	"math"
+	"math/rand"
+	"strings"
+	"testing"
+	"time"
+)
+
+// Tests Generate Fake identity is consistent and returns a correct result.
+func Test_generateFakeIdentity(t *testing.T) {
+	rng := rand.New(rand.NewSource(42))
+
+	end, _ := json.Marshal(time.Unix(0, 1258494203759765625))
+	startValid, _ := json.Marshal(time.Unix(0, 1258407803759765625))
+	endValid, _ := json.Marshal(time.Unix(0, 1258494203759765625))
+	expected := "{\"EphId\":[0,0,0,0,0,0,46,197]," +
+		"\"Source\":[83,140,127,150,177,100,191,27,151,187,159,75,180,114," +
+		"232,159,91,20,132,242,82,9,201,217,52,62,146,186,9,221,157,82,3]," +
+		"\"End\":" + string(end) + ",\"ExtraChecks\":0," +
+		"\"StartValid\":" + string(startValid) + "," +
+		"\"EndValid\":" + string(endValid) + "," +
+		"\"RequestMask\":86400000000000,\"Ephemeral\":true," +
+		"\"StartRequest\":\"0001-01-01T00:00:00Z\"," +
+		"\"EndRequest\":\"0001-01-01T00:00:00Z\",\"Fake\":true,\"KR\":null}"
+
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+
+	received, err := generateFakeIdentity(rng, 15, timestamp)
+	if err != nil {
+		t.Errorf("generateFakeIdentity() returned an error: %+v", err)
+	}
+
+	receivedJson, _ := json.Marshal(received)
+
+	if expected != string(receivedJson) {
+		t.Errorf("The fake identity was generated incorrectly.\n "+
+			"expected: %s\nreceived: %s", expected, receivedJson)
+	}
+}
+
+// Error path: fails to generate random bytes.
+func Test_generateFakeIdentity_RngError(t *testing.T) {
+	rng := strings.NewReader("")
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+
+	_, err := generateFakeIdentity(rng, 15, timestamp)
+	if err == nil || !strings.Contains(err.Error(), "failed to generate a random identity") {
+		t.Errorf("generateFakeIdentity() did not return the correct error on "+
+			"failure to generate random bytes: %+v", err)
+	}
+}
+
+// Error path: fails to get the ephemeral ID.
+func Test_generateFakeIdentity_GetEphemeralIdError(t *testing.T) {
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+
+	_, err := generateFakeIdentity(rng, math.MaxUint64, timestamp)
+	if err == nil || !strings.Contains(err.Error(), "ephemeral ID") {
+		t.Errorf("generateFakeIdentity() did not return the correct error on "+
+			"failure to generate ephemeral ID: %+v", err)
+	}
+}
diff --git a/storage/reception/identity.go b/storage/reception/identity.go
new file mode 100644
index 0000000000000000000000000000000000000000..e64c0dd33c172a5bc4a854c8f6379670d08316f1
--- /dev/null
+++ b/storage/reception/identity.go
@@ -0,0 +1,94 @@
+package reception
+
+import (
+	"encoding/json"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"strconv"
+	"time"
+)
+
+const identityStorageKey = "IdentityStorage"
+const identityStorageVersion = 0
+
+type Identity struct {
+	// Identity
+	EphId  ephemeral.Id
+	Source *id.ID
+
+	// Usage variables
+	End         time.Time // Timestamp when active polling will stop
+	ExtraChecks uint      // Number of extra checks executed as active after the
+	// ID exits active
+
+	// Polling parameters
+	StartValid  time.Time     // Timestamp when the ephID begins being valid
+	EndValid    time.Time     // Timestamp when the ephID stops being valid
+	RequestMask time.Duration // Amount of extra time requested for the poll in
+	// order to mask the exact valid time for the ID
+
+	// Makes the identity not store on disk
+	Ephemeral bool
+}
+
+func loadIdentity(kv *versioned.KV) (Identity, error) {
+	obj, err := kv.Get(identityStorageKey)
+	if err != nil {
+		return Identity{}, errors.WithMessage(err, "Failed to load Identity")
+	}
+
+	r := Identity{}
+	err = json.Unmarshal(obj.Data, &r)
+	if err != nil {
+		return Identity{}, errors.WithMessage(err, "Failed to unmarshal Identity")
+	}
+	return r, nil
+}
+
+func (i Identity) store(kv *versioned.KV) error {
+	// Marshal the registration
+	regStr, err := json.Marshal(&i)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to marshal Identity")
+	}
+
+	// Create versioned object with data
+	obj := &versioned.Object{
+		Version:   identityStorageVersion,
+		Timestamp: time.Now(),
+		Data:      regStr,
+	}
+
+	// Store the data
+	err = kv.Set(identityStorageKey, obj)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to store Identity")
+	}
+
+	return nil
+}
+
+func (i Identity) delete(kv *versioned.KV) error {
+	return kv.Delete(identityStorageKey)
+}
+
+func (i Identity) calculateKrSize() int {
+	return int(i.EndValid.Sub(i.StartValid).Seconds()+1) * maxRoundsPerSecond
+}
+
+func (i *Identity) String() string {
+	return strconv.FormatInt(i.EphId.Int64(), 16) + " " + i.Source.String()
+}
+
+func (i Identity) Equal(b Identity) bool {
+	return i.EphId == b.EphId &&
+		i.Source.Cmp(b.Source) &&
+		i.End.Equal(b.End) &&
+		i.ExtraChecks == b.ExtraChecks &&
+		i.StartValid.Equal(b.StartValid) &&
+		i.EndValid.Equal(b.EndValid) &&
+		i.RequestMask == b.RequestMask &&
+		i.Ephemeral == b.Ephemeral
+}
diff --git a/storage/reception/identityUse_test.go b/storage/reception/identityUse_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e54d73e723a4daa8365f34e446c60916a43ca3dd
--- /dev/null
+++ b/storage/reception/identityUse_test.go
@@ -0,0 +1,67 @@
+package reception
+
+import (
+	"math/rand"
+	"testing"
+	"time"
+)
+
+func TestIdentityUse_SetSamplingPeriod(t *testing.T) {
+	rng := rand.New(rand.NewSource(42))
+
+	const numTests = 1000
+
+	for i := 0; i < numTests; i++ {
+		// Generate an identity use
+		start := randate()
+		end := start.Add(time.Duration(rand.Uint64() % uint64(92*time.Hour)))
+		mask := time.Duration(rand.Uint64() % uint64(92*time.Hour))
+		iu := IdentityUse{
+			Identity: Identity{
+				StartValid:  start,
+				EndValid:    end,
+				RequestMask: mask,
+			},
+		}
+
+		// Generate the sampling period
+		var err error
+		iu, err = iu.setSamplingPeriod(rng)
+		if err != nil {
+			t.Errorf("Errored in generatign sampling "+
+				"period on interation %v: %+v", i, err)
+		}
+
+		// Test that the range between the periods is correct
+		resultRange := iu.EndRequest.Sub(iu.StartRequest)
+		expectedRange := iu.EndValid.Sub(iu.StartValid) + iu.RequestMask
+
+		if resultRange != expectedRange {
+			t.Errorf("The generated sampling period is of the wrong "+
+				"size: Expecterd: %s, Received: %s", expectedRange, resultRange)
+		}
+
+		// Test the sampling range does not exceed a reasonable lower bound
+		lowerBound := iu.StartValid.Add(-iu.RequestMask)
+		if !iu.StartRequest.After(lowerBound) {
+			t.Errorf("Start request exceeds the reasonable lower "+
+				"bound: \n\t Bound: %s\n\t Start: %s", lowerBound, iu.StartValid)
+		}
+
+		// Test the sampling range does not exceed a reasonable upper bound
+		upperBound := iu.EndValid.Add(iu.RequestMask - time.Millisecond)
+		if iu.EndRequest.After(upperBound) {
+			t.Errorf("End request exceeds the reasonable upper bound")
+		}
+	}
+
+}
+
+func randate() time.Time {
+	min := time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
+	max := time.Date(2070, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
+	delta := max - min
+
+	sec := rand.Int63n(delta) + min
+	return time.Unix(sec, 0)
+}
diff --git a/storage/reception/identity_test.go b/storage/reception/identity_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..4657330ebb1cf3359eb3fb34cedba96c74e2e2f9
--- /dev/null
+++ b/storage/reception/identity_test.go
@@ -0,0 +1,118 @@
+package reception
+
+import (
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"math/rand"
+	"testing"
+	"time"
+)
+
+func TestIdentity_EncodeDecode(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	r := Identity{
+		EphId:       ephemeral.Id{},
+		Source:      &id.Permissioning,
+		End:         time.Now().Round(0),
+		ExtraChecks: 12,
+		StartValid:  time.Now().Round(0),
+		EndValid:    time.Now().Round(0),
+		RequestMask: 2 * time.Hour,
+		Ephemeral:   false,
+	}
+
+	err := r.store(kv)
+	if err != nil {
+		t.Errorf("Failed to store: %+v", err)
+	}
+
+	rLoad, err := loadIdentity(kv)
+	if err != nil {
+		t.Errorf("Failed to load: %+v", err)
+	}
+
+	if !r.Equal(rLoad) {
+		t.Errorf("Registrations are not the same\nsaved:  %+v\nloaded: %+v",
+			r, rLoad)
+	}
+}
+
+func TestIdentity_Delete(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	r := Identity{
+		EphId:       ephemeral.Id{},
+		Source:      &id.Permissioning,
+		End:         time.Now().Round(0),
+		ExtraChecks: 12,
+		StartValid:  time.Now().Round(0),
+		EndValid:    time.Now().Round(0),
+		RequestMask: 2 * time.Hour,
+		Ephemeral:   false,
+	}
+
+	err := r.store(kv)
+	if err != nil {
+		t.Errorf("Failed to store: %s", err)
+	}
+
+	err = r.delete(kv)
+	if err != nil {
+		t.Errorf("Failed to delete: %s", err)
+	}
+
+	_, err = loadIdentity(kv)
+	if err == nil {
+		t.Error("Load after delete succeeded.")
+	}
+}
+
+func TestIdentity_String(t *testing.T) {
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	received, _ := generateFakeIdentity(rng, 15, timestamp)
+	expected := "-1763 U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID"
+
+	s := received.String()
+	if s != expected {
+		t.Errorf("String did not return the correct value."+
+			"\nexpected: %s\nreceived: %s", expected, s)
+	}
+}
+
+func TestIdentity_CalculateKrSize(t *testing.T) {
+	deltas := []time.Duration{0, 2 * time.Second, 2 * time.Hour, 36 * time.Hour,
+		time.Duration(rand.Uint32()) * time.Millisecond}
+	for _, d := range deltas {
+		expected := int(d.Seconds()+1) * maxRoundsPerSecond
+		now := time.Now()
+		i := Identity{
+			StartValid: now,
+			EndValid:   now.Add(d),
+		}
+
+		krSize := i.calculateKrSize()
+		if krSize != expected {
+			t.Errorf("krSize is not correct.\nexpected: %d\nrecieved: %d",
+				expected, krSize)
+		}
+	}
+}
+
+func TestIdentity_Equal(t *testing.T) {
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	a, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, timestamp)
+	b, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, timestamp)
+	c, _ := generateFakeIdentity(rand.New(rand.NewSource(42)), 15, time.Now())
+
+	if !a.Identity.Equal(b.Identity) {
+		t.Errorf("Equal() found two equal identities as unequal."+
+			"\na: %s\nb: %s", a.String(), b.String())
+	}
+
+	if a.Identity.Equal(c.Identity) {
+		t.Errorf("Equal() found two unequal identities as equal."+
+			"\na: %s\nc: %s", a.String(), c.String())
+	}
+}
diff --git a/storage/reception/registration.go b/storage/reception/registration.go
new file mode 100644
index 0000000000000000000000000000000000000000..0df67b81c8be0be71b58158a5f76f1f53ce16ee0
--- /dev/null
+++ b/storage/reception/registration.go
@@ -0,0 +1,118 @@
+package reception
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/utility"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/primitives/knownRounds"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"strconv"
+	"time"
+)
+
+const maxRoundsPerSecond = 100
+const knownRoundsStorageKey = "krStorage"
+
+type registration struct {
+	Identity
+	knownRounds        *knownRounds.KnownRounds
+	knownRoundsStorage *utility.KnownRounds
+	kv                 *versioned.KV
+}
+
+func newRegistration(reg Identity, kv *versioned.KV) (*registration, error) {
+	// Round the times to remove the monotonic clocks for future saving
+	reg.StartValid = reg.StartValid.Round(0)
+	reg.EndValid = reg.EndValid.Round(0)
+	reg.End = reg.End.Round(0)
+
+	now := time.Now()
+
+	// Do edge checks to determine if the identity is valid
+	if now.After(reg.End) && reg.ExtraChecks < 1 {
+		return nil, errors.New("Cannot create a registration for an " +
+			"identity which has expired")
+	}
+
+	// Set the prefix
+	kv = kv.Prefix(regPrefix(reg.EphId, reg.Source, reg.StartValid))
+
+	r := &registration{
+		Identity:    reg,
+		knownRounds: knownRounds.NewKnownRound(reg.calculateKrSize()),
+		kv:          kv,
+	}
+
+	// If this is not ephemeral, then store everything
+	if !reg.Ephemeral {
+		// Store known rounds
+		var err error
+		r.knownRoundsStorage, err = utility.NewKnownRounds(kv, knownRoundsStorageKey, r.knownRounds)
+		if err != nil {
+			return nil, errors.WithMessage(err, "failed to store known rounds")
+		}
+
+		// Store the registration
+		if err = reg.store(kv); err != nil {
+			return nil, errors.WithMessage(err, "failed to store registration")
+		}
+	}
+
+	return r, nil
+}
+
+func loadRegistration(EphId ephemeral.Id, Source *id.ID, startValid time.Time,
+	kv *versioned.KV) (*registration, error) {
+
+	kv = kv.Prefix(regPrefix(EphId, Source, startValid))
+
+	reg, err := loadIdentity(kv)
+	if err != nil {
+		return nil, errors.WithMessagef(err, "Failed to load identity "+
+			"for %s", regPrefix(EphId, Source, startValid))
+	}
+
+	kr, err := utility.LoadKnownRounds(kv, knownRoundsStorageKey, reg.calculateKrSize())
+	if err != nil {
+		return nil, errors.WithMessagef(err, "Failed to load known "+
+			"rounds for %s", regPrefix(EphId, Source, startValid))
+	}
+
+	r := &registration{
+		Identity:           reg,
+		knownRoundsStorage: kr,
+		kv:                 kv,
+	}
+
+	return r, nil
+}
+
+func (r *registration) Delete() error {
+	if !r.Ephemeral {
+		if err := r.knownRoundsStorage.Delete(); err != nil {
+			return errors.WithMessagef(err, "Failed to delete registration "+
+				"known rounds %s", r)
+		}
+		if err := r.delete(r.kv); err != nil {
+			return errors.WithMessagef(err, "Failed to delete registration "+
+				"public data %s", r)
+		}
+	}
+
+	return nil
+}
+
+func (r registration) getKR() KnownRounds {
+	if r.Ephemeral {
+		return r.knownRounds
+	} else {
+		return r.knownRoundsStorage
+	}
+}
+
+func regPrefix(EphId ephemeral.Id, Source *id.ID, startTime time.Time) string {
+	return "receptionRegistration_" +
+		strconv.FormatInt(EphId.Int64(), 16) + Source.String() +
+		strconv.FormatInt(startTime.Round(0).UnixNano(), 10)
+}
diff --git a/storage/reception/registration_test.go b/storage/reception/registration_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ffb155fe3b0e08949fd66b73975ac98cb4733692
--- /dev/null
+++ b/storage/reception/registration_test.go
@@ -0,0 +1,158 @@
+package reception
+
+import (
+	"gitlab.com/elixxir/client/storage/utility"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/ekv"
+	"math/rand"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestNewRegistration_Failed(t *testing.T) {
+	// Generate an identity for use
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	idu, _ := generateFakeIdentity(rng, 15, timestamp)
+	id := idu.Identity
+	kv := versioned.NewKV(make(ekv.Memstore))
+
+	id.End = time.Time{}
+	id.ExtraChecks = 0
+
+	_, err := newRegistration(id, kv)
+	if err == nil || !strings.Contains(err.Error(), "Cannot create a registration for an identity which has expired") {
+		t.Error("Registration creation succeeded with expired identity.")
+	}
+}
+
+func TestNewRegistration_Ephemeral(t *testing.T) {
+	// Generate an identity for use
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	idu, _ := generateFakeIdentity(rng, 15, timestamp)
+	id := idu.Identity
+	kv := versioned.NewKV(make(ekv.Memstore))
+
+	id.End = time.Now().Add(1 * time.Hour)
+	id.ExtraChecks = 2
+	id.Ephemeral = true
+
+	reg, err := newRegistration(id, kv)
+	if err != nil {
+		t.Fatalf("Registration creation failed when it should have "+
+			"succeeded: %+v", err)
+	}
+
+	if reg.knownRounds == nil {
+		t.Error("Ephemeral identity does not have a known rounds.")
+	}
+
+	if reg.knownRoundsStorage != nil {
+		t.Error("Ephemeral identity has a known rounds storage.")
+	}
+
+	// Check if the known rounds is stored, it should not be
+	if _, err = utility.LoadKnownRounds(reg.kv, knownRoundsStorageKey, id.calculateKrSize()); err == nil {
+		t.Error("Ephemeral identity stored the known rounds when it should not have.")
+	}
+
+	if _, err = reg.kv.Get(identityStorageKey); err == nil {
+		t.Error("Ephemeral identity stored the identity when it should not have.")
+	}
+}
+
+func TestNewRegistration_Persistent(t *testing.T) {
+	// Generate an identity for use
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	idu, _ := generateFakeIdentity(rng, 15, timestamp)
+	id := idu.Identity
+	kv := versioned.NewKV(make(ekv.Memstore))
+
+	id.End = time.Now().Add(1 * time.Hour)
+	id.ExtraChecks = 2
+	id.Ephemeral = false
+
+	reg, err := newRegistration(id, kv)
+	if err != nil {
+		t.Fatalf("Registration creation failed when it should have "+
+			"succeeded: %+v", err)
+	}
+
+	if reg.knownRounds == nil {
+		t.Error("Persistent identity does not have a known rounds.")
+	}
+
+	if reg.knownRoundsStorage == nil {
+		t.Error("Persistent identity does not have a known rounds storage.")
+	}
+
+	// Check if the known rounds is stored, it should not be
+	if _, err = utility.LoadKnownRounds(reg.kv, knownRoundsStorageKey, id.calculateKrSize()); err != nil {
+		t.Errorf("Persistent identity did not store known rounds when "+
+			"it should: %+v", err)
+	}
+
+	if _, err = reg.kv.Get(identityStorageKey); err != nil {
+		t.Error("Persistent identity did not store the identity when it should.")
+	}
+}
+
+func TestLoadRegistration(t *testing.T) {
+	// Generate an identity for use
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	idu, _ := generateFakeIdentity(rng, 15, timestamp)
+	id := idu.Identity
+	kv := versioned.NewKV(make(ekv.Memstore))
+
+	id.End = time.Now().Add(1 * time.Hour)
+	id.ExtraChecks = 2
+	id.Ephemeral = false
+
+	_, err := newRegistration(id, kv)
+	if err != nil {
+		t.Fatalf("Registration creation failed when it should have "+
+			"succeeded: %+v", err)
+	}
+
+	reg, err := loadRegistration(idu.EphId, idu.Source, idu.StartValid, kv)
+	if err != nil {
+		t.Fatalf("Registration loading failed: %+v", err)
+	}
+
+	if reg.knownRounds != nil {
+		t.Error("Loading has a separated known rounds, it should not have.")
+	}
+
+	if reg.knownRoundsStorage == nil {
+		t.Error("Loading identity does not have a known rounds storage.")
+	}
+}
+
+// TODO: finish
+func Test_registration_Delete(t *testing.T) {
+	// Generate an identity for use
+	rng := rand.New(rand.NewSource(42))
+	timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+	idu, _ := generateFakeIdentity(rng, 15, timestamp)
+	id := idu.Identity
+	kv := versioned.NewKV(make(ekv.Memstore))
+
+	id.End = time.Now().Add(1 * time.Hour)
+	id.ExtraChecks = 2
+	id.Ephemeral = false
+
+	r, err := newRegistration(id, kv)
+	if err != nil {
+		t.Fatalf("Registration creation failed when it should have "+
+			"succeeded: %+v", err)
+	}
+
+	err = r.Delete()
+	if err != nil {
+		t.Errorf("Delete() returned an error: %+v", err)
+	}
+}
diff --git a/storage/reception/store.go b/storage/reception/store.go
new file mode 100644
index 0000000000000000000000000000000000000000..ec987af518ce38a03c222ac6d960eebf1b9b69ab
--- /dev/null
+++ b/storage/reception/store.go
@@ -0,0 +1,314 @@
+package reception
+
+import (
+	"bytes"
+	"encoding/json"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/hash"
+	"gitlab.com/xx_network/crypto/randomness"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"io"
+	"math/big"
+	"strconv"
+	"sync"
+	"time"
+)
+
+const receptionPrefix = "reception"
+const receptionStoreStorageKey = "receptionStoreKey"
+const receptionStoreStorageVersion = 0
+const receptionIDSizeStorageKey = "receptionIDSizeKey"
+const receptionIDSizeStorageVersion = 0
+const defaultIDSize = 12
+
+type Store struct {
+	// Identities which are being actively checked
+	active []*registration
+	idSize int
+
+	kv *versioned.KV
+
+	mux sync.Mutex
+}
+
+type storedReference struct {
+	Eph        ephemeral.Id
+	Source     *id.ID
+	StartValid time.Time
+}
+
+// NewStore creates a new reception store that starts empty.
+func NewStore(kv *versioned.KV) *Store {
+	kv = kv.Prefix(receptionPrefix)
+	s := &Store{
+		active: make([]*registration, 0),
+		idSize: defaultIDSize * 2,
+		kv:     kv,
+	}
+
+	// Store the empty list
+	if err := s.save(); err != nil {
+		jww.FATAL.Panicf("Failed to save new reception store: %+v", err)
+	}
+
+	// Update the size so queries can be made
+	s.UpdateIdSize(defaultIDSize)
+
+	return s
+}
+
+func LoadStore(kv *versioned.KV) *Store {
+	kv = kv.Prefix(receptionPrefix)
+	s := &Store{
+		kv: kv,
+	}
+
+	// Load the versioned object for the reception list
+	vo, err := kv.Get(receptionStoreStorageKey)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to get the reception storage list: %+v", err)
+	}
+
+	identities := make([]storedReference, len(s.active))
+	err = json.Unmarshal(vo.Data, &identities)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to unmarshal the reception storage list: %+v", err)
+	}
+
+	s.active = make([]*registration, len(identities))
+	for i, sr := range identities {
+		s.active[i], err = loadRegistration(sr.Eph, sr.Source, sr.StartValid, s.kv)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to load registration for %s: %+v",
+				regPrefix(sr.Eph, sr.Source, sr.StartValid), err)
+		}
+	}
+
+	// Load the ephemeral ID length
+	vo, err = kv.Get(receptionIDSizeStorageKey)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to get the reception ID size: %+v", err)
+	}
+
+	if s.idSize, err = strconv.Atoi(string(vo.Data)); err != nil {
+		jww.FATAL.Panicf("Failed to unmarshal the reception ID size: %+v",
+			err)
+	}
+
+	return s
+}
+
+func (s *Store) save() error {
+	identities := s.makeStoredReferences()
+
+	data, err := json.Marshal(&identities)
+	if err != nil {
+		return errors.WithMessage(err, "failed to store reception store")
+	}
+
+	// Create versioned object with data
+	obj := &versioned.Object{
+		Version:   receptionStoreStorageVersion,
+		Timestamp: time.Now(),
+		Data:      data,
+	}
+
+	err = s.kv.Set(receptionStoreStorageKey, obj)
+	if err != nil {
+		return errors.WithMessage(err, "Failed to store reception store")
+	}
+
+	return nil
+}
+
+// makeStoredReferences generates a reference of any non-ephemeral identities
+// for storage.
+func (s *Store) makeStoredReferences() []storedReference {
+	identities := make([]storedReference, len(s.active))
+
+	i := 0
+	for _, reg := range s.active {
+		if !reg.Ephemeral {
+			identities[i] = storedReference{
+				Eph:        reg.EphId,
+				Source:     reg.Source,
+				StartValid: reg.StartValid.Round(0),
+			}
+			i++
+		}
+	}
+
+	return identities[:i]
+}
+
+func (s *Store) GetIdentity(rng io.Reader) (IdentityUse, error) {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	now := time.Now()
+
+	// Remove any now expired identities
+	s.prune(now)
+
+	var identity IdentityUse
+	var err error
+
+	// If the list is empty, then we return a randomly generated identity to
+	// poll with so we can continue tracking the network and to further
+	// obfuscate network identities.
+	if len(s.active) == 0 {
+		identity, err = generateFakeIdentity(rng, uint(s.idSize), now)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to generate a new ID when none "+
+				"available: %+v", err)
+		}
+	} else {
+		identity, err = s.selectIdentity(rng, now)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to select an ID: %+v", err)
+		}
+	}
+
+	// Calculate the sampling period
+	identity, err = identity.setSamplingPeriod(rng)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to calculate the sampling period: "+
+			"%+v", err)
+	}
+
+	return identity, nil
+}
+
+func (s *Store) AddIdentity(identity Identity) error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	reg, err := newRegistration(identity, s.kv)
+	if err != nil {
+		return errors.WithMessage(err, "failed to add new identity to "+
+			"reception store")
+	}
+
+	s.active = append(s.active, reg)
+	if !identity.Ephemeral {
+		if err := s.save(); err != nil {
+			jww.FATAL.Panicf("Failed to save reception store after identity " +
+				"addition")
+		}
+	}
+
+	return nil
+}
+
+func (s *Store) RemoveIdentity(ephID ephemeral.Id) {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	for i := 0; i < len(s.active); i++ {
+		inQuestion := s.active[i]
+		if bytes.Equal(inQuestion.EphId[:], ephID[:]) {
+			s.active = append(s.active[:i], s.active[i+1:]...)
+			err := inQuestion.Delete()
+			if err != nil {
+				jww.FATAL.Panicf("Failed to delete identity: %+v", err)
+			}
+			if !inQuestion.Ephemeral {
+				if err := s.save(); err != nil {
+					jww.FATAL.Panicf("Failed to save reception store after " +
+						"identity removal")
+				}
+			}
+			return
+		}
+	}
+}
+
+func (s *Store) UpdateIdSize(idSize uint) {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+	if s.idSize == int(idSize) {
+		return
+	}
+
+	s.idSize = int(idSize)
+
+	// Store the ID size
+	obj := &versioned.Object{
+		Version:   receptionIDSizeStorageVersion,
+		Timestamp: time.Now(),
+		Data:      []byte(strconv.Itoa(s.idSize)),
+	}
+
+	err := s.kv.Set(receptionIDSizeStorageKey, obj)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to store reception ID size: %+v", err)
+	}
+}
+
+func (s *Store) GetIDSize() uint {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+	return uint(s.idSize)
+}
+
+func (s *Store) prune(now time.Time) {
+	lengthBefore := len(s.active)
+
+	// Prune the list
+	for i := 0; i < len(s.active); i++ {
+		inQuestion := s.active[i]
+		if now.After(inQuestion.End) && inQuestion.ExtraChecks == 0 {
+			if err := inQuestion.Delete(); err != nil {
+				jww.ERROR.Printf("Failed to delete Identity for %s: "+
+					"%+v", inQuestion, err)
+			}
+
+			s.active = append(s.active[:i], s.active[i+1:]...)
+
+			i--
+		}
+	}
+
+	// Save the list if it changed
+	if lengthBefore != len(s.active) {
+		if err := s.save(); err != nil {
+			jww.FATAL.Panicf("Failed to store reception storage")
+		}
+	}
+}
+
+func (s *Store) selectIdentity(rng io.Reader, now time.Time) (IdentityUse, error) {
+	// Choose a member from the list
+	var selected *registration
+
+	if len(s.active) == 1 {
+		selected = s.active[0]
+	} else {
+		seed := make([]byte, 32)
+		if _, err := rng.Read(seed); err != nil {
+			return IdentityUse{}, errors.WithMessage(err, "Failed to "+
+				"choose ID due to rng failure")
+		}
+		h, err := hash.NewCMixHash()
+		if err != nil {
+			return IdentityUse{}, err
+		}
+
+		selectedNum := randomness.RandInInterval(
+			big.NewInt(int64(len(s.active)-1)), seed, h)
+		selected = s.active[selectedNum.Uint64()]
+	}
+
+	if now.After(selected.End) {
+		selected.ExtraChecks--
+	}
+
+	return IdentityUse{
+		Identity: selected.Identity,
+		Fake:     false,
+		KR:       selected.getKR(),
+	}, nil
+}
diff --git a/storage/reception/store_test.go b/storage/reception/store_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..bb6ad2b6fc395cd9324136383bb3c6065044621f
--- /dev/null
+++ b/storage/reception/store_test.go
@@ -0,0 +1,291 @@
+package reception
+
+import (
+	"bytes"
+	"encoding/json"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/ekv"
+	"math/rand"
+	"reflect"
+	"testing"
+	"time"
+)
+
+func TestNewStore(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	expected := &Store{
+		active: make([]*registration, 0),
+		idSize: defaultIDSize,
+		kv:     kv,
+	}
+
+	s := NewStore(kv)
+
+	if !reflect.DeepEqual([]*registration{}, s.active) || s.idSize != defaultIDSize {
+		t.Errorf("NewStore() failed to return the expected Store."+
+			"\nexpected: %+v\nreceived: %+v", expected, s)
+	}
+
+	obj, err := s.kv.Get(receptionStoreStorageKey)
+	if err != nil {
+		t.Fatalf("Failed to load store from KV: %+v", err)
+	}
+
+	var testStoredReference []storedReference
+	err = json.Unmarshal(obj.Data, &testStoredReference)
+	if err != nil {
+		t.Errorf("Failed to unmarshal []storedReference: %+v", err)
+	}
+	if !reflect.DeepEqual([]storedReference{}, testStoredReference) {
+		t.Errorf("Failed to retreive expected storedReference from KV."+
+			"\nexpected: %#v\nreceived: %#v", []storedReference{}, testStoredReference)
+	}
+}
+
+func TestLoadStore(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+
+	// Fill active registration with fake identities
+	for i := 0; i < 10; i++ {
+		testID, err := generateFakeIdentity(prng, 15, time.Now())
+		if err != nil {
+			t.Fatalf("Failed to generate fake ID: %+v", err)
+		}
+		testID.Ephemeral = false
+		if s.AddIdentity(testID.Identity) != nil {
+			t.Fatalf("Failed to AddIdentity: %+v", err)
+		}
+	}
+
+	err := s.save()
+	if err != nil {
+		t.Errorf("save() produced an error: %+v", err)
+	}
+
+	testStore := LoadStore(kv)
+	for i, active := range testStore.active {
+		s.active[i].knownRounds = nil
+		if !s.active[i].Equal(active.Identity) {
+			t.Errorf("Failed to generate expected Store."+
+				"\nexpected: %#v\nreceived: %#v", s.active[i], active)
+		}
+	}
+}
+
+func TestStore_save(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+
+	// Fill active registration with fake identities
+	for i := 0; i < 10; i++ {
+		testID, err := generateFakeIdentity(prng, 15, time.Now())
+		if err != nil {
+			t.Fatalf("Failed to generate fake ID: %+v", err)
+		}
+		testID.Ephemeral = false
+		s.active = append(s.active, &registration{Identity: testID.Identity})
+	}
+
+	expected := s.makeStoredReferences()
+
+	err := s.save()
+	if err != nil {
+		t.Errorf("save() produced an error: %+v", err)
+	}
+
+	obj, err := kv.Prefix(receptionPrefix).Get(receptionStoreStorageKey)
+	if err != nil {
+		t.Errorf("Get() produced an error: %+v", err)
+	}
+
+	expectedData, err := json.Marshal(expected)
+	if obj.Version != receptionStoreStorageVersion {
+		t.Errorf("Rectrieved version incorrect.\nexpected: %d\nreceived: %d",
+			receptionStoreStorageVersion, obj.Version)
+	}
+
+	if !bytes.Equal(expectedData, obj.Data) {
+		t.Errorf("Rectrieved data incorrect.\nexpected: %s\nreceived: %s",
+			expectedData, obj.Data)
+	}
+}
+
+func TestStore_makeStoredReferences(t *testing.T) {
+	s := NewStore(versioned.NewKV(make(ekv.Memstore)))
+	prng := rand.New(rand.NewSource(42))
+	expected := make([]storedReference, 0)
+
+	// Fill active registration with fake identities
+	for i := 0; i < 10; i++ {
+		testID, err := generateFakeIdentity(prng, 15, time.Now())
+		if err != nil {
+			t.Fatalf("Failed to generate fake ID: %+v", err)
+		}
+		if i%2 == 0 {
+			testID.Ephemeral = false
+			expected = append(expected, storedReference{
+				Eph:        testID.EphId,
+				Source:     testID.Source,
+				StartValid: testID.StartValid.Round(0),
+			})
+		}
+		s.active = append(s.active, &registration{Identity: testID.Identity})
+	}
+
+	sr := s.makeStoredReferences()
+	if !reflect.DeepEqual(expected, sr) {
+		t.Errorf("Failed to generate expected list of identities."+
+			"\nexpected: %+v\nreceived: %+v", expected, sr)
+	}
+}
+
+func TestStore_GetIdentity(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+	testID, err := generateFakeIdentity(prng, 15, time.Now())
+	if err != nil {
+		t.Fatalf("Failed to generate fake ID: %+v", err)
+	}
+	if s.AddIdentity(testID.Identity) != nil {
+		t.Errorf("AddIdentity() produced an error: %+v", err)
+	}
+
+	idu, err := s.GetIdentity(prng)
+	if err != nil {
+		t.Errorf("GetIdentity() produced an error: %+v", err)
+	}
+
+	if !testID.Equal(idu.Identity) {
+		t.Errorf("GetIdentity() did not return the expected Identity."+
+			"\nexpected: %s\nreceived: %s", testID.String(), idu.String())
+	}
+}
+
+func TestStore_AddIdentity(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+	testID, err := generateFakeIdentity(prng, 15, time.Now())
+	if err != nil {
+		t.Fatalf("Failed to generate fake ID: %+v", err)
+	}
+
+	err = s.AddIdentity(testID.Identity)
+	if err != nil {
+		t.Errorf("AddIdentity() produced an error: %+v", err)
+	}
+
+	if !s.active[0].Identity.Equal(testID.Identity) {
+		t.Errorf("Failed to get expected Identity.\nexpected: %s\nreceived: %s",
+			testID.Identity.String(), s.active[0])
+	}
+}
+
+func TestStore_RemoveIdentity(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+	testID, err := generateFakeIdentity(prng, 15, time.Now())
+	if err != nil {
+		t.Fatalf("Failed to generate fake ID: %+v", err)
+	}
+	err = s.AddIdentity(testID.Identity)
+	if err != nil {
+		t.Fatalf("AddIdentity() produced an error: %+v", err)
+	}
+	s.RemoveIdentity(testID.EphId)
+
+	if len(s.active) != 0 {
+		t.Errorf("RemoveIdentity() failed to remove: %+v", s.active)
+	}
+}
+
+func TestStore_UpdateIdSize(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	newSize := s.idSize * 2
+
+	s.UpdateIdSize(uint(newSize))
+
+	if s.idSize != newSize {
+		t.Errorf("UpdateIdSize() failed to update the size."+
+			"\nexpected: %d\nrecieved: %d", newSize, s.idSize)
+	}
+}
+
+func TestStore_prune(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+	runs := 10
+	expected := make([]*registration, runs/2)
+
+	for i := 0; i < runs; i++ {
+		timestamp := time.Now()
+		if i%2 == 0 {
+			timestamp = timestamp.Add(24 * time.Hour)
+		}
+		testID, err := generateFakeIdentity(prng, 15, timestamp)
+		if err != nil {
+			t.Fatalf("Failed to generate fake ID: %+v", err)
+		}
+		err = s.AddIdentity(testID.Identity)
+		if err != nil {
+			t.Fatalf("AddIdentity() produced an error: %+v", err)
+		}
+		if i%2 == 0 {
+			expected[i/2] = s.active[i]
+		}
+	}
+
+	s.prune(time.Now().Add(24 * time.Hour))
+
+	for i, reg := range s.active {
+		if !reg.Equal(expected[i].Identity) {
+			t.Errorf("Unexpected identity (%d).\nexpected: %+v\nreceived: %+v",
+				i, expected[i], reg)
+		}
+	}
+}
+
+func TestStore_selectIdentity(t *testing.T) {
+	kv := versioned.NewKV(make(ekv.Memstore))
+	s := NewStore(kv)
+	prng := rand.New(rand.NewSource(42))
+	runs := 10
+	expectedReg := make([]*registration, runs)
+
+	for i := 0; i < runs; i++ {
+		testID, err := generateFakeIdentity(prng, 15, time.Now())
+		if err != nil {
+			t.Fatalf("Failed to generate fake ID: %+v", err)
+		}
+		err = s.AddIdentity(testID.Identity)
+		if err != nil {
+			t.Fatalf("AddIdentity() produced an error: %+v", err)
+		}
+		expectedReg[i] = s.active[i]
+	}
+
+	for i := 0; i < runs; i++ {
+		idu, err := s.selectIdentity(prng, time.Now())
+		if err != nil {
+			t.Errorf("selectIdentity() produced an error: %+v", err)
+		}
+
+		var found bool
+		for _, expected := range expectedReg {
+			if idu.Equal(expected.Identity) {
+				found = true
+				break
+			}
+		}
+		if !found {
+			t.Errorf("Unexpected Identity returned.\nreceived: %+v", idu)
+		}
+	}
+}
diff --git a/storage/regStatus.go b/storage/regStatus.go
index 52f74dd10bf98631892237b1820ba31b105c8ecd..ec18a0cfcb92aaa9c154f23528a40a96f202273f 100644
--- a/storage/regStatus.go
+++ b/storage/regStatus.go
@@ -27,7 +27,7 @@ const (
 	UDBComplete           RegistrationStatus = 30000 // Set upon completion of RegisterWithUdb
 )
 
-// stringer for Registration Status
+// stringer for Identity Status
 func (rs RegistrationStatus) String() string {
 	switch rs {
 	case NotStarted:
@@ -35,9 +35,9 @@ func (rs RegistrationStatus) String() string {
 	case KeyGenComplete:
 		return "Key Generation Complete"
 	case PermissioningComplete:
-		return "Permissioning Registration Complete"
+		return "Permissioning Identity Complete"
 	case UDBComplete:
-		return "User Discovery Registration Complete"
+		return "User Discovery Identity Complete"
 	default:
 		return fmt.Sprintf("Unknown registration state %v", uint32(rs))
 	}
diff --git a/storage/session.go b/storage/session.go
index 44278489c94d868f1b76556c2375c8fe8981d298..ce575952455fd0d84cb24d9497ce7acb80fe6f8c 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -18,6 +18,7 @@ import (
 	"gitlab.com/elixxir/client/storage/conversation"
 	"gitlab.com/elixxir/client/storage/e2e"
 	"gitlab.com/elixxir/client/storage/partition"
+	"gitlab.com/elixxir/client/storage/reception"
 	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/storage/utility"
 	"gitlab.com/elixxir/client/storage/versioned"
@@ -56,6 +57,7 @@ type Session struct {
 	criticalRawMessages *utility.CmixMessageBuffer
 	garbledMessages     *utility.MeteredCmixMessageBuffer
 	checkedRounds       *utility.KnownRounds
+	reception           *reception.Store
 }
 
 // Initialize a new Session object
@@ -116,13 +118,6 @@ func New(baseDir, password string, u userInterface.User, cmixGrp,
 		return nil, errors.WithMessage(err, "Failed to create garbledMessages buffer")
 	}
 
-	s.checkedRounds, err = utility.NewKnownRounds(s.kv, checkedRoundsKey, CheckRoundsMaxSize)
-	if err != nil {
-		return nil, errors.WithMessage(err, "Failed to create checkedRounds")
-	}
-	// There is no round id 0
-	s.checkedRounds.Check(0)
-
 	s.criticalMessages, err = utility.NewE2eMessageBuffer(s.kv, criticalMessagesKey)
 	if err != nil {
 		return nil, errors.WithMessage(err, "Failed to create e2e critical message buffer")
@@ -136,6 +131,8 @@ func New(baseDir, password string, u userInterface.User, cmixGrp,
 	s.conversations = conversation.NewStore(s.kv)
 	s.partition = partition.New(s.kv)
 
+	s.reception = reception.NewStore(s.kv)
+
 	return s, nil
 }
 
@@ -197,6 +194,8 @@ func Load(baseDir, password string, rng *fastRNG.StreamGenerator) (*Session, err
 	s.conversations = conversation.NewStore(s.kv)
 	s.partition = partition.New(s.kv)
 
+	s.reception = reception.LoadStore(s.kv)
+
 	return s, nil
 }
 
@@ -224,6 +223,12 @@ func (s *Session) Auth() *auth.Store {
 	return s.auth
 }
 
+func (s *Session) Reception() *reception.Store {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.reception
+}
+
 func (s *Session) GetCriticalMessages() *utility.E2eMessageBuffer {
 	s.mux.RLock()
 	defer s.mux.RUnlock()
@@ -344,5 +349,6 @@ func InitTestingSession(i interface{}) *Session {
 	s.conversations = conversation.NewStore(s.kv)
 	s.partition = partition.New(s.kv)
 
+	s.reception = reception.NewStore(s.kv)
 	return s
 }
diff --git a/storage/user/regValidationSig.go b/storage/user/regValidationSig.go
index 215526936b02440a3ac6a8c84d2ee9b6d96a135b..a64b33d4d713acefe6dad14eb8d1c3a056188d66 100644
--- a/storage/user/regValidationSig.go
+++ b/storage/user/regValidationSig.go
@@ -17,7 +17,7 @@ const currentRegValidationSigVersion = 0
 const transmissionRegValidationSigKey = "transmissionRegistrationValidationSignature"
 const receptionRegValidationSigKey = "receptionRegistrationValidationSignature"
 
-// Returns the transmission Registration Validation Signature stored in RAM. May return
+// Returns the transmission Identity Validation Signature stored in RAM. May return
 // nil of no signature is stored
 func (u *User) GetTransmissionRegistrationValidationSignature() []byte {
 	u.rvsMux.RLock()
@@ -25,7 +25,7 @@ func (u *User) GetTransmissionRegistrationValidationSignature() []byte {
 	return u.transmissionRegValidationSig
 }
 
-// Returns the reception Registration Validation Signature stored in RAM. May return
+// Returns the reception Identity Validation Signature stored in RAM. May return
 // nil of no signature is stored
 func (u *User) GetReceptionRegistrationValidationSignature() []byte {
 	u.rvsMux.RLock()
@@ -33,7 +33,7 @@ func (u *User) GetReceptionRegistrationValidationSignature() []byte {
 	return u.receptionRegValidationSig
 }
 
-// Loads the transmission Registration Validation Signature if it exists in the ekv
+// Loads the transmission Identity Validation Signature if it exists in the ekv
 func (u *User) loadTransmissionRegistrationValidationSignature() {
 	u.rvsMux.Lock()
 	obj, err := u.kv.Get(transmissionRegValidationSigKey)
@@ -43,7 +43,7 @@ func (u *User) loadTransmissionRegistrationValidationSignature() {
 	u.rvsMux.Unlock()
 }
 
-// Loads the reception Registration Validation Signature if it exists in the ekv
+// Loads the reception Identity Validation Signature if it exists in the ekv
 func (u *User) loadReceptionRegistrationValidationSignature() {
 	u.rvsMux.Lock()
 	obj, err := u.kv.Get(receptionRegValidationSigKey)
@@ -53,7 +53,7 @@ func (u *User) loadReceptionRegistrationValidationSignature() {
 	u.rvsMux.Unlock()
 }
 
-// Sets the Registration Validation Signature if it is not set and stores it in
+// Sets the Identity Validation Signature if it is not set and stores it in
 // the ekv
 func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) {
 	u.rvsMux.Lock()
@@ -61,7 +61,7 @@ func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) {
 
 	//check if the signature already exists
 	if u.transmissionRegValidationSig != nil {
-		jww.FATAL.Panicf("cannot overwrite existing transmission Registration Validation Signature")
+		jww.FATAL.Panicf("cannot overwrite existing transmission Identity Validation Signature")
 	}
 
 	obj := &versioned.Object{
@@ -72,14 +72,14 @@ func (u *User) SetTransmissionRegistrationValidationSignature(b []byte) {
 
 	err := u.kv.Set(transmissionRegValidationSigKey, obj)
 	if err != nil {
-		jww.FATAL.Panicf("Failed to store the transmission Registration Validation "+
+		jww.FATAL.Panicf("Failed to store the transmission Identity Validation "+
 			"Signature: %s", err)
 	}
 
 	u.transmissionRegValidationSig = b
 }
 
-// Sets the Registration Validation Signature if it is not set and stores it in
+// Sets the Identity Validation Signature if it is not set and stores it in
 // the ekv
 func (u *User) SetReceptionRegistrationValidationSignature(b []byte) {
 	u.rvsMux.Lock()
@@ -87,7 +87,7 @@ func (u *User) SetReceptionRegistrationValidationSignature(b []byte) {
 
 	//check if the signature already exists
 	if u.receptionRegValidationSig != nil {
-		jww.FATAL.Panicf("cannot overwrite existing reception Registration Validation Signature")
+		jww.FATAL.Panicf("cannot overwrite existing reception Identity Validation Signature")
 	}
 
 	obj := &versioned.Object{
@@ -98,7 +98,7 @@ func (u *User) SetReceptionRegistrationValidationSignature(b []byte) {
 
 	err := u.kv.Set(receptionRegValidationSigKey, obj)
 	if err != nil {
-		jww.FATAL.Panicf("Failed to store the reception Registration Validation "+
+		jww.FATAL.Panicf("Failed to store the reception Identity Validation "+
 			"Signature: %s", err)
 	}
 
diff --git a/storage/utility/knownRounds.go b/storage/utility/knownRounds.go
index 767ad917c4e57f7e8040deb58713e069fd2b6596..72f4833d7158483fb88c881434a7ed8f4009852b 100644
--- a/storage/utility/knownRounds.go
+++ b/storage/utility/knownRounds.go
@@ -35,10 +35,10 @@ type KnownRounds struct {
 // NewKnownRounds creates a new empty KnownRounds and saves it to the passed
 // in key value store at the specified key. An error is returned on an
 // unsuccessful save.
-func NewKnownRounds(kv *versioned.KV, key string, size int) (*KnownRounds, error) {
+func NewKnownRounds(kv *versioned.KV, key string, known *knownRounds.KnownRounds) (*KnownRounds, error) {
 	// Create new empty struct
 	kr := &KnownRounds{
-		rounds: knownRounds.NewKnownRound(size),
+		rounds: known,
 		kv:     kv.Prefix(knownRoundsPrefix),
 		key:    key,
 	}
@@ -107,6 +107,15 @@ func (kr *KnownRounds) load() error {
 	return nil
 }
 
+// Deletes a known rounds object from disk and memory
+func (kr *KnownRounds) Delete() error {
+	err := kr.kv.Delete(kr.key)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 // Checked determines if the round has been checked.
 func (kr *KnownRounds) Checked(rid id.Round) bool {
 	kr.mux.RLock()
@@ -158,7 +167,7 @@ func (kr *KnownRounds) RangeUnchecked(newestRid id.Round,
 
 // RangeUncheckedMasked checks rounds based off the provided mask.
 func (kr *KnownRounds) RangeUncheckedMasked(mask *knownRounds.KnownRounds,
-	roundCheck func(id id.Round) bool, maxChecked int) {
+	roundCheck knownRounds.RoundCheckFunc, maxChecked int) {
 	kr.mux.Lock()
 	defer kr.mux.Unlock()
 
@@ -169,3 +178,17 @@ func (kr *KnownRounds) RangeUncheckedMasked(mask *knownRounds.KnownRounds,
 		jww.FATAL.Panicf("Error saving list of checked rounds: %v", err)
 	}
 }
+
+// RangeUncheckedMasked checks rounds based off the provided mask.
+func (kr *KnownRounds) RangeUncheckedMaskedRange(mask *knownRounds.KnownRounds,
+	roundCheck knownRounds.RoundCheckFunc, start, end id.Round, maxChecked int) {
+	kr.mux.Lock()
+	defer kr.mux.Unlock()
+
+	kr.rounds.RangeUncheckedMaskedRange(mask, roundCheck, start, end, maxChecked)
+
+	err := kr.save()
+	if err != nil {
+		jww.FATAL.Panicf("Error saving list of checked rounds: %v", err)
+	}
+}
diff --git a/storage/utility/knownRounds_test.go b/storage/utility/knownRounds_test.go
index 73f0cb5a38d2ef39b33d57ea1ae2892d335d015c..653025dbb46282006abdafdbf6733e591ade0705 100644
--- a/storage/utility/knownRounds_test.go
+++ b/storage/utility/knownRounds_test.go
@@ -28,7 +28,8 @@ func TestNewKnownRounds(t *testing.T) {
 	}
 
 	// Create new KnownRounds
-	kr, err := NewKnownRounds(rootKv, expectedKR.key, size)
+	k := knownRounds.NewKnownRound(size)
+	kr, err := NewKnownRounds(rootKv, expectedKR.key, k)
 	if err != nil {
 		t.Errorf("NewKnownRounds() returned an error."+
 			"\n\texpected: %v\n\treceived: %v", nil, err)
@@ -154,7 +155,8 @@ func TestKnownRounds_save(t *testing.T) {
 // }
 
 func TestKnownRounds_Smoke(t *testing.T) {
-	kr, err := NewKnownRounds(versioned.NewKV(make(ekv.Memstore)), "testKey", 10)
+	k := knownRounds.NewKnownRound(10)
+	kr, err := NewKnownRounds(versioned.NewKV(make(ekv.Memstore)), "testKey", k)
 	if err != nil {
 		t.Fatalf("Failed to create new KnownRounds: %v", err)
 	}
diff --git a/ud/lookup_test.go b/ud/lookup_test.go
index d732c7004f8f0bdf9f35291006cf08b93ae10b91..6bd9b7357855ef99f55d0fcdced916cfcba0d787 100644
--- a/ud/lookup_test.go
+++ b/ud/lookup_test.go
@@ -18,6 +18,7 @@ import (
 	"gitlab.com/xx_network/crypto/csprng"
 	"gitlab.com/xx_network/crypto/large"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
 	"gitlab.com/xx_network/primitives/ndf"
 	"math/rand"
 	"reflect"
@@ -352,8 +353,8 @@ func (t *testNetworkManager) SendUnsafe(m message.Send, _ params.Unsafe) ([]id.R
 	return rounds, nil
 }
 
-func (t *testNetworkManager) SendCMIX(format.Message, params.CMIX) (id.Round, error) {
-	return 0, nil
+func (t *testNetworkManager) SendCMIX(format.Message, *id.ID, params.CMIX) (id.Round, ephemeral.Id, error) {
+	return 0, ephemeral.Id{}, nil
 }
 
 func (t *testNetworkManager) GetInstance() *network.Instance {
diff --git a/ud/register.go b/ud/register.go
index c280ce58ded85c05c859849b1a170e39d0dbdd73..764b8a2b96ee03e75b3eba91e44a2f31f4590f3b 100644
--- a/ud/register.go
+++ b/ud/register.go
@@ -20,7 +20,7 @@ type registerUserComms interface {
 // network signatures are malformed or if the username is taken. Usernames cannot
 // be changed after registration at this time. Will fail if the user is already
 // registered.
-// Registration does not go over cmix, it occurs over normal communications
+// Identity does not go over cmix, it occurs over normal communications
 func (m *Manager) Register(username string) error {
 	jww.INFO.Printf("ud.Register(%s)", username)
 	return m.register(username, m.comms)