diff --git a/auth/interface.go b/auth/interface.go
index 97c970f30effbbf484e52808dcd1421265d03a17..40f5e72e4ddefcb46bb716765cc163dca94876a6 100644
--- a/auth/interface.go
+++ b/auth/interface.go
@@ -107,6 +107,7 @@ type State interface {
 }
 
 // Callbacks is the interface for auth callback methods.
+// TODO: Document this
 type Callbacks interface {
 	Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
 		round rounds.Round)
diff --git a/bindings/contact.go b/bindings/contact.go
index 9f808f66ae7059ee86b698dda93583a9a60a9cae..c07b66f8f790eb9ffb4bdf0081aad25c32c8185c 100644
--- a/bindings/contact.go
+++ b/bindings/contact.go
@@ -68,30 +68,30 @@ func (c *Cmix) GetContactFromIdentity(identity []byte) ([]byte, error) {
 	return ct.Marshal(), nil
 }
 
-func (c *Cmix) unmarshalIdentity(marshaled []byte) (*xxdk.TransmissionIdentity, error) {
-	newIdentity := &xxdk.TransmissionIdentity{}
+func (c *Cmix) unmarshalIdentity(marshaled []byte) (xxdk.TransmissionIdentity, error) {
+	newIdentity := xxdk.TransmissionIdentity{}
 
 	// Unmarshal given identity into TransmissionIdentity object
 	givenIdentity := TransmissionIdentity{}
 	err := json.Unmarshal(marshaled, &givenIdentity)
 	if err != nil {
-		return nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
 	newIdentity.ID, err = id.Unmarshal(givenIdentity.ID)
 	if err != nil {
-		return nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
 	newIdentity.DHKeyPrivate = c.api.GetStorage().GetE2EGroup().NewInt(1)
 	err = newIdentity.DHKeyPrivate.UnmarshalJSON(givenIdentity.DHKeyPrivate)
 	if err != nil {
-		return nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
 	newIdentity.RSAPrivatePem, err = rsa.LoadPrivateKeyFromPem(givenIdentity.RSAPrivatePem)
 	if err != nil {
-		return nil, err
+		return xxdk.TransmissionIdentity{}, err
 	}
 
 	newIdentity.Salt = givenIdentity.Salt
diff --git a/bindings/e2e.go b/bindings/e2e.go
index 7af7ea0d84bb39d4c7173b6c0c18672f35622878..6134db25db442727b6d32873f1f11d795f8d8f2c 100644
--- a/bindings/e2e.go
+++ b/bindings/e2e.go
@@ -29,49 +29,42 @@ type E2e struct {
 }
 
 // Login creates and returns a new E2e object and adds it to the e2eTrackerSingleton
-// identity can be left nil such that a new TransmissionIdentity will be created automatically
-// callbacks can be left nil and a default will be used
+// identity should be created via MakeIdentity() and passed in here
+// If callbacks is left nil, a default auth.Callbacks will be used
 func (e *E2e) Login(cmixId int, callbacks AuthCallbacks, identity []byte) (*E2e, error) {
 	cmix, err := cmixTrackerSingleton.get(cmixId)
 	if err != nil {
 		return nil, err
 	}
 
-	newIdentity := &xxdk.TransmissionIdentity{}
-	if identity == nil {
-		newIdentity = nil
-	} else {
-		newIdentity, err = cmix.unmarshalIdentity(identity)
-		if err != nil {
-			return nil, err
-		}
+	newIdentity, err := cmix.unmarshalIdentity(identity)
+	if err != nil {
+		return nil, err
 	}
 
+	var authCallbacks auth.Callbacks
 	if callbacks == nil {
-		authCallbacks := auth.DefaultAuthCallbacks{}
-		newE2e, err := xxdk.Login(cmix.api, authCallbacks, newIdentity)
-		if err != nil {
-			return nil, err
-		}
-		return e2eTrackerSingleton.make(newE2e), nil
+		authCallbacks = auth.DefaultAuthCallbacks{}
 	} else {
-		authCallbacks := &authCallback{bindingsCbs: callbacks}
-		newE2e, err := xxdk.Login(cmix.api, authCallbacks, newIdentity)
-		if err != nil {
-			return nil, err
-		}
-		return e2eTrackerSingleton.make(newE2e), nil
+		authCallbacks = &authCallback{bindingsCbs: callbacks}
+	}
+
+	newE2e, err := xxdk.Login(cmix.api, authCallbacks, newIdentity)
+	if err != nil {
+		return nil, err
 	}
+	return e2eTrackerSingleton.make(newE2e), nil
 }
 
 // AuthCallbacks is the bindings-specific interface for auth.Callbacks methods.
 type AuthCallbacks interface {
-	Request(contact, receptionId []byte, ephemeralId, roundId uint64)
-	Confirm(contact, receptionId []byte, ephemeralId, roundId uint64)
-	Reset(contact, receptionId []byte, ephemeralId, roundId uint64)
+	Request(contact, receptionId []byte, ephemeralId, roundId int64)
+	Confirm(contact, receptionId []byte, ephemeralId, roundId int64)
+	Reset(contact, receptionId []byte, ephemeralId, roundId int64)
 }
 
-// authCallback implements AuthCallbacks
+// authCallback implements AuthCallbacks as a way of obtaining
+// an auth.Callbacks over the bindings
 type authCallback struct {
 	bindingsCbs AuthCallbacks
 }
@@ -79,12 +72,12 @@ type authCallback struct {
 // convertAuthCallbacks turns an auth.Callbacks into an AuthCallbacks
 func convertAuthCallbacks(requestor contact.Contact,
 	receptionID receptionID.EphemeralIdentity,
-	round rounds.Round) (contact []byte, receptionId []byte, ephemeralId uint64, roundId uint64) {
+	round rounds.Round) (contact []byte, receptionId []byte, ephemeralId int64, roundId int64) {
 
 	contact = requestor.Marshal()
 	receptionId = receptionID.Source.Marshal()
-	ephemeralId = receptionID.EphId.UInt64()
-	roundId = uint64(round.ID)
+	ephemeralId = int64(receptionID.EphId.UInt64())
+	roundId = int64(round.ID)
 	return
 }
 
diff --git a/bindings/e2eTracker.go b/bindings/e2eTracker.go
index d42ba27ccd9d8d1f004c8035f0cb89130fbb174b..8f3ff5374ddb048642eeeda0a74a04a7f6bc3c44 100644
--- a/bindings/e2eTracker.go
+++ b/bindings/e2eTracker.go
@@ -15,6 +15,7 @@ import (
 // e2eTracker is a singleton used to keep track of extant E2e objects,
 // preventing race conditions created by passing it over the bindings
 type e2eTracker struct {
+	// TODO: Key on Identity.ID to prevent duplication
 	clients map[int]*E2e
 	count   int
 	mux     sync.RWMutex
diff --git a/xxdk/e2e.go b/xxdk/e2e.go
index 57fc30cd74235cb0c777b72dcf8e01c1dfd3dbbc..c3536ec8eb316f61bfc49643ab903ee393b1a99b 100644
--- a/xxdk/e2e.go
+++ b/xxdk/e2e.go
@@ -11,6 +11,7 @@ import (
 	"encoding/json"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
+	"gitlab.com/xx_network/crypto/xx"
 	"time"
 
 	"github.com/pkg/errors"
@@ -37,14 +38,14 @@ type E2e struct {
 // Login creates a new E2e backed by the xxdk.Cmix persistent versioned.KV
 // If identity == nil, a new TransmissionIdentity will be generated automagically
 func Login(client *Cmix, callbacks auth.Callbacks,
-	identity *TransmissionIdentity) (m *E2e, err error) {
+	identity TransmissionIdentity) (m *E2e, err error) {
 	return login(client, callbacks, identity, client.GetStorage().GetKV())
 }
 
 // LoginEphemeral creates a new E2e backed by a totally ephemeral versioned.KV
 // If identity == nil, a new TransmissionIdentity will be generated automagically
 func LoginEphemeral(client *Cmix, callbacks auth.Callbacks,
-	identity *TransmissionIdentity) (m *E2e, err error) {
+	identity TransmissionIdentity) (m *E2e, err error) {
 	return login(client, callbacks, identity, versioned.NewKV(ekv.MakeMemstore()))
 }
 
@@ -83,25 +84,23 @@ func LoginLegacy(client *Cmix, callbacks auth.Callbacks) (m *E2e, err error) {
 
 // login creates a new e2eApi.E2e backed by the given versioned.KV
 func login(client *Cmix, callbacks auth.Callbacks,
-	identity *TransmissionIdentity, kv *versioned.KV) (m *E2e, err error) {
-	e2eGrp := client.GetStorage().GetE2EGroup()
+	identity TransmissionIdentity, kv *versioned.KV) (m *E2e, err error) {
 
-	// Create new identity automatically if one isn't specified
-	if identity == nil {
-		rng := client.GetRng().GetStream()
-		newIdentity, err := MakeTransmissionIdentity(rng, e2eGrp)
-		rng.Close()
-		if err != nil {
-			return nil, err
-		}
-		identity = &newIdentity
-		client.GetCmix().AddIdentity(identity.ID, time.Time{}, !kv.IsMemStore())
+	// Verify the passed-in TransmissionIdentity matches its properties
+	generatedId, err := xx.NewID(identity.RSAPrivatePem.GetPublic(), identity.Salt, id.User)
+	if err != nil {
+		return nil, err
+	}
+	if !generatedId.Cmp(identity.ID) {
+		return nil, errors.Errorf("Given identity %s is invalid, generated ID does not match",
+			identity.ID.String())
 	}
 
+	e2eGrp := client.GetStorage().GetE2EGroup()
 	m = &E2e{
 		Cmix:        client,
 		backup:      &Container{},
-		e2eIdentity: *identity,
+		e2eIdentity: identity,
 	}
 
 	//initialize the e2e storage