Skip to content
Snippets Groups Projects
Commit 372c23f8 authored by Benjamin Wenger's avatar Benjamin Wenger
Browse files

Merge branch 'XX-3077/partnerRelationshipFingerprint' into 'release'

XX-3077/ Relationship Fingerprint

See merge request !624
parents 282de08b bced126a
No related branches found
No related tags found
1 merge request!23Release
...@@ -125,3 +125,17 @@ func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact { ...@@ -125,3 +125,17 @@ func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact {
Facts: make([]fact.Fact, 0), 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
}
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/contact"
"gitlab.com/xx_network/primitives/id"
) )
// Create an insecure e2e relationship with a precanned user // Create an insecure e2e relationship with a precanned user
...@@ -123,3 +124,15 @@ func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (b ...@@ -123,3 +124,15 @@ func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (b
return c.api.VerifyOwnership(received, verified), nil 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)
}
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
package e2e package e2e
import ( import (
"bytes"
"encoding/base64"
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
...@@ -17,6 +19,8 @@ import ( ...@@ -17,6 +19,8 @@ import (
"gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/cyclic"
dh "gitlab.com/elixxir/crypto/diffieHellman" dh "gitlab.com/elixxir/crypto/diffieHellman"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"golang.org/x/crypto/blake2b"
"sort"
) )
const managerPrefix = "Manager{partner:%s}" const managerPrefix = "Manager{partner:%s}"
...@@ -198,3 +202,24 @@ func (m *Manager) GetMyOriginPrivateKey() *cyclic.Int { ...@@ -198,3 +202,24 @@ func (m *Manager) GetMyOriginPrivateKey() *cyclic.Int {
func (m *Manager) GetPartnerOriginPublicKey() *cyclic.Int { func (m *Manager) GetPartnerOriginPublicKey() *cyclic.Int {
return m.originPartnerPubKey.DeepCopy() 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]
}
...@@ -9,12 +9,14 @@ package e2e ...@@ -9,12 +9,14 @@ package e2e
import ( import (
"bytes" "bytes"
"encoding/base64"
"fmt" "fmt"
"gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/params"
"gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv" "gitlab.com/elixxir/ekv"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/netTime"
"golang.org/x/crypto/blake2b"
"math/rand" "math/rand"
"reflect" "reflect"
"testing" "testing"
...@@ -283,3 +285,65 @@ func managersEqual(expected, received *Manager, t *testing.T) bool { ...@@ -283,3 +285,65 @@ func managersEqual(expected, received *Manager, t *testing.T) bool {
return equal 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
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment