diff --git a/auth/utils_test.go b/auth/utils_test.go
index 5f27a218e0651736ace0ca165ef44e0ef581b05d..0fd05d2aecffd239ee13ae6f09dd4725c42a3bb3 100644
--- a/auth/utils_test.go
+++ b/auth/utils_test.go
@@ -62,8 +62,8 @@ func (m mockE2eHandler) StartProcesses() (stoppable.Stoppable, error) {
 
 func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID,
 	payload []byte, params e2e.Params) ([]id.Round, cryptoE2e.MessageID,
-	time.Time, error) {
-	return nil, cryptoE2e.MessageID{}, time.Time{}, nil
+	time.Time, cryptoE2e.KeyResidue, error) {
+	return nil, cryptoE2e.MessageID{}, time.Time{}, cryptoE2e.KeyResidue{}, nil
 }
 
 func (m mockE2eHandler) RegisterListener(senderID *id.ID,
diff --git a/bindings/connect.go b/bindings/connect.go
index 912ee6ffa9744e12a5b44ae626a198cb6e9bb36e..75e1d7f4045f33ffd1d6eaecbe5019ae4c9305ca 100644
--- a/bindings/connect.go
+++ b/bindings/connect.go
@@ -85,7 +85,7 @@ func (c *Cmix) Connect(e2eId int, recipientContact, e2eParamsJSON []byte) (
 //  - []byte - the JSON marshalled bytes of the E2ESendReport object, which can
 //    be passed into Cmix.WaitForRoundResult to see if the send succeeded.
 func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) {
-	rounds, mid, ts, err := c.connection.SendE2E(catalog.MessageType(mt), payload,
+	rounds, mid, ts, keyResidue, err := c.connection.SendE2E(catalog.MessageType(mt), payload,
 		c.params.Base)
 
 	if err != nil {
@@ -96,6 +96,7 @@ func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) {
 		RoundsList: makeRoundsList(rounds...),
 		MessageID:  mid.Marshal(),
 		Timestamp:  ts.UnixNano(),
+		KeyResidue: keyResidue,
 	}
 
 	return json.Marshal(&sr)
diff --git a/bindings/e2eHandler.go b/bindings/e2eHandler.go
index b71d6646d85eec5cea9a4450979d75003e20b9d2..a80e23e08d9a47d17446b2474fbfe0157a7021dc 100644
--- a/bindings/e2eHandler.go
+++ b/bindings/e2eHandler.go
@@ -33,6 +33,8 @@ type E2ESendReport struct {
 	RoundsList
 	MessageID []byte
 	Timestamp int64
+	// todo: make marshal function
+	KeyResidue []byte
 }
 
 // GetReceptionID returns the marshalled default IDs.
@@ -133,7 +135,7 @@ func (e *E2e) SendE2E(messageType int, recipientId, payload,
 		return nil, err
 	}
 
-	roundIds, messageId, ts, err := e.api.GetE2E().SendE2E(
+	roundIds, messageId, ts, keyResidue, err := e.api.GetE2E().SendE2E(
 		catalog.MessageType(messageType), recipient, payload, params)
 	if err != nil {
 		return nil, err
@@ -143,6 +145,7 @@ func (e *E2e) SendE2E(messageType int, recipientId, payload,
 		RoundsList: makeRoundsList(roundIds...),
 		MessageID:  messageId.Marshal(),
 		Timestamp:  ts.UnixNano(),
+		KeyResidue: keyResidue,
 	}
 	return json.Marshal(result)
 }
diff --git a/cmd/connect.go b/cmd/connect.go
index e8697dc60b8f0b5181df175274e12e881ce12b78..bb1e9ff171fbbbb8c2afd4ace614122ba1927e16 100644
--- a/cmd/connect.go
+++ b/cmd/connect.go
@@ -486,7 +486,7 @@ func miscConnectionFunctions(user *xxdk.E2e, conn connect.Connection) {
 			conn.GetPartner().PartnerId())
 		payload := []byte(msgBody)
 		for {
-			roundIDs, _, _, err := conn.SendE2E(catalog.XxMessage, payload,
+			roundIDs, _, _, _, err := conn.SendE2E(catalog.XxMessage, payload,
 				paramsE2E)
 			if err != nil {
 				jww.FATAL.Panicf("[CONN] Failed to send E2E message: %v", err)
diff --git a/cmd/root.go b/cmd/root.go
index 837b68e1af7d13f8476844c3bb0f525be4bcbd63..6fe4ee7788a006b8e28e01c1df020f4d028fdef2 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -288,7 +288,7 @@ var rootCmd = &cobra.Command{
 								e2eParams.Base)
 						} else {
 							e2eParams.Base.DebugTag = "cmd.E2E"
-							roundIDs, _, _, err = user.GetE2E().SendE2E(mt,
+							roundIDs, _, _, _, err = user.GetE2E().SendE2E(mt,
 								recipient, payload, e2eParams.Base)
 						}
 						if err != nil {
diff --git a/connect/authenticated.go b/connect/authenticated.go
index c45489fbc78ab87ab1115ab6da02d2b0fe5167f4..de3d9e656367c2fa74c1c8dc9ed4475f49aeb3f3 100644
--- a/connect/authenticated.go
+++ b/connect/authenticated.go
@@ -98,7 +98,7 @@ func connectWithAuthentication(conn Connection, timeStart time.Time,
 	}
 
 	// Send message to server
-	rids, _, _, err := conn.SendE2E(catalog.ConnectionAuthenticationRequest,
+	rids, _, _, _, err := conn.SendE2E(catalog.ConnectionAuthenticationRequest,
 		payload, clientE2e.GetDefaultParams())
 	if err != nil {
 		// Close connection on an error
diff --git a/connect/connect.go b/connect/connect.go
index ba87dc91873e5d3153e38c60474d42b2f3e23cbc..8c20cf5693f653828fd60a56bfe11a86299acfe2 100644
--- a/connect/connect.go
+++ b/connect/connect.go
@@ -43,7 +43,7 @@ type Connection interface {
 	// SendE2E is a wrapper for sending specifically to the Connection's
 	// partner.Manager
 	SendE2E(mt catalog.MessageType, payload []byte, params clientE2e.Params) (
-		[]id.Round, e2e.MessageID, time.Time, error)
+		[]id.Round, e2e.MessageID, time.Time, e2e.KeyResidue, error)
 
 	// RegisterListener is used for E2E reception
 	// and allows for reading data sent from the partner.Manager
@@ -221,9 +221,9 @@ func (h *handler) GetPartner() partner.Manager {
 // SendE2E is a wrapper for sending specifically to the Connection's
 // partner.Manager.
 func (h *handler) SendE2E(mt catalog.MessageType, payload []byte,
-	params clientE2e.Params) ([]id.Round, e2e.MessageID, time.Time, error) {
+	params clientE2e.Params) ([]id.Round, e2e.MessageID, time.Time, e2e.KeyResidue, error) {
 	if h.isClosed() {
-		return nil, e2e.MessageID{}, time.Time{}, alreadyClosedErr
+		return nil, e2e.MessageID{}, time.Time{}, e2e.KeyResidue{}, alreadyClosedErr
 	}
 
 	h.updateLastUse(netTime.Now())
diff --git a/connect/utils_test.go b/connect/utils_test.go
index 6e4be5173d00cd8ba4b671d6abee3a8669e1c77c..4414b2e8b4f399ef2884d7c9ed19e4205aef513d 100644
--- a/connect/utils_test.go
+++ b/connect/utils_test.go
@@ -116,7 +116,7 @@ func (m *mockConnection) GetPartner() partner.Manager { return m.partner }
 
 func (m *mockConnection) SendE2E(
 	mt catalog.MessageType, payload []byte, _ e2e.Params) (
-	[]id.Round, cryptoE2e.MessageID, time.Time, error) {
+	[]id.Round, cryptoE2e.MessageID, time.Time, cryptoE2e.KeyResidue, error) {
 	m.payloadChan <- payload
 	m.listener.Hear(receive.Message{
 		MessageType: mt,
@@ -124,7 +124,7 @@ func (m *mockConnection) SendE2E(
 		Sender:      m.partner.myID,
 		RecipientID: m.partner.partnerId,
 	})
-	return nil, cryptoE2e.MessageID{}, time.Time{}, nil
+	return nil, cryptoE2e.MessageID{}, time.Time{}, cryptoE2e.KeyResidue{}, nil
 }
 
 func (m *mockConnection) RegisterListener(
diff --git a/fileTransfer/connect/send.go b/fileTransfer/connect/send.go
index 2b00c8ba71cc8817a2764025ae34f8e4bdcc3438..91dcfb6754610cc95fc9e7a78e01f7dd40f3dbac 100644
--- a/fileTransfer/connect/send.go
+++ b/fileTransfer/connect/send.go
@@ -45,7 +45,7 @@ func sendNewFileTransferMessage(
 	params.LastServiceTag = catalog.Silent
 	params.DebugTag = initialMessageDebugTag
 
-	_, _, _, err := connectionHandler.SendE2E(
+	_, _, _, _, err := connectionHandler.SendE2E(
 		catalog.NewFileTransfer, transferInfo, params)
 	if err != nil {
 		return errors.Errorf(errNewFtSendE2e, err)
@@ -65,7 +65,7 @@ func sendEndFileTransferMessage(cmix ft.Cmix, connectionHandler connection) {
 				params.LastServiceTag = catalog.EndFT
 				params.DebugTag = lastMessageDebugTag
 
-				_, _, _, err := connectionHandler.SendE2E(
+				_, _, _, _, err := connectionHandler.SendE2E(
 					catalog.EndFileTransfer, nil, params)
 				if err != nil {
 					jww.ERROR.Printf(errEndFtSendE2e, err)
diff --git a/fileTransfer/connect/utils_test.go b/fileTransfer/connect/utils_test.go
index 7d0fb6aeba668c2fcccf89cd881746007a84a101..af9990b9c0a3120b79e3960de86dae4ff52107c9 100644
--- a/fileTransfer/connect/utils_test.go
+++ b/fileTransfer/connect/utils_test.go
@@ -268,7 +268,8 @@ func (m *mockConnection) GetPartner() partner.Manager {
 
 // SendE2E adds the message to the e2e handler map.
 func (m *mockConnection) SendE2E(mt catalog.MessageType, payload []byte,
-	_ e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error) {
+	_ e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time,
+	e2eCrypto.KeyResidue, error) {
 	m.handler.Lock()
 	defer m.handler.Unlock()
 
@@ -278,7 +279,8 @@ func (m *mockConnection) SendE2E(mt catalog.MessageType, payload []byte,
 		Sender:      m.myID,
 	})
 
-	return []id.Round{42}, e2eCrypto.MessageID{}, netTime.Now(), nil
+	return []id.Round{42}, e2eCrypto.MessageID{}, netTime.Now(),
+		e2eCrypto.KeyResidue{}, nil
 }
 
 func (m *mockConnection) RegisterListener(mt catalog.MessageType,
diff --git a/fileTransfer/connect/wrapper.go b/fileTransfer/connect/wrapper.go
index 60a3f6641da53aad60d53a29feb533180738556b..b0943f5ebf974092f3da5079c1f087ad4debb631 100644
--- a/fileTransfer/connect/wrapper.go
+++ b/fileTransfer/connect/wrapper.go
@@ -41,7 +41,7 @@ type Wrapper struct {
 type connection interface {
 	GetPartner() partner.Manager
 	SendE2E(mt catalog.MessageType, payload []byte, params e2e.Params) (
-		[]id.Round, e2eCrypto.MessageID, time.Time, error)
+		[]id.Round, e2eCrypto.MessageID, time.Time, e2eCrypto.KeyResidue, error)
 	RegisterListener(messageType catalog.MessageType,
 		newListener receive.Listener) (receive.ListenerID, error)
 }
diff --git a/fileTransfer/e2e/send.go b/fileTransfer/e2e/send.go
index a073d0afe841a04026081b9033e0e1cc5c164062..017313dc266fe88d3d11817a638b4870045bee30 100644
--- a/fileTransfer/e2e/send.go
+++ b/fileTransfer/e2e/send.go
@@ -46,7 +46,7 @@ func sendNewFileTransferMessage(
 	params.LastServiceTag = catalog.Silent
 	params.DebugTag = initialMessageDebugTag
 
-	_, _, _, err := e2eHandler.SendE2E(
+	_, _, _, _, err := e2eHandler.SendE2E(
 		catalog.NewFileTransfer, recipient, transferInfo, params)
 	if err != nil {
 		return errors.Errorf(errNewFtSendE2e, err)
@@ -66,7 +66,7 @@ func sendEndFileTransferMessage(recipient *id.ID, cmix ft.Cmix, e2eHandler e2eHa
 				params.LastServiceTag = catalog.EndFT
 				params.DebugTag = lastMessageDebugTag
 
-				_, _, _, err := e2eHandler.SendE2E(
+				_, _, _, _, err := e2eHandler.SendE2E(
 					catalog.EndFileTransfer, recipient, nil, params)
 				if err != nil {
 					jww.ERROR.Printf(errEndFtSendE2e, err)
diff --git a/fileTransfer/e2e/utils_test.go b/fileTransfer/e2e/utils_test.go
index 164d155740c789916f1ff5a96b3bd3c89079c61f..c2ecdd01a352f7d46f9e4ea0510072696a9cafd2 100644
--- a/fileTransfer/e2e/utils_test.go
+++ b/fileTransfer/e2e/utils_test.go
@@ -259,7 +259,7 @@ func (m *mockE2e) StartProcesses() (stoppable.Stoppable, error) { panic("impleme
 
 // SendE2E adds the message to the e2e handler map.
 func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID,
-	payload []byte, _ e2e.Params) ([]id.Round, e.MessageID, time.Time, error) {
+	payload []byte, _ e2e.Params) ([]id.Round, e.MessageID, time.Time, e.KeyResidue, error) {
 
 	m.handler.listeners[mt].Hear(receive.Message{
 		MessageType: mt,
@@ -268,7 +268,7 @@ func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID,
 		RecipientID: recipient,
 	})
 
-	return []id.Round{42}, e.MessageID{}, netTime.Now(), nil
+	return []id.Round{42}, e.MessageID{}, netTime.Now(), e.KeyResidue{}, nil
 }
 
 func (m *mockE2e) RegisterListener(_ *id.ID, mt catalog.MessageType,
diff --git a/fileTransfer/e2e/wrapper.go b/fileTransfer/e2e/wrapper.go
index e27c281c9dfc490d271b3d225b73643b9e75cfa2..12b44091b46911061491ecf2d030bc5ede21966c 100644
--- a/fileTransfer/e2e/wrapper.go
+++ b/fileTransfer/e2e/wrapper.go
@@ -39,7 +39,8 @@ type Wrapper struct {
 // for easier testing.
 type e2eHandler interface {
 	SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte,
-		params e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error)
+		params e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time,
+		e2eCrypto.KeyResidue, error)
 	RegisterListener(senderID *id.ID, messageType catalog.MessageType,
 		newListener receive.Listener) receive.ListenerID
 }
diff --git a/groupChat/e2eManager_test.go b/groupChat/e2eManager_test.go
index 37e4019cb8442cf95c8537cbb412d2d4a5d1e585..7bee5fa08696e99c951cc6d1b3bc67bfc2e21d1f 100644
--- a/groupChat/e2eManager_test.go
+++ b/groupChat/e2eManager_test.go
@@ -66,15 +66,15 @@ func (tnm *testE2eManager) GetE2eMsg(i int) testE2eMessage {
 
 func (tnm *testE2eManager) SendE2E(_ catalog.MessageType, recipient *id.ID,
 	payload []byte, _ clientE2E.Params) ([]id.Round, e2e.MessageID, time.Time,
-	error) {
+	e2e.KeyResidue, error) {
 	tnm.Lock()
 	defer tnm.Unlock()
 
 	tnm.errSkip++
 	if tnm.sendErr == 1 {
-		return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error")
+		return nil, e2e.MessageID{}, time.Time{}, e2e.KeyResidue{}, errors.New("SendE2E error")
 	} else if tnm.sendErr == 2 && tnm.errSkip%2 == 0 {
-		return nil, e2e.MessageID{}, time.Time{}, errors.New("SendE2E error")
+		return nil, e2e.MessageID{}, time.Time{}, e2e.KeyResidue{}, errors.New("SendE2E error")
 	}
 
 	tnm.e2eMessages = append(tnm.e2eMessages, testE2eMessage{
@@ -82,7 +82,7 @@ func (tnm *testE2eManager) SendE2E(_ catalog.MessageType, recipient *id.ID,
 		Payload:   payload,
 	})
 
-	return []id.Round{0, 1, 2, 3}, e2e.MessageID{}, time.Time{}, nil
+	return []id.Round{0, 1, 2, 3}, e2e.MessageID{}, time.Time{}, e2e.KeyResidue{}, nil
 }
 
 func (*testE2eManager) RegisterListener(*id.ID, catalog.MessageType, receive.Listener) receive.ListenerID {
diff --git a/groupChat/interface.go b/groupChat/interface.go
index 0355c90943797cb7ab98d7e02e648ba946f1692b..28d7f4e3a305dd04f1408159943c1c606fe68a9e 100644
--- a/groupChat/interface.go
+++ b/groupChat/interface.go
@@ -126,7 +126,7 @@ type groupCmix interface {
 // needed by GroupChat
 type groupE2eHandler interface {
 	SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte,
-		params e2e.Params) ([]id.Round, crypto.MessageID, time.Time, error)
+		params e2e.Params) ([]id.Round, crypto.MessageID, time.Time, crypto.KeyResidue, error)
 	RegisterListener(senderID *id.ID, messageType catalog.MessageType,
 		newListener receive.Listener) receive.ListenerID
 	AddService(tag string, processor message.Processor) error
diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go
index b28985361e09183b6b4d807e10c770b454386bda..43648928b73232bfd078aa4fbd0ad975965659bd 100644
--- a/groupChat/sendRequests.go
+++ b/groupChat/sendRequests.go
@@ -120,7 +120,7 @@ func (m *manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, erro
 	p.LastServiceTag = catalog.GroupRq
 	p.DebugTag = "group.Request"
 
-	rounds, _, _, err := m.getE2eHandler().SendE2E(
+	rounds, _, _, _, err := m.getE2eHandler().SendE2E(
 		catalog.GroupCreationRequest, memberID, request, p)
 	if err != nil {
 		return nil, errors.Errorf(sendE2eErr, memberID, err)
diff --git a/restlike/connect/receiver.go b/restlike/connect/receiver.go
index d6e87c57489a4235cd0e225fb38c4c87dad4afc3..051a91d3f1b1983307ac2372360e5f05f22c1871 100644
--- a/restlike/connect/receiver.go
+++ b/restlike/connect/receiver.go
@@ -55,7 +55,7 @@ func respond(response *restlike.Message, conn connect.Connection) error {
 	}
 
 	// TODO: Parameterize params
-	_, _, _, err = conn.SendE2E(catalog.XxMessage, payload, e2e.GetDefaultParams())
+	_, _, _, _, err = conn.SendE2E(catalog.XxMessage, payload, e2e.GetDefaultParams())
 	if err != nil {
 		return errors.Errorf("unable to send restlike response message: %+v", err)
 	}
diff --git a/restlike/connect/request.go b/restlike/connect/request.go
index 4ea32656a2f3716481153e1955d0435311b61244..7d0b435c0aa3188f006535652d8b74aa691a0685 100644
--- a/restlike/connect/request.go
+++ b/restlike/connect/request.go
@@ -49,7 +49,8 @@ func (s *Request) Request(method restlike.Method, path restlike.URI,
 	s.Net.RegisterListener(catalog.XxMessage, &response{responseCallback: cb})
 
 	// Transmit the Message
-	_, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams)
+	// fixme: should this use the key residue?
+	_, _, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams)
 	if err != nil {
 		return nil, err
 	}
@@ -84,6 +85,7 @@ func (s *Request) AsyncRequest(method restlike.Method, path restlike.URI,
 	s.Net.RegisterListener(catalog.XxMessage, &response{responseCallback: cb})
 
 	// Transmit the Message
-	_, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams)
+	// fixme: should this use the key residue?
+	_, _, _, _, err = s.Net.SendE2E(catalog.XxMessage, msg, e2eParams)
 	return err
 }
diff --git a/ud/mockE2e_test.go b/ud/mockE2e_test.go
index c57e148fe6a63845a480bebb1aa939789b600bfc..33b1e543aec380a1d1effeeb41371eaa1773b453 100644
--- a/ud/mockE2e_test.go
+++ b/ud/mockE2e_test.go
@@ -109,7 +109,7 @@ func (m mockE2eHandler) StartProcesses() (stoppable.Stoppable, error) {
 	panic("implement me")
 }
 
-func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params e2e.Params) ([]id.Round, cryptoE2e.MessageID, time.Time, error) {
+func (m mockE2eHandler) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params e2e.Params) ([]id.Round, cryptoE2e.MessageID, time.Time, cryptoE2e.KeyResidue, error) {
 	//TODO implement me
 	panic("implement me")
 }