diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go
index 88682af983c107345b6415648bec9558f2eb4d6b..24b5a8e4af3c771d59dabc3e01d6ffa1b8125a17 100644
--- a/api/authenticatedChannel.go
+++ b/api/authenticatedChannel.go
@@ -125,3 +125,17 @@ func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact {
 		Facts:          make([]fact.Fact, 0),
 	}
 }
+
+// GetRelationshipFingerprint returns a unique 15 character fingerprint for an
+// E2E relationship. An error is returned if no relationship with the partner
+// is found.
+func (c *Client) GetRelationshipFingerprint(partner *id.ID) (string, error) {
+	m, err := c.storage.E2e().GetPartner(partner)
+	if err != nil {
+		return "", errors.Errorf("could not get partner %s: %+v", partner, err)
+	} else if m == nil {
+		return "", errors.Errorf("manager for partner %s is nil.", partner)
+	}
+
+	return m.GetRelationshipFingerprint(), nil
+}
diff --git a/bindings/authenticatedChannels.go b/bindings/authenticatedChannels.go
index 30b12f0a1b3039fba5b18eafeff874cc7a438a60..da1d0d7ea128c15a6e4d407f8a7a88430666fd16 100644
--- a/bindings/authenticatedChannels.go
+++ b/bindings/authenticatedChannels.go
@@ -11,6 +11,7 @@ import (
 	"errors"
 	"fmt"
 	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/xx_network/primitives/id"
 )
 
 // Create an insecure e2e relationship with a precanned user
@@ -123,3 +124,15 @@ func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (b
 
 	return c.api.VerifyOwnership(received, verified), nil
 }
+
+// GetRelationshipFingerprint returns a unique 15 character fingerprint for an
+// E2E relationship. An error is returned if no relationship with the partner
+// is found.
+func (c *Client) GetRelationshipFingerprint(partnerID []byte) (string, error) {
+	partner, err := id.Unmarshal(partnerID)
+	if err != nil {
+		return "", err
+	}
+
+	return c.api.GetRelationshipFingerprint(partner)
+}
diff --git a/storage/e2e/manager.go b/storage/e2e/manager.go
index 802e81ebe2329f5bd3714500e0229071eaea3bd3..6d7691b2b8f402c92ea6d4615a175b0b14b4b61e 100644
--- a/storage/e2e/manager.go
+++ b/storage/e2e/manager.go
@@ -8,6 +8,8 @@
 package e2e
 
 import (
+	"bytes"
+	"encoding/base64"
 	"fmt"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
@@ -17,6 +19,8 @@ import (
 	"gitlab.com/elixxir/crypto/cyclic"
 	dh "gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/xx_network/primitives/id"
+	"golang.org/x/crypto/blake2b"
+	"sort"
 )
 
 const managerPrefix = "Manager{partner:%s}"
@@ -198,3 +202,24 @@ func (m *Manager) GetMyOriginPrivateKey() *cyclic.Int {
 func (m *Manager) GetPartnerOriginPublicKey() *cyclic.Int {
 	return m.originPartnerPubKey.DeepCopy()
 }
+
+const relationshipFpLength = 15
+
+// GetRelationshipFingerprint returns a unique fingerprint for an E2E
+// relationship. The fingerprint is a base 64 encoded hash of of the two
+// relationship fingerprints truncated to 15 characters.
+func (m *Manager) GetRelationshipFingerprint() string {
+	// Sort fingerprints
+	fps := [][]byte{m.receive.fingerprint, m.send.fingerprint}
+	less := func(i, j int) bool { return bytes.Compare(fps[i], fps[j]) == -1 }
+	sort.Slice(fps, less)
+
+	// Hash fingerprints
+	h, _ := blake2b.New256(nil)
+	for _, fp := range fps {
+		h.Write(fp)
+	}
+
+	// Base 64 encode hash and truncate
+	return base64.StdEncoding.EncodeToString(h.Sum(nil))[:relationshipFpLength]
+}
diff --git a/storage/e2e/manager_test.go b/storage/e2e/manager_test.go
index 907bbff91b561d2267b71371356ae7bf6f332b86..195b0752a603002dcb395507fc0b7d361a0b235a 100644
--- a/storage/e2e/manager_test.go
+++ b/storage/e2e/manager_test.go
@@ -9,12 +9,14 @@ package e2e
 
 import (
 	"bytes"
+	"encoding/base64"
 	"fmt"
 	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/ekv"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/netTime"
+	"golang.org/x/crypto/blake2b"
 	"math/rand"
 	"reflect"
 	"testing"
@@ -283,3 +285,65 @@ func managersEqual(expected, received *Manager, t *testing.T) bool {
 
 	return equal
 }
+
+// Unit test of Manager.GetRelationshipFingerprint.
+func TestManager_GetRelationshipFingerprint(t *testing.T) {
+	m, _ := newTestManager(t)
+	m.receive.fingerprint = []byte{5}
+	m.send.fingerprint = []byte{10}
+	h, _ := blake2b.New256(nil)
+	h.Write(append(m.receive.fingerprint, m.send.fingerprint...))
+	expected := base64.StdEncoding.EncodeToString(h.Sum(nil))[:relationshipFpLength]
+
+	fp := m.GetRelationshipFingerprint()
+	if fp != expected {
+		t.Errorf("GetRelationshipFingerprint did not return the expected "+
+			"fingerprint.\nexpected: %s\nreceived: %s", expected, fp)
+	}
+
+	// Flip the order and show that the output is the same.
+	m.receive.fingerprint, m.send.fingerprint = m.send.fingerprint, m.receive.fingerprint
+
+	fp = m.GetRelationshipFingerprint()
+	if fp != expected {
+		t.Errorf("GetRelationshipFingerprint did not return the expected "+
+			"fingerprint.\nexpected: %s\nreceived: %s", expected, fp)
+	}
+}
+
+// Tests the consistency of the output of Manager.GetRelationshipFingerprint.
+func TestManager_GetRelationshipFingerprint_Consistency(t *testing.T) {
+	m, _ := newTestManager(t)
+	prng := rand.New(rand.NewSource(42))
+	expectedFps := []string{
+		"GmeTCfxGOqRqeID", "gbpJjHd3tIe8BKy", "2/ZdG+WNzODJBiF",
+		"+V1ySeDLQfQNSkv", "23OMC+rBmCk+gsu", "qHu5MUVs83oMqy8",
+		"kuXqxsezI0kS9Bc", "SlEhsoZ4BzAMTtr", "yG8m6SPQfV/sbTR",
+		"j01ZSSm762TH7mj", "SKFDbFvsPcohKPw", "6JB5HK8DHGwS4uX",
+		"dU3mS1ujduGD+VY", "BDXAy3trbs8P4mu", "I4HoXW45EwWR0oD",
+		"661YH2l2jfOkHbA", "cSS9ZyTOQKVx67a", "ojfubzDIsMNYc/t",
+		"2WrEw83Yz6Rhq9I", "TQILxBIUWMiQS2j", "rEqdieDTXJfCQ6I",
+	}
+
+	for i, expected := range expectedFps {
+		prng.Read(m.receive.fingerprint)
+		prng.Read(m.send.fingerprint)
+
+		fp := m.GetRelationshipFingerprint()
+		if fp != expected {
+			t.Errorf("GetRelationshipFingerprint did not return the expected "+
+				"fingerprint (%d).\nexpected: %s\nreceived: %s", i, expected, fp)
+		}
+
+		// Flip the order and show that the output is the same.
+		m.receive.fingerprint, m.send.fingerprint = m.send.fingerprint, m.receive.fingerprint
+
+		fp = m.GetRelationshipFingerprint()
+		if fp != expected {
+			t.Errorf("GetRelationshipFingerprint did not return the expected "+
+				"fingerprint (%d).\nexpected: %s\nreceived: %s", i, expected, fp)
+		}
+
+		// fmt.Printf("\"%s\",\n", fp) // Uncomment to reprint expected values
+	}
+}