From 90237695757bf665f609a8fd9f78cba03bb34678 Mon Sep 17 00:00:00 2001 From: Benjamin Wenger <ben@elixxir.ioo> Date: Fri, 29 Jan 2021 12:53:43 -0800 Subject: [PATCH] partially tested reception store, updated sendCMIX for ephemeral IDs --- api/send.go | 11 ++--- auth/confirm.go | 3 +- auth/request.go | 5 +- bindings/send.go | 5 +- go.mod | 4 +- go.sum | 5 ++ interfaces/message/receiveMessage.go | 3 ++ interfaces/networkManager.go | 3 +- keyExchange/utils_test.go | 9 ++-- network/message/critical.go | 2 +- network/message/handler.go | 9 +++- network/message/sendCmix.go | 35 ++++++++++--- network/message/sendE2E.go | 3 +- network/message/sendUnsafe.go | 3 +- network/send.go | 7 +-- storage/reception/IdentityUse.go | 13 ++--- storage/reception/fake.go | 8 ++- storage/reception/fake_test.go | 40 +++++++++++++++ storage/reception/identity.go | 3 +- storage/reception/identityUse_test.go | 68 ++++++++++++++++++++++++++ storage/reception/identity_test.go | 42 +++++++++++++++- storage/reception/registration.go | 4 +- storage/reception/registration_test.go | 54 ++++++++++++++++++++ storage/reception/store.go | 6 +-- storage/session.go | 7 --- ud/lookup_test.go | 5 +- 26 files changed, 296 insertions(+), 61 deletions(-) create mode 100644 storage/reception/fake_test.go create mode 100644 storage/reception/identityUse_test.go create mode 100644 storage/reception/registration_test.go diff --git a/api/send.go b/api/send.go index 84256b206..19d6a54b8 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 a58306c2d..4a1d27cde 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 5ba9d412b..2c73521dc 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 f9c116d5b..6b2c1e33d 100644 --- a/bindings/send.go +++ b/bindings/send.go @@ -30,6 +30,7 @@ import ( // This will return the round the message was sent on if it is successfully sent // This can be used to register a round event to learn about message delivery. // on failure a round id of -1 is returned +// todo- return the ephemeral ID func (c *Client) SendCmix(recipient, contents []byte) (int, error) { u, err := id.Unmarshal(recipient) if err != nil { @@ -37,13 +38,13 @@ func (c *Client) SendCmix(recipient, contents []byte) (int, error) { 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, params.GetDefaultCMIX()) + rid, _, err := c.api.SendCMIX(msg, u, params.GetDefaultCMIX()) if err != nil { return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v", err)) diff --git a/go.mod b/go.mod index 2487cca13..4cc442b1e 100644 --- a/go.mod +++ b/go.mod @@ -21,12 +21,12 @@ require ( 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/crypto v0.0.7-0.20210114172156-b576829ba7d8 gitlab.com/elixxir/ekv v0.1.4 gitlab.com/elixxir/primitives v0.0.3-0.20210127201240-6a42ad925e8a 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.20210121231232-022320b01e08 + gitlab.com/xx_network/primitives v0.0.4-0.20210129204839-cc84bb5a253b 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 2c7a05e3a..4f42c98a8 100644 --- a/go.sum +++ b/go.sum @@ -283,6 +283,7 @@ gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptC 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.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 +291,8 @@ 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.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/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= @@ -359,6 +362,8 @@ gitlab.com/xx_network/primitives v0.0.4-0.20210120193504-6fb365621996 h1:ChTPjKV gitlab.com/xx_network/primitives v0.0.4-0.20210120193504-6fb365621996/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= gitlab.com/xx_network/primitives v0.0.4-0.20210121231232-022320b01e08 h1:NZl2gjkiSZQVls4dHys+EoE6eGIU2YBXKqLaBVuV+b0= gitlab.com/xx_network/primitives v0.0.4-0.20210121231232-022320b01e08/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE= +gitlab.com/xx_network/primitives v0.0.4-0.20210129204839-cc84bb5a253b h1:zKtKCoScDcJM8/nBC4U5uhjifDHHcND3vKm1gfoc5yQ= +gitlab.com/xx_network/primitives v0.0.4-0.20210129204839-cc84bb5a253b/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= diff --git a/interfaces/message/receiveMessage.go b/interfaces/message/receiveMessage.go index faa61d61f..f5373e716 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 541dc5b14..b7ff3a886 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 4fc72a604..c11728b1a 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/message/critical.go b/network/message/critical.go index c6dbfbd9f..0e89cf110 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 6a3d5bb2a..c81829858 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -13,6 +13,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" "time" ) @@ -72,10 +73,16 @@ 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 + ephID, err := ephemeral.Marshal(msg.GetEphemeralRID()) + 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: ephID, Timestamp: time.Time{}, Encryption: message.None, } diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go index cdc25ed10..81050831a 100644 --- a/network/message/sendCmix.go +++ b/network/message/sendCmix.go @@ -14,10 +14,12 @@ import ( "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" + "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" ) @@ -33,7 +35,7 @@ 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 (m *Manager) SendCMIX(msg format.Message, recipient *id.ID, param params.CMIX) (id.Round, ephemeral.Id, error) { timeStart := time.Now() attempted := set.New() @@ -42,7 +44,7 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err 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") @@ -59,6 +61,22 @@ 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])) + + 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 { @@ -94,10 +112,10 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err 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 @@ -115,7 +133,8 @@ func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, err RoundID: bestRound.ID, } //Add the mac proving ownership - msg.MAC = roundKeys.MakeClientGatewayKey(salt, network.GenerateSlotDigest(msg)) + msg.MAC = roundKeys.MakeClientGatewayKey(salt, + network.GenerateSlotDigest(msg)) //add the round on to the list of attempted so it is not tried again attempted.Insert(bestRound) @@ -134,11 +153,11 @@ 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 diff --git a/network/message/sendE2E.go b/network/message/sendE2E.go index 04e24e8e4..fbb2e910f 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 8975309dc..956a50f54 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/send.go b/network/send.go index cd3d13da4..0e3e9020a 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/storage/reception/IdentityUse.go b/storage/reception/IdentityUse.go index 5a96aef57..1507d9321 100644 --- a/storage/reception/IdentityUse.go +++ b/storage/reception/IdentityUse.go @@ -26,7 +26,9 @@ type IdentityUse struct{ KR KnownRounds } -func (iu IdentityUse)SetSamplingPeriod(rng io.Reader)(IdentityUse, error){ +// 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) @@ -36,18 +38,17 @@ func (iu IdentityUse)SetSamplingPeriod(rng io.Reader)(IdentityUse, error){ } h, err := hash.NewCMixHash() - if err==nil{ + if err!=nil{ return IdentityUse{}, err } //calculate the period offset periodOffset := randomness.RandInInterval(big.NewInt(iu.RequestMask.Nanoseconds()), - seed,h).Uint64() - iu.StartRequest = iu.StartValid.Add(-time.Duration(periodOffset)* - time.Nanosecond) + seed,h).Int64() + iu.StartRequest = iu.StartValid.Add(-time.Duration(periodOffset)) iu.EndRequest = iu.EndValid.Add(iu.RequestMask - - time.Duration(periodOffset)*time.Nanosecond) + time.Duration(periodOffset)) return iu, nil } diff --git a/storage/reception/fake.go b/storage/reception/fake.go index bc72c6157..17c0b1a31 100644 --- a/storage/reception/fake.go +++ b/storage/reception/fake.go @@ -8,7 +8,10 @@ import ( "time" ) -func generateFakeIdentity(rng io.Reader, idSize uint)(IdentityUse, error){ +// 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 " + @@ -19,8 +22,9 @@ func generateFakeIdentity(rng io.Reader, idSize uint)(IdentityUse, error){ 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, - time.Now().UnixNano()) + now.UnixNano()) if err!=nil{ return IdentityUse{}, errors.WithMessage(err, "failed to " + "generate an ephemral ID for random identity when none is " + diff --git a/storage/reception/fake_test.go b/storage/reception/fake_test.go new file mode 100644 index 000000000..1fa4a6b4a --- /dev/null +++ b/storage/reception/fake_test.go @@ -0,0 +1,40 @@ +package reception + +import ( + "encoding/json" + "math/rand" + "testing" + "time" +) + +//tests Generate Fake identity is consistant and returns a correct result +func TestGenerateFakeIdentity(t *testing.T) { + rng := rand.New(rand.NewSource(42)) + + 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\":\"2009-11-17T13:43:23.759765625-08:00\",\"ExtraChecks\":0,"+ + "\"StartValid\":\"2009-11-16T13:43:23.759765625-08:00\"," + + "\"EndValid\":\"2009-11-17T13:43:23.759765625-08:00\"," + + "\"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("Generate fake identity returned an unexpected " + + "error: %+v", err ) + } + + receivedJson, _ := json.Marshal(received) + + if expected!=string(receivedJson){ + t.Errorf("The fake identity was generated incorrectly\n " + + "Expected: %s,\n Received: %s", expected, receivedJson) + } +} \ No newline at end of file diff --git a/storage/reception/identity.go b/storage/reception/identity.go index 7ec0a33a3..d8a639b9d 100644 --- a/storage/reception/identity.go +++ b/storage/reception/identity.go @@ -6,6 +6,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "strconv" "time" ) @@ -80,6 +81,6 @@ func (i Identity)calculateKrSize()int{ } func (i *Identity)String()string{ - return string(i.EphId.Int64()) + " " + i.String() + return strconv.FormatInt(i.EphId.Int64(), 16) + " " + i.Source.String() } diff --git a/storage/reception/identityUse_test.go b/storage/reception/identityUse_test.go new file mode 100644 index 000000000..3c14746f3 --- /dev/null +++ b/storage/reception/identityUse_test.go @@ -0,0 +1,68 @@ +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) +} \ No newline at end of file diff --git a/storage/reception/identity_test.go b/storage/reception/identity_test.go index 2117f731f..b0095e1c9 100644 --- a/storage/reception/identity_test.go +++ b/storage/reception/identity_test.go @@ -5,12 +5,13 @@ import ( "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "math/rand" "reflect" "testing" "time" ) -func TestIdentityEncodeDecode(t *testing.T) { +func TestIdentity_EncodeDecode(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) r := Identity{ @@ -38,7 +39,7 @@ func TestIdentityEncodeDecode(t *testing.T) { } } -func TestIdentityDelete(t *testing.T) { +func TestIdentity_Delete(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) r := Identity{ @@ -66,3 +67,40 @@ func TestIdentityDelete(t *testing.T) { t.Errorf("Load after delete succeded") } } + + +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: " + + "\n\t Expected: %s\n\t Received: %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() + id := Identity{ + StartValid: now, + EndValid: now.Add(d), + } + + krSize := id.calculateKrSize() + if krSize != expected{ + t.Errorf("kr size not correct! expected: %v, recieved: %v", + expected, krSize) + } + } +} \ No newline at end of file diff --git a/storage/reception/registration.go b/storage/reception/registration.go index f010b46b0..58cb254d8 100644 --- a/storage/reception/registration.go +++ b/storage/reception/registration.go @@ -7,6 +7,7 @@ import ( "gitlab.com/elixxir/primitives/knownRounds" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "strconv" "time" ) @@ -111,5 +112,6 @@ func (r registration)getKR()KnownRounds{ } func regPrefix(EphId ephemeral.Id, Source *id.ID)string{ - return "receptionRegistration_" + string(EphId.Int64()) + Source.String() + return "receptionRegistration_" + + strconv.FormatInt(EphId.Int64(), 16) + Source.String() } \ No newline at end of file diff --git a/storage/reception/registration_test.go b/storage/reception/registration_test.go new file mode 100644 index 000000000..f198af197 --- /dev/null +++ b/storage/reception/registration_test.go @@ -0,0 +1,54 @@ +package reception + +import ( + "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.Errorf("Registeration creation succeded 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 + + _, err := newRegistration(id, kv) + if err!=nil || !strings.Contains(err.Error(), "Cannot create a registration for an identity which has expired"){ + t.Errorf("Registeration creation failed when it should have " + + "succeded: %+v", err) + } +} \ No newline at end of file diff --git a/storage/reception/store.go b/storage/reception/store.go index 36353924e..858681559 100644 --- a/storage/reception/store.go +++ b/storage/reception/store.go @@ -154,7 +154,7 @@ func (s *Store)GetIdentity(rng io.Reader)(IdentityUse, error){ // 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)) + 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) @@ -167,7 +167,7 @@ func (s *Store)GetIdentity(rng io.Reader)(IdentityUse, error){ } //calculate the sampling period - identity, err = identity.SetSamplingPeriod(rng) + identity, err = identity.setSamplingPeriod(rng) if err!=nil{ jww.FATAL.Panicf("Failed to caluclate the sampling period: " + "%+v", err) @@ -207,7 +207,7 @@ func (s *Store)RemoveIdentity(ephID ephemeral.Id)bool { s.active = append(s.active[:i], s.active[i+1:]...) err := inQuestion.Delete() if err!=nil{ - jww.FATAL.Panicf("Failed to delete identity %s") + jww.FATAL.Panicf("Failed to delete identity: %+v", err) } if !inQuestion.Ephemeral{ if err := s.save(); err!=nil{ diff --git a/storage/session.go b/storage/session.go index 258506d4b..88653b151 100644 --- a/storage/session.go +++ b/storage/session.go @@ -116,13 +116,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") diff --git a/ud/lookup_test.go b/ud/lookup_test.go index d732c7004..6bd9b7357 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 { -- GitLab