diff --git a/e2e/critical.go b/e2e/critical.go index 9019dfee70ae1ea68a8e349d9ea0c8bc34b7eddf..8fbcf39e859fb8ad68cb85850766d50edf8bf50c 100644 --- a/e2e/critical.go +++ b/e2e/critical.go @@ -1,6 +1,8 @@ package e2e import ( + "time" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" @@ -11,7 +13,6 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" - "time" ) const e2eCriticalMessagesKey = "E2ECriticalMessages" @@ -43,8 +44,8 @@ func newCritical(kv *versioned.KV, hm func(f func(bool)) uint64, roundEvents roundEventRegistrar, send criticalSender) *critical { cm, err := NewOrLoadE2eMessageBuffer(kv, e2eCriticalMessagesKey) if err != nil { - jww.FATAL.Panicf( - "Failed to load the buffer for critical messages: %+v", err) + jww.FATAL.Panicf("cannot load the critical messages buffer: "+ + "%+v", err) } c := &critical{ @@ -82,19 +83,27 @@ func (c *critical) handle(mt catalog.MessageType, recipient *id.ID, for _, rid := range rids { c.roundEvents.AddRoundEventChan( - rid, sendResults, 1*time.Minute, states.COMPLETED, + rid, sendResults, 1*time.Minute, + states.COMPLETED, states.FAILED) } - success, numTimeOut, _ := cmix.TrackResults(sendResults, len(rids)) + success, numTimeOut, _ := cmix.TrackResults(sendResults, + len(rids)) if !success { if numTimeOut > 0 { - jww.ERROR.Printf("Critical e2e message resend to %s "+ - "(msgDigest: %s) on round %d failed to transmit due to "+ - "timeout", recipient, format.DigestContents(payload), rids) + jww.ERROR.Printf("Critical e2e message resend "+ + "to %s (msgDigest: %s) on round %d "+ + "failed to transmit due to timeout", + recipient, + format.DigestContents(payload), + rids) } else { - jww.ERROR.Printf("Critical raw message resend to %s "+ - "(msgDigest: %s) on round %d failed to transmit due to "+ - "send failure", recipient, format.DigestContents(payload), + jww.ERROR.Printf("Critical raw message resend "+ + "to %s (msgDigest: %s) on round %d "+ + "failed to transmit "+ + "due to send failure", + recipient, + format.DigestContents(payload), rids) } @@ -114,16 +123,19 @@ func (c *critical) handle(mt catalog.MessageType, recipient *id.ID, // evaluate tries to send every message in the critical messages and the raw // critical messages buffer in parallel. func (c *critical) evaluate(stop *stoppable.Single) { - for mt, recipient, payload, params, has := c.Next(); has; mt, recipient, payload, params, has = c.Next() { + mt, recipient, payload, params, has := c.Next() + for ; has; mt, recipient, payload, params, has = c.Next() { go func(mt catalog.MessageType, recipient *id.ID, payload []byte, params Params) { params.CMIX.Stop = stop jww.INFO.Printf("Resending critical raw message to %s "+ - "(msgDigest: %s)", recipient, format.DigestContents(payload)) + "(msgDigest: %s)", recipient, + format.DigestContents(payload)) // Send the message - round, _, _, err := c.send(mt, recipient, payload, params) + round, _, _, err := c.send(mt, recipient, payload, + params) // Pass to the handler c.handle(mt, recipient, payload, round, err) diff --git a/e2e/e2eMessageBuffer.go b/e2e/e2eMessageBuffer.go index 4727ff19afb75b48dc75095c8e5ce906eab7336c..00b196d6bd70d9c5dafe7e3915e1786d89581b61 100644 --- a/e2e/e2eMessageBuffer.go +++ b/e2e/e2eMessageBuffer.go @@ -10,6 +10,7 @@ package e2e import ( "encoding/binary" "encoding/json" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/storage/utility" @@ -32,12 +33,14 @@ type e2eMessage struct { // SaveMessage saves the e2eMessage as a versioned object at the specified key // in the key value store. -func (emh *e2eMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, key string) error { +func (emh *e2eMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, + key string) error { msg := m.(e2eMessage) b, err := json.Marshal(&msg) if err != nil { - jww.FATAL.Panicf("Failed to marshal e2e message for storage: %s", err) + jww.FATAL.Panicf("cannot marshal e2e message for storage: %s", + err) } // Create versioned object @@ -54,7 +57,8 @@ func (emh *e2eMessageHandler) SaveMessage(kv *versioned.KV, m interface{}, key s // LoadMessage returns the e2eMessage with the specified key from the key value // store. An empty message and error are returned if the message could not be // retrieved. -func (emh *e2eMessageHandler) LoadMessage(kv *versioned.KV, key string) (interface{}, error) { +func (emh *e2eMessageHandler) LoadMessage(kv *versioned.KV, key string) ( + interface{}, error) { // Load the versioned object vo, err := kv.Get(key, currentE2EMessageVersion) if err != nil { @@ -64,7 +68,8 @@ func (emh *e2eMessageHandler) LoadMessage(kv *versioned.KV, key string) (interfa // Unmarshal data into e2eMessage msg := e2eMessage{} if err := json.Unmarshal(vo.Data, &msg); err != nil { - jww.FATAL.Panicf("Failed to unmarshal e2e message for storage: %s", err) + jww.FATAL.Panicf("cannot unmarshal e2e message for storage: %s", + err) } return msg, err @@ -72,7 +77,8 @@ func (emh *e2eMessageHandler) LoadMessage(kv *versioned.KV, key string) (interfa // DeleteMessage deletes the message with the specified key from the key value // store. -func (emh *e2eMessageHandler) DeleteMessage(kv *versioned.KV, key string) error { +func (emh *e2eMessageHandler) DeleteMessage(kv *versioned.KV, + key string) error { return kv.Delete(key, currentE2EMessageVersion) } @@ -100,7 +106,8 @@ type E2eMessageBuffer struct { mb *utility.MessageBuffer } -func NewOrLoadE2eMessageBuffer(kv *versioned.KV, key string) (*E2eMessageBuffer, error) { +func NewOrLoadE2eMessageBuffer(kv *versioned.KV, key string) ( + *E2eMessageBuffer, error) { mb, err := LoadE2eMessageBuffer(kv, key) if err == nil { return mb, nil @@ -112,7 +119,8 @@ func NewOrLoadE2eMessageBuffer(kv *versioned.KV, key string) (*E2eMessageBuffer, return &E2eMessageBuffer{mb: mbInt}, nil } -func LoadE2eMessageBuffer(kv *versioned.KV, key string) (*E2eMessageBuffer, error) { +func LoadE2eMessageBuffer(kv *versioned.KV, key string) ( + *E2eMessageBuffer, error) { mb, err := utility.LoadMessageBuffer(kv, &e2eMessageHandler{}, key) if err != nil { return nil, err @@ -161,12 +169,14 @@ func (emb *E2eMessageBuffer) Next() (catalog.MessageType, *id.ID, []byte, return mt, recipient, msg.Payload, msg.Params, true } -func (emb *E2eMessageBuffer) Succeeded(mt catalog.MessageType, recipient *id.ID, payload []byte) { +func (emb *E2eMessageBuffer) Succeeded(mt catalog.MessageType, + recipient *id.ID, payload []byte) { emb.mb.Succeeded(e2eMessage{recipient.Marshal(), payload, uint32(mt), Params{}}) } -func (emb *E2eMessageBuffer) Failed(mt catalog.MessageType, recipient *id.ID, payload []byte) { +func (emb *E2eMessageBuffer) Failed(mt catalog.MessageType, + recipient *id.ID, payload []byte) { emb.mb.Failed(e2eMessage{recipient.Marshal(), payload, uint32(mt), Params{}}) } diff --git a/e2e/fpGenerator.go b/e2e/fpGenerator.go index 19d7958925aa60cb198e21f5d65d945e3f2a593f..3a9a6c00ee1fdd753e3a6aaa78ef9e17e56b91cc 100644 --- a/e2e/fpGenerator.go +++ b/e2e/fpGenerator.go @@ -13,10 +13,11 @@ type fpGenerator struct { } func (fp *fpGenerator) AddKey(k *session.Cypher) { - err := fp.net.AddFingerprint(fp.myDefaultID, k.Fingerprint(), &processor{ - cy: k, - m: fp.manager, - }) + err := fp.net.AddFingerprint(fp.myID, k.Fingerprint(), + &processor{ + cy: k, + m: fp.manager, + }) if err != nil { jww.ERROR.Printf("Could not add fingerprint %s: %+v", k.Fingerprint(), err) @@ -24,5 +25,5 @@ func (fp *fpGenerator) AddKey(k *session.Cypher) { } func (fp *fpGenerator) DeleteKey(k *session.Cypher) { - fp.net.DeleteFingerprint(fp.myDefaultID, k.Fingerprint()) + fp.net.DeleteFingerprint(fp.myID, k.Fingerprint()) } diff --git a/e2e/interface.go b/e2e/interface.go index ac9590649c7038ac1d1ab04cfd8361d777192f8f..03e9d312a692dfd9649f8ce4e4fe2521a3bb82eb 100644 --- a/e2e/interface.go +++ b/e2e/interface.go @@ -1,6 +1,8 @@ package e2e import ( + "time" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix/message" @@ -11,7 +13,6 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" - "time" ) type Handler interface { @@ -19,94 +20,108 @@ type Handler interface { // handlers and the critical message handlers StartProcesses() (stoppable.Stoppable, error) - // SendE2E send a message containing the payload to the recipient of the - // passed message type, per the given parameters - encrypted with end to - // end encryption. - // Default parameters can be retrieved through GetDefaultParams() - // If too long, it will chunk a message up into its messages and send each - // as a separate cmix message. It will return the list of all rounds sent - // on, a unique ID for the message, and the timestamp sent on. - // the recipient must already have an e2e relationship, otherwise an error - // will be returned. - // Will return an error if the network is not healthy or in the event of - // a failed send + // SendE2E send a message containing the payload to the + // recipient of the passed message type, per the given + // parameters - encrypted with end to end encryption. + // Default parameters can be retrieved through + // GetDefaultParams() + // If too long, it will chunk a message up into its messages + // and send each as a separate cmix message. It will return + // the list of all rounds sent on, a unique ID for the + // message, and the timestamp sent on. + // the recipient must already have an e2e relationship, + // otherwise an error will be returned. + // Will return an error if the network is not healthy or in + // the event of a failed send SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) - /* === Reception ======================================================== */ + /* === Reception ==================================================== */ - // RegisterListener Registers a new listener. Returns the ID of the new - // listener. Keep the ID around if you want to be able to delete the - // listener later. + // RegisterListener Registers a new listener. Returns the ID + // of the new listener. Keep the ID around if you want to be + // able to delete the listener later. // - // The name is used for debug printing and not checked for uniqueness + // The name is used for debug printing and not checked for + // uniqueness // - // user: 0 for all, or any user ID to listen for messages from a particular - // user. 0 can be id.ZeroUser or id.ZeroID - // messageType: 0 for all, or any message type to listen for messages of that - // type. 0 can be Message.AnyType - // newListener: something implementing the Listener interface. Do not - // pass nil to this. + // user: 0 for all, or any user ID to listen for messages from + // a particular user. 0 can be id.ZeroUser or id.ZeroID + // messageType: 0 for all, or any message type to listen for + // messages of that type. 0 can be Message.AnyType + // newListener: something implementing the Listener + // interface. Do not pass nil to this. // - // If a message matches multiple listeners, all of them will hear the message. - RegisterListener(senderID *id.ID, messageType catalog.MessageType, + // If a message matches multiple listeners, all of them will + // hear the message. + RegisterListener(senderID *id.ID, + messageType catalog.MessageType, newListener receive.Listener) receive.ListenerID - // RegisterFunc Registers a new listener built around the passed function. - // Returns the ID of the new listener. Keep the ID around if you want to - // be able to delete the listener later. + // RegisterFunc Registers a new listener built around the + // passed function. Returns the ID of the new listener. Keep + // the ID around if you want to be able to delete the listener + // later. // - // name is used for debug printing and not checked for uniqueness + // name is used for debug printing and not checked for + // uniqueness // - // user: 0 for all, or any user ID to listen for messages from a particular - // user. 0 can be id.ZeroUser or id.ZeroID - // messageType: 0 for all, or any message type to listen for messages of that - // type. 0 can be Message.AnyType - // newListener: a function implementing the ListenerFunc function type. - // Do not pass nil to this. + // user: 0 for all, or any user ID to listen for messages from + // a particular user. 0 can be id.ZeroUser or id.ZeroID + // messageType: 0 for all, or any message type to listen for + // messages of that type. 0 can be Message.AnyType + // newListener: a function implementing the ListenerFunc + // function type. Do not pass nil to this. // - // If a message matches multiple listeners, all of them will hear the message. - RegisterFunc(name string, senderID *id.ID, messageType catalog.MessageType, + // If a message matches multiple listeners, all of them will + // hear the message. + RegisterFunc(name string, senderID *id.ID, + messageType catalog.MessageType, newListener receive.ListenerFunc) receive.ListenerID - // RegisterChannel Registers a new listener built around the passed channel. - // Returns the ID of the new listener. Keep the ID around if you want to - // // be able to delete the listener later. + // RegisterChannel Registers a new listener built around the + // passed channel. Returns the ID of the new listener. Keep + // the ID around if you want to be able to delete the listener + // later. // - // name is used for debug printing and not checked for uniqueness + // name is used for debug printing and not checked for + // uniqueness // - // user: 0 for all, or any user ID to listen for messages from a particular - // user. 0 can be id.ZeroUser or id.ZeroID - // messageType: 0 for all, or any message type to listen for messages of that - // type. 0 can be Message.AnyType - // newListener: an item channel. - // Do not pass nil to this. + // user: 0 for all, or any user ID to listen for messages from + // a particular user. 0 can be id.ZeroUser or id.ZeroID + // messageType: 0 for all, or any message type to listen for + // messages of that type. 0 can be Message.AnyType + // newListener: an item channel. Do not pass nil to this. // - // If a message matches multiple listeners, all of them will hear the message. - RegisterChannel(name string, senderID *id.ID, messageType catalog.MessageType, + // If a message matches multiple listeners, all of them will + // hear the message. + RegisterChannel(name string, senderID *id.ID, + messageType catalog.MessageType, newListener chan receive.Message) receive.ListenerID - // Unregister removes the listener with the specified ID so it will no longer - // get called + // Unregister removes the listener with the specified ID so it + // will no longer get called Unregister(listenerID receive.ListenerID) - /* === Partners ========================================================= */ + /* === Partners ===================================================== */ - // AddPartner adds a partner. Automatically creates both send and receive - // sessions using the passed cryptographic data and per the parameters sent - // If an alternate ID public key are to be used for this relationship, - // then pass them in, otherwise, leave myID and myPrivateKey nil - // If temporary is true, an alternate ram kv will be used for storage and - // the relationship will not survive a reset + // AddPartner adds a partner. Automatically creates both send + // and receive sessions using the passed cryptographic data + // and per the parameters sent If an alternate ID public key + // are to be used for this relationship, then pass them in, + // otherwise, leave myID and myPrivateKey nil If temporary is + // true, an alternate ram kv will be used for storage and the + // relationship will not survive a reset AddPartner(partnerID *id.ID, - partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, + partnerPubKey, myPrivKey *cyclic.Int, + partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, - receiveParams session.Params) (*partner.Manager, error) + receiveParams session.Params) (partner.Manager, error) // GetPartner returns the partner per its ID, if it exists // myID is your ID in the relationship, if left blank, it will // assume to be your defaultID - GetPartner(partnerID *id.ID) (*partner.Manager, error) + GetPartner(partnerID *id.ID) (partner.Manager, error) // DeletePartner removes the associated contact from the E2E store // myID is your ID in the relationship, if left blank, it will @@ -117,28 +132,29 @@ type Handler interface { // an E2E relationship with. GetAllPartnerIDs() []*id.ID - /* === Services ========================================================= */ - - // AddService adds a service for all partners of the given tag, which will - // call back on the given processor. These can be sent to using the - // tag fields in the Params Object - // Passing nil for the processor allows you to create a service which is - // never called but will be visible by notifications - // Processes added this way are generally not end ot end encrypted messages - // themselves, but other protocols which piggyback on e2e relationships - // to start communication + /* === Services ===================================================== */ + + // AddService adds a service for all partners of the given + // tag, which will call back on the given processor. These can + // be sent to using the tag fields in the Params Object + // Passing nil for the processor allows you to create a + // service which is never called but will be visible by + // notifications Processes added this way are generally not + // end ot end encrypted messages themselves, but other + // protocols which piggyback on e2e relationships to start + // communication AddService(tag string, processor message.Processor) error // RemoveService removes all services for the given tag RemoveService(tag string) error - /* === Unsafe =========================================================== */ + /* === Unsafe ======================================================= */ - // SendUnsafe sends a message without encryption. It breaks both privacy - // and security. It does partition the message. It should ONLY be used for - // debugging. - // It does not respect service tags in the parameters and sends all - // messages with "Silent" and "E2E" tags. + // SendUnsafe sends a message without encryption. It breaks + // both privacy and security. It does partition the + // message. It should ONLY be used for debugging. + // It does not respect service tags in the parameters and + // sends all messages with "Silent" and "E2E" tags. // It does not support critical messages. // It does not check that an e2e relationship exists with the recipient // Will return an error if the network is not healthy or in the event of @@ -150,15 +166,16 @@ type Handler interface { // registering bespoke services for reception. For debugging only! EnableUnsafeReception() - /* === Utility ========================================================== */ + /* === Utility ====================================================== */ // GetGroup returns the cyclic group used for end to end encruption GetGroup() *cyclic.Group - // GetHistoricalDHPubkey returns the default user's Historical DH Public Key + // GetHistoricalDHPubkey returns the user's Historical DH + // Public Key GetHistoricalDHPubkey() *cyclic.Int - // GetHistoricalDHPrivkey returns the default user's Historical DH Private Key + // GetHistoricalDHPrivkey returns the user's Historical DH Private Key GetHistoricalDHPrivkey() *cyclic.Int // GetReceptionID returns the default IDs diff --git a/e2e/manager.go b/e2e/manager.go index aac3cb2040cbc849ebec1b97f9c9c5e00f1d3767..06710c4189386456dbc289f55dabd59c180d8e81 100644 --- a/e2e/manager.go +++ b/e2e/manager.go @@ -2,6 +2,8 @@ package e2e import ( "encoding/json" + "time" + "github.com/pkg/errors" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" @@ -17,7 +19,6 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" - "time" ) type manager struct { @@ -25,7 +26,7 @@ type manager struct { *receive.Switchboard partitioner parse.Partitioner net cmix.Client - myDefaultID *id.ID + myID *id.ID rng *fastRNG.StreamGenerator events event.Manager grp *cyclic.Group @@ -42,7 +43,7 @@ const e2eRekeyParamsVer = 0 func Init(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, grp *cyclic.Group, rekeyParams rekey.Params) error { kv = kv.Prefix(makeE2ePrefix(myID)) - return InitLegacy(kv, myID, privKey, grp, rekeyParams) + return initE2E(kv, myID, privKey, grp, rekeyParams) } // InitLegacy Creates stores. After calling, use load @@ -50,6 +51,11 @@ func Init(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, // Does not modify the kv prefix in any way to maintain backwards compatibility // before multiple IDs were supported func InitLegacy(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, + grp *cyclic.Group, rekeyParams rekey.Params) error { + return initE2E(kv, myID, privKey, grp, rekeyParams) +} + +func initE2E(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, grp *cyclic.Group, rekeyParams rekey.Params) error { rekeyParamsData, err := json.Marshal(rekeyParams) if err != nil { @@ -66,50 +72,61 @@ func InitLegacy(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, return ratchet.New(kv, myID, privKey, grp) } -func Load(kv *versioned.KV, net cmix.Client, myDefaultID *id.ID, - grp *cyclic.Group, rng *fastRNG.StreamGenerator, events event.Manager) ( - Handler, error) { - +// Load returns an e2e manager from storage. It uses an ID to prefix the kv +// and is used for partner relationships. +// You can use a memkv for an ephemeral e2e id +func Load(kv *versioned.KV, net cmix.Client, myID *id.ID, + grp *cyclic.Group, rng *fastRNG.StreamGenerator, + events event.Manager) (Handler, error) { + kv = kv.Prefix(makeE2ePrefix(myID)) + return loadE2E(kv, net, myID, grp, rng, events) } // LoadLegacy returns an e2e manager from storage -// Passes a default ID which is used for relationship with -// partners when no default ID is selected +// Passes an ID which is used for relationship with +// partners. // Does not modify the kv prefix in any way to maintain backwards compatibility // before multiple IDs were supported -func LoadLegacy(kv *versioned.KV, net cmix.Client, myDefaultID *id.ID, - grp *cyclic.Group, rng *fastRNG.StreamGenerator, events event.Manager) (Handler, error) { +// You can use a memkv for an ephemeral e2e id +func LoadLegacy(kv *versioned.KV, net cmix.Client, myID *id.ID, + grp *cyclic.Group, rng *fastRNG.StreamGenerator, + events event.Manager) (Handler, error) { + return loadE2E(kv, net, myID, grp, rng, events) +} + +func loadE2E(kv *versioned.KV, net cmix.Client, myDefaultID *id.ID, + grp *cyclic.Group, rng *fastRNG.StreamGenerator, + events event.Manager) (Handler, error) { - //build the manager m := &manager{ Switchboard: receive.New(), - partitioner: parse.NewPartitioner(kv, net.GetMaxMessageLength()), + partitioner: parse.NewPartitioner(kv, + net.GetMaxMessageLength()), net: net, - myDefaultID: myDefaultID, + myID: myDefaultID, events: events, grp: grp, rekeyParams: rekey.Params{}, } var err error - //load the ratchets m.Ratchet, err = ratchet.Load(kv, myDefaultID, grp, &fpGenerator{m}, net, rng) if err != nil { return nil, err } - //load rekey params here rekeyParams, err := kv.Get(e2eRekeyParamsKey, e2eRekeyParamsVer) if err != nil { - return nil, errors.WithMessage(err, "Failed to load rekeyParams") + return nil, errors.WithMessage(err, + "Failed to load rekeyParams") } err = json.Unmarshal(rekeyParams.Data, &m.rekeyParams) if err != nil { - return nil, errors.WithMessage(err, "Failed to unmarshal rekeyParams data") + return nil, errors.WithMessage(err, + "Failed to unmarshal rekeyParams data") } - //attach critical messages m.crit = newCritical(kv, net.AddHealthCallback, net.GetInstance().GetRoundEvents(), m.SendE2E) @@ -119,19 +136,21 @@ func LoadLegacy(kv *versioned.KV, net cmix.Client, myDefaultID *id.ID, func (m *manager) StartProcesses() (stoppable.Stoppable, error) { multi := stoppable.NewMulti("e2eManager") - critcalNetworkStopper := stoppable.NewSingle("e2eCriticalMessagesStopper") + critcalNetworkStopper := stoppable.NewSingle( + "e2eCriticalMessagesStopper") m.crit.runCriticalMessages(critcalNetworkStopper) multi.Add(critcalNetworkStopper) - rekeySendFunc := func(mt catalog.MessageType, recipient *id.ID, payload []byte, + rekeySendFunc := func(mt catalog.MessageType, + recipient *id.ID, payload []byte, cmixParams cmix.CMIXParams) ( []id.Round, e2e.MessageID, time.Time, error) { par := GetDefaultParams() par.CMIX = cmixParams return m.SendE2E(mt, recipient, payload, par) } - rekeyStopper, err := rekey.Start(m.Switchboard, m.Ratchet, rekeySendFunc, m.net, m.grp, - rekey.GetDefaultParams()) + rekeyStopper, err := rekey.Start(m.Switchboard, m.Ratchet, + rekeySendFunc, m.net, m.grp, rekey.GetDefaultParams()) if err != nil { return nil, err } @@ -144,15 +163,15 @@ func (m *manager) StartProcesses() (stoppable.Stoppable, error) { // EnableUnsafeReception enables the reception of unsafe message by registering // bespoke services for reception. For debugging only! func (m *manager) EnableUnsafeReception() { - m.net.AddService(m.myDefaultID, message.Service{ - Identifier: m.myDefaultID[:], + m.net.AddService(m.myID, message.Service{ + Identifier: m.myID[:], Tag: ratchet.Silent, }, &UnsafeProcessor{ m: m, tag: ratchet.Silent, }) - m.net.AddService(m.myDefaultID, message.Service{ - Identifier: m.myDefaultID[:], + m.net.AddService(m.myID, message.Service{ + Identifier: m.myID[:], Tag: ratchet.E2e, }, &UnsafeProcessor{ m: m, diff --git a/e2e/params.go b/e2e/params.go index 78212dbdaf9530d9296a25ef969ad11dd3214dd6..ef54d50ee7cd1148a553055f04c53c4c2cbc9f92 100644 --- a/e2e/params.go +++ b/e2e/params.go @@ -2,27 +2,29 @@ package e2e import ( "encoding/json" + "time" + "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" - "time" ) type Params struct { // Tag to use to generate the service. ServiceTag string - // Often, for notifications purposes, all messages except the last should - // use a silent service. This allows a + // Often, for notifications purposes, all messages except the + // last should use a silent service. This allows a LastServiceTag string - // The parameters adjust how the code behaves if there are not keys available. - // the number of times the code will attempt to get a key to encrypt with + // The parameters adjust how the code behaves if there are not + // keys available. the number of times the code will attempt + // to get a key to encrypt with KeyGetRetryCount uint // Delay between attempting to get kets KeyGeRetryDelay time.Duration //Underlying cmix tags. - // Note: if critical is true, an alternative critical messages system within - // e2e will be used which preserves privacy + // Note: if critical is true, an alternative critical messages + // system within e2e will be used which preserves privacy CMIX cmix.CMIXParams //Authorizes the message to use a key reserved for rekeying. Do not use diff --git a/e2e/processor.go b/e2e/processor.go index be0ad21ad3a03f26805aa9c25ee438f646e50ae4..7405859894c12ece7243f9aba78e2bc0ec1eb6a6 100644 --- a/e2e/processor.go +++ b/e2e/processor.go @@ -13,24 +13,22 @@ type processor struct { m *manager } -func (p *processor) Process(ecrMsg format.Message, receptionID receptionID.EphemeralIdentity, +func (p *processor) Process(ecrMsg format.Message, + receptionID receptionID.EphemeralIdentity, round historical.Round) { - //ensure the key is used before returning + // ensure the key will be marked used before returning defer p.cy.Use() - //decrypt contents, err := p.cy.Decrypt(ecrMsg) if err != nil { - jww.ERROR.Printf("Decryption Failed of %s (fp: %s), dropping: %+v", + jww.ERROR.Printf("decrypt failed of %s (fp: %s), dropping: %+v", ecrMsg.Digest(), p.cy.Fingerprint(), err) return } - //Parse sess := p.cy.GetSession() message, done := p.m.partitioner.HandlePartition(sess.GetPartner(), contents, sess.GetRelationshipFingerprint()) - if done { message.RecipientID = receptionID.Source message.EphemeralID = receptionID.EphId diff --git a/e2e/ratchet/partner/interface.go b/e2e/ratchet/partner/interface.go index c051bf0b71b071387615615fcf50ffc3bd60eaf3..6877291c48c81e332e044ebbb9a4042d1cf6dfcd 100644 --- a/e2e/ratchet/partner/interface.go +++ b/e2e/ratchet/partner/interface.go @@ -9,22 +9,27 @@ import ( "gitlab.com/xx_network/primitives/id" ) -type Manager2 interface { +type Manager interface { NewReceiveSession(partnerPubKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, e2eParams session.Params, source *session.Session) (*session.Session, bool) - NewSendSession(myPrivKey *cyclic.Int, - mySIDHPrivKey *sidh.PrivateKey, e2eParams session.Params) + NewSendSession(myDHPrivKey *cyclic.Int, mySIDHPrivateKey *sidh.PrivateKey, + e2eParams session.Params, source *session.Session) *session.Session PopSendCypher() (*session.Cypher, error) PopRekeyCypher() (*session.Cypher, error) GetPartnerID() *id.ID + GetMyID() *id.ID GetSendSession(sid session.SessionID) *session.Session - GetSendRelationshipFingerprint() - Confirm(sid session.SessionID) + GetReceiveSession(sid session.SessionID) *session.Session + Confirm(sid session.SessionID) error TriggerNegotiations() []*session.Session - GetMyOriginPrivateKey() - GetPartnerOriginPublicKey() + GetMyOriginPrivateKey() *cyclic.Int + GetPartnerOriginPublicKey() *cyclic.Int + GetSendRelationshipFingerprint() []byte GetRelationshipFingerprintBytes() []byte + GetRelationshipFingerprint() string MakeService(tag string) message.Service GetContact() contact.Contact + DeleteRelationship() error + ClearManager() error } diff --git a/e2e/ratchet/partner/manager.go b/e2e/ratchet/partner/manager.go index 98699392f5e4a56d57b439c984d6e6ec8f89811f..a8e482cc4acbc53c14f6680a9f94825391b27fe6 100644 --- a/e2e/ratchet/partner/manager.go +++ b/e2e/ratchet/partner/manager.go @@ -11,6 +11,7 @@ import ( "bytes" "encoding/base64" "fmt" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -29,7 +30,7 @@ const managerPrefix = "Manager{partner:%s}" const originMyPrivKeyKey = "originMyPrivKey" const originPartnerPubKey = "originPartnerPubKey" -type Manager struct { +type manager struct { kv *versioned.KV myID *id.ID @@ -47,8 +48,6 @@ type Manager struct { grp *cyclic.Group cyHandler session.CypherHandler rng *fastRNG.StreamGenerator - - managerID ManagerIdentity } // NewManager creates the relationship and its first Send and Receive sessions. @@ -56,13 +55,11 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, partnerPubKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey, sendParams, receiveParams session.Params, cyHandler session.CypherHandler, - grp *cyclic.Group, rng *fastRNG.StreamGenerator) *Manager { - - mi := MakeManagerIdentity(partnerID, myID) + grp *cyclic.Group, rng *fastRNG.StreamGenerator) Manager { - kv = kv.Prefix(makeManagerPrefix(mi)) + kv = kv.Prefix(makeManagerPrefix(partnerID)) - m := &Manager{ + m := &manager{ kv: kv, originMyPrivKey: myPrivKey, originPartnerPubKey: partnerPubKey, @@ -73,21 +70,22 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, cyHandler: cyHandler, grp: grp, rng: rng, - managerID: mi, } - if err := utility.StoreCyclicKey(kv, myPrivKey, originMyPrivKeyKey); err != nil { + if err := utility.StoreCyclicKey(kv, myPrivKey, + originMyPrivKeyKey); err != nil { jww.FATAL.Panicf("Failed to store %s: %+v", originMyPrivKeyKey, err) } - if err := utility.StoreCyclicKey(kv, partnerPubKey, originPartnerPubKey); err != nil { + if err := utility.StoreCyclicKey(kv, partnerPubKey, + originPartnerPubKey); err != nil { jww.FATAL.Panicf("Failed to store %s: %+v", originPartnerPubKey, err) } m.send = NewRelationship(m.kv, session.Send, myID, partnerID, myPrivKey, - partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, sendParams, cyHandler, - grp, rng) + partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, + sendParams, cyHandler, grp, rng) m.receive = NewRelationship(m.kv, session.Receive, myID, partnerID, myPrivKey, partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, receiveParams, cyHandler, grp, rng) @@ -98,36 +96,27 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, //LoadManager loads a relationship and all buffers and sessions from disk func LoadManager(kv *versioned.KV, myID, partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group, - rng *fastRNG.StreamGenerator) (*Manager, error) { + rng *fastRNG.StreamGenerator) (Manager, error) { - mi := MakeManagerIdentity(partnerID, myID) - - m := &Manager{ - kv: kv.Prefix(makeManagerPrefix(mi)), + m := &manager{ + kv: kv.Prefix(makeManagerPrefix(partnerID)), myID: myID, partner: partnerID, cyHandler: cyHandler, grp: grp, rng: rng, - managerID: mi, } var err error m.originMyPrivKey, err = utility.LoadCyclicKey(m.kv, originMyPrivKeyKey) if err != nil { - // if the key cannot be found, this might be an old session, in which case - // we attempt to revert to the old file structure - m.kv = kv.Prefix(makeOldManagerPrefix(partnerID)) - m.originMyPrivKey, err = utility.LoadCyclicKey(m.kv, originMyPrivKeyKey) - if err != nil { - jww.FATAL.Panicf("Failed to load %s: %+v", originMyPrivKeyKey, - err) - } - + jww.FATAL.Panicf("Failed to load %s: %+v", originMyPrivKeyKey, + err) } - m.originPartnerPubKey, err = utility.LoadCyclicKey(m.kv, originPartnerPubKey) + m.originPartnerPubKey, err = utility.LoadCyclicKey(m.kv, + originPartnerPubKey) if err != nil { jww.FATAL.Panicf("Failed to load %s: %+v", originPartnerPubKey, err) @@ -137,16 +126,16 @@ func LoadManager(kv *versioned.KV, myID, partnerID *id.ID, cyHandler, grp, rng) if err != nil { return nil, errors.WithMessage(err, - "Failed to load partner key relationship due to failure to "+ - "load the Send session buffer") + "cannot load partner key relationship due to failure"+ + " to load the Send session buffer") } m.receive, err = LoadRelationship(m.kv, session.Receive, myID, partnerID, cyHandler, grp, rng) if err != nil { return nil, errors.WithMessage(err, - "Failed to load partner key relationship due to failure to "+ - "load the Receive session buffer") + "cannot load partner key relationship due to failure"+ + " to load the Receive session buffer") } return m, nil @@ -155,17 +144,16 @@ func LoadManager(kv *versioned.KV, myID, partnerID *id.ID, // ClearManager removes the relationship between the partner // and deletes the Send and Receive sessions. This includes the // sessions and the key vectors -func ClearManager(m *Manager, kv *versioned.KV) error { - kv = kv.Prefix(fmt.Sprintf(managerPrefix, m.partner)) - - if err := DeleteRelationship(m); err != nil { +func (m *manager) ClearManager() error { + if err := m.DeleteRelationship(); err != nil { return errors.WithMessage(err, "Failed to delete relationship") } - if err := utility.DeleteCyclicKey(m.kv, originPartnerPubKey); err != nil { - jww.FATAL.Panicf("Failed to delete %s: %+v", originPartnerPubKey, - err) + if err := utility.DeleteCyclicKey(m.kv, + originPartnerPubKey); err != nil { + jww.FATAL.Panicf("Failed to delete %s: %+v", + originPartnerPubKey, err) } return nil @@ -176,13 +164,14 @@ func ClearManager(m *Manager, kv *versioned.KV) error { // session already exists, then it will not be overwritten and the extant // session will be returned with the bool set to true denoting a duplicate. This // allows for support of duplicate key exchange triggering. -func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int, +func (m *manager) NewReceiveSession(partnerPubKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, e2eParams session.Params, source *session.Session) (*session.Session, bool) { // Check if the session already exists - baseKey := session.GenerateE2ESessionBaseKey(source.GetMyPrivKey(), partnerPubKey, - m.grp, source.GetMySIDHPrivKey(), partnerSIDHPubKey) + baseKey := session.GenerateE2ESessionBaseKey(source.GetMyPrivKey(), + partnerPubKey, m.grp, source.GetMySIDHPrivKey(), + partnerSIDHPubKey) sessionID := session.GetSessionIDFromBaseKey(baseKey) @@ -201,73 +190,73 @@ func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int, // NewSendSession creates a new Send session using the latest public key // received from the partner and a new private key for the user. Passing in a // private key is optional. A private key will be generated if none is passed. -func (m *Manager) NewSendSession(myPrivKey *cyclic.Int, +func (m *manager) NewSendSession(myPrivKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, e2eParams session.Params, sourceSession *session.Session) *session.Session { // Add the session to the Send session buffer and return - return m.send.AddSession(myPrivKey, sourceSession.GetPartnerPubKey(), nil, - mySIDHPrivKey, sourceSession.GetPartnerSIDHPubKey(), + return m.send.AddSession(myPrivKey, sourceSession.GetPartnerPubKey(), + nil, mySIDHPrivKey, sourceSession.GetPartnerSIDHPubKey(), sourceSession.GetID(), session.Sending, e2eParams) } // PopSendCypher gets the correct session to Send with depending on the type // of Send. -func (m *Manager) PopSendCypher() (*session.Cypher, error) { +func (m *manager) PopSendCypher() (*session.Cypher, error) { return m.send.getKeyForSending() } // PopRekeyCypher gets the correct session to Send with depending on the type // of Send. -func (m *Manager) PopRekeyCypher() (*session.Cypher, error) { +func (m *manager) PopRekeyCypher() (*session.Cypher, error) { return m.send.getKeyForRekey() } // GetPartnerID returns a copy of the ID of the partner. -func (m *Manager) GetPartnerID() *id.ID { +func (m *manager) GetPartnerID() *id.ID { return m.partner.DeepCopy() } // GetMyID returns a copy of the ID used as self. -func (m *Manager) GetMyID() *id.ID { +func (m *manager) GetMyID() *id.ID { return m.myID.DeepCopy() } // GetSendSession gets the Send session of the passed ID. Returns nil if no // session is found. -func (m *Manager) GetSendSession(sid session.SessionID) *session.Session { +func (m *manager) GetSendSession(sid session.SessionID) *session.Session { return m.send.GetByID(sid) } // GetReceiveSession gets the Receive session of the passed ID. Returns nil if // no session is found. -func (m *Manager) GetReceiveSession(sid session.SessionID) *session.Session { +func (m *manager) GetReceiveSession(sid session.SessionID) *session.Session { return m.receive.GetByID(sid) } // GetSendSession gets the Send session of the passed ID. Returns nil if no // session is found. -func (m *Manager) GetSendRelationshipFingerprint() []byte { +func (m *manager) GetSendRelationshipFingerprint() []byte { return m.send.fingerprint } // Confirm confirms a Send session is known about by the partner. -func (m *Manager) Confirm(sid session.SessionID) error { +func (m *manager) Confirm(sid session.SessionID) error { return m.send.Confirm(sid) } // TriggerNegotiations returns a list of key exchange operations if any are // necessary. -func (m *Manager) TriggerNegotiations() []*session.Session { +func (m *manager) TriggerNegotiations() []*session.Session { return m.send.TriggerNegotiation() } -func (m *Manager) GetMyOriginPrivateKey() *cyclic.Int { +func (m *manager) GetMyOriginPrivateKey() *cyclic.Int { return m.originMyPrivKey.DeepCopy() } -func (m *Manager) GetPartnerOriginPublicKey() *cyclic.Int { +func (m *manager) GetPartnerOriginPublicKey() *cyclic.Int { return m.originPartnerPubKey.DeepCopy() } @@ -276,15 +265,16 @@ 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 { +func (m *manager) GetRelationshipFingerprint() string { // Base 64 encode hash and truncate - return base64.StdEncoding.EncodeToString(m.GetRelationshipFingerprintBytes())[:relationshipFpLength] + return base64.StdEncoding.EncodeToString( + m.GetRelationshipFingerprintBytes())[:relationshipFpLength] } // GetRelationshipFingerprintBytes returns a unique fingerprint for an E2E // relationship. used for the e2e preimage. -func (m *Manager) GetRelationshipFingerprintBytes() []byte { +func (m *manager) GetRelationshipFingerprintBytes() []byte { // Sort fingerprints var fps [][]byte @@ -304,14 +294,10 @@ func (m *Manager) GetRelationshipFingerprintBytes() []byte { return h.Sum(nil) } -func (m *Manager) GetIdentity() ManagerIdentity { - return m.managerID -} - // MakeService Returns a service interface with the // appropriate identifier for who is being sent to. Will populate // the metadata with the partner -func (m *Manager) MakeService(tag string) message.Service { +func (m *manager) MakeService(tag string) message.Service { return message.Service{ Identifier: m.GetRelationshipFingerprintBytes(), Tag: tag, @@ -321,7 +307,7 @@ func (m *Manager) MakeService(tag string) message.Service { // GetContact assembles and returns a contact.Contact with the partner's ID // and DH key. -func (m *Manager) GetContact() contact.Contact { +func (m *manager) GetContact() contact.Contact { // Assemble Contact return contact.Contact{ ID: m.GetPartnerID(), @@ -329,10 +315,6 @@ func (m *Manager) GetContact() contact.Contact { } } -func makeOldManagerPrefix(pid *id.ID) string { +func makeManagerPrefix(pid *id.ID) string { return fmt.Sprintf(managerPrefix, pid) } - -func makeManagerPrefix(identity ManagerIdentity) string { - return fmt.Sprintf(managerPrefix, identity) -} diff --git a/e2e/ratchet/partner/managerID.go b/e2e/ratchet/partner/managerID.go deleted file mode 100644 index 177036b5e9abda973b5f4357bc16a8ab67369996..0000000000000000000000000000000000000000 --- a/e2e/ratchet/partner/managerID.go +++ /dev/null @@ -1,31 +0,0 @@ -package partner - -import ( - "encoding/base64" - "gitlab.com/xx_network/primitives/id" -) - -type ManagerIdentity [2 * id.ArrIDLen]byte - -func MakeManagerIdentity(partner, me *id.ID) ManagerIdentity { - ph := ManagerIdentity{} - copy(ph[:id.ArrIDLen], me[:]) - copy(ph[id.ArrIDLen:], partner[:]) - return ph -} - -func (mi ManagerIdentity) GetMe() *id.ID { - me := &id.ID{} - copy(me[:], mi[:id.ArrIDLen]) - return me -} - -func (mi ManagerIdentity) GetPartner() *id.ID { - partner := &id.ID{} - copy(partner[:], mi[id.ArrIDLen:]) - return partner -} - -func (mi ManagerIdentity) String() string { - return base64.StdEncoding.EncodeToString(mi[:]) -} diff --git a/e2e/ratchet/partner/managerID_test.go b/e2e/ratchet/partner/managerID_test.go deleted file mode 100644 index caa82f81dda26b39c21eeaf9b2e3712ffa97526f..0000000000000000000000000000000000000000 --- a/e2e/ratchet/partner/managerID_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package partner - -import ( - "gitlab.com/xx_network/primitives/id" - "math/rand" - "testing" -) - -// ManagerIdentity.GetMe unit test -func TestManagerIdentity_GetMe(t *testing.T) { - partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - myId := id.NewIdFromUInt(rand.Uint64(), id.User, t) - - mid := MakeManagerIdentity(partnerID, myId) - - if !myId.Cmp(mid.GetMe()) { - t.Fatalf("GetMe did not retrieve expected data."+ - "\nExpected: %v"+ - "\nReceived: %v", myId, mid.GetMe()) - } - -} - -// ManagerIdentity.GetPartner unit test -func TestManagerIdentity_GetPartner(t *testing.T) { - partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - myId := id.NewIdFromUInt(rand.Uint64(), id.User, t) - - mid := MakeManagerIdentity(partnerID, myId) - - if !partnerID.Cmp(mid.GetPartner()) { - t.Fatalf("GetPartner did not retrieve expected data."+ - "\nExpected: %v"+ - "\nReceived: %v", partnerID, mid.GetPartner()) - } - -} diff --git a/e2e/ratchet/partner/manager_test.go b/e2e/ratchet/partner/manager_test.go index 938218ab8215807cedef4620c171ed06d3111773..f0ffd05b9fac33be86ad92ae514bdff4f8927d2b 100644 --- a/e2e/ratchet/partner/manager_test.go +++ b/e2e/ratchet/partner/manager_test.go @@ -10,6 +10,10 @@ package partner import ( "bytes" "encoding/base64" + "math/rand" + "reflect" + "testing" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" @@ -20,9 +24,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "golang.org/x/crypto/blake2b" - "math/rand" - "reflect" - "testing" ) // Tests happy path of newManager. @@ -31,15 +32,17 @@ func Test_newManager(t *testing.T) { expectedM, kv := newTestManager(t) // Create new relationship - m := NewManager(kv, expectedM.myID, expectedM.partner, + newM := NewManager(kv, expectedM.myID, expectedM.partner, expectedM.originMyPrivKey, expectedM.originPartnerPubKey, expectedM.originMySIDHPrivKey, expectedM.originPartnerSIDHPubKey, session.GetDefaultParams(), session.GetDefaultParams(), expectedM.cyHandler, expectedM.grp, expectedM.rng) + m := newM.(*manager) + // Check if the new relationship matches the expected - if !managersEqual(expectedM, m, t) { + if !managersEqual(&expectedM, m, t) { t.Errorf("newManager() did not produce the expected Manager."+ "\n\texpected: %+v\n\treceived: %+v", expectedM, m) } @@ -51,14 +54,15 @@ func TestLoadManager(t *testing.T) { expectedM, kv := newTestManager(t) // Attempt to load relationship - m, err := LoadManager(kv, expectedM.myID, expectedM.partner, + newM, err := LoadManager(kv, expectedM.myID, expectedM.partner, expectedM.cyHandler, expectedM.grp, expectedM.rng) if err != nil { t.Errorf("LoadManager() returned an error: %v", err) } + m := newM.(*manager) // Check if the loaded relationship matches the expected - if !managersEqual(expectedM, m, t) { + if !managersEqual(&expectedM, m, t) { t.Errorf("LoadManager() did not produce the expected Manager."+ "\n\texpected: %+v\n\treceived: %+v", expectedM, m) } @@ -76,7 +80,7 @@ func TestManager_ClearManager(t *testing.T) { // Set up expected and test values expectedM, kv := newTestManager(t) - err := ClearManager(expectedM, kv) + err := expectedM.ClearManager() if err != nil { t.Fatalf("clearManager returned an error: %v", err) } @@ -251,7 +255,7 @@ func TestManager_GetPartnerID(t *testing.T) { func TestManager_GetMyID(t *testing.T) { myId := id.NewIdFromUInt(rand.Uint64(), id.User, t) - m := &Manager{myID: myId} + m := &manager{myID: myId} receivedMyId := m.GetMyID() diff --git a/e2e/ratchet/partner/relationship.go b/e2e/ratchet/partner/relationship.go index 603c6e0750825a948de10f62afee5ff24f620c6f..e41b368116068c074aa974caf546c7e6bc180525 100644 --- a/e2e/ratchet/partner/relationship.go +++ b/e2e/ratchet/partner/relationship.go @@ -9,6 +9,8 @@ package partner import ( "encoding/json" + "sync" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -18,7 +20,6 @@ import ( "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "sync" ) const maxUnconfirmed uint = 3 @@ -68,7 +69,6 @@ func NewRelationship(kv *versioned.KV, t session.RelationshipType, kv = kv.Prefix(t.Prefix()) - //build the fingerprint fingerprint := makeRelationshipFingerprint(t, grp, myOriginPrivateKey, partnerOriginPublicKey, myID, partnerID) @@ -96,7 +96,8 @@ func NewRelationship(kv *versioned.KV, t session.RelationshipType, s := session.NewSession(r.kv, r.t, partnerID, myOriginPrivateKey, partnerOriginPublicKey, nil, originMySIDHPrivKey, originPartnerSIDHPubKey, session.SessionID{}, - r.fingerprint, session.Confirmed, initialParams, cyHandler, grp, rng) + r.fingerprint, session.Confirmed, initialParams, cyHandler, + grp, rng) if err := s.Save(); err != nil { jww.FATAL.Panicf("Failed to Send session after setting to "+ @@ -147,26 +148,30 @@ func LoadRelationship(kv *versioned.KV, t session.RelationshipType, myID, // DeleteRelationship removes all relationship and // relationship adjacent information from storage -func DeleteRelationship(manager *Manager) error { +func (m *manager) DeleteRelationship() error { // Delete the send information - sendKv := manager.kv.Prefix(session.Send.Prefix()) - manager.send.Delete() + sendKv := m.kv.Prefix(session.Send.Prefix()) + m.send.Delete() if err := deleteRelationshipFingerprint(sendKv); err != nil { return err } - if err := sendKv.Delete(relationshipKey, currentRelationshipVersion); err != nil { - return errors.Errorf("Could not delete send relationship: %v", err) + if err := sendKv.Delete(relationshipKey, + currentRelationshipVersion); err != nil { + return errors.Errorf("cannot delete send relationship: %v", + err) } // Delete the receive information - receiveKv := manager.kv.Prefix(session.Receive.Prefix()) - manager.receive.Delete() + receiveKv := m.kv.Prefix(session.Receive.Prefix()) + m.receive.Delete() if err := deleteRelationshipFingerprint(receiveKv); err != nil { return err } - if err := receiveKv.Delete(relationshipKey, currentRelationshipVersion); err != nil { - return errors.Errorf("Could not delete receive relationship: %v", err) + if err := receiveKv.Delete(relationshipKey, + currentRelationshipVersion); err != nil { + return errors.Errorf("cannot delete receive relationship: %v", + err) } return nil @@ -210,7 +215,6 @@ func (r *relationship) unmarshal(b []byte) error { return err } - //load the fingerprint r.fingerprint = loadRelationshipFingerprint(r.kv) //load all the sessions @@ -323,13 +327,15 @@ func (r *relationship) getSessionForSending() *session.Session { return unconfirmedRekey[0] } - jww.INFO.Printf("[REKEY] Details about %v sessions which are invalid:", len(sessions)) + jww.INFO.Printf("[REKEY] Details about %v sessions which are invalid:", + len(sessions)) for i, s := range sessions { if s == nil { jww.INFO.Printf("[REKEY]\tSession %v is nil", i) } else { jww.INFO.Printf("[REKEY]\tSession %v: status: %v,"+ - " confirmed: %v", i, s.Status(), s.IsConfirmed()) + " confirmed: %v", i, s.Status(), + s.IsConfirmed()) } } @@ -376,10 +382,12 @@ func (r *relationship) getNewestRekeyableSession() *session.Session { for _, s := range r.sessions { jww.TRACE.Printf("[REKEY] Looking at session %s", s) //fmt.Println(i) - // This looks like it might not be thread safe, I think it is because - // the failure mode is it skips to a lower key to rekey with, which is - // always valid. It isn't clear it can fail though because we are - // accessing the data in the same order it would be written (i think) + // This looks like it might not be thread safe, I + // think it is because the failure mode is it skips to + // a lower key to rekey with, which is always + // valid. It isn't clear it can fail though because we + // are accessing the data in the same order it would + // be written (i think) if s.Status() != session.RekeyEmpty { if s.IsConfirmed() { jww.TRACE.Printf("[REKEY] Selected rekey: %s", @@ -412,7 +420,8 @@ func (r *relationship) Confirm(id session.SessionID) error { s, ok := r.sessionByID[id] if !ok { - return errors.Errorf("Could not confirm session %s, does not exist", id) + return errors.Errorf("cannot confirm session %s, "+ + "does not exist", id) } s.SetNegotiationStatus(session.Confirmed) @@ -442,7 +451,8 @@ func (r *relationship) clean() { for _, s := range r.sessions { if s.IsConfirmed() { numConfirmed++ - //if the number of newer confirmed is sufficient, delete the confirmed + //if the number of newer confirmed is + // sufficient, delete the confirmed if numConfirmed > maxUnconfirmed { delete(r.sessionByID, s.GetID()) s.Delete() @@ -458,7 +468,7 @@ func (r *relationship) clean() { r.sessions = newSessions if err := r.save(); err != nil { - jww.FATAL.Printf("Failed to save Session Buffer %s after "+ + jww.FATAL.Printf("cannot save Session Buffer %s after "+ "clean: %s", r.kv.GetFullKey(relationshipKey, currentRelationshipVersion), err) } diff --git a/e2e/ratchet/partner/relationshipFingerprint.go b/e2e/ratchet/partner/relationshipFingerprint.go index 0cceefc61cb8aa6e2e0b6e461689fff8e3b704a4..e00f6aa69638830752b079332e63f0f6bb68755f 100644 --- a/e2e/ratchet/partner/relationshipFingerprint.go +++ b/e2e/ratchet/partner/relationshipFingerprint.go @@ -52,14 +52,13 @@ func loadRelationshipFingerprint(kv *versioned.KV) []byte { obj, err := kv.Get(relationshipFingerprintKey, currentRelationshipVersion) if err != nil { - jww.FATAL.Panicf("Failed to load relationshipFingerprint at %s: "+ + jww.FATAL.Panicf("cannot load relationshipFingerprint at %s: "+ "%s", kv.GetFullKey(relationshipFingerprintKey, currentRelationshipFingerprintVersion), err) } return obj.Data } -// deleteRelationshipFingerprint is a helper function which deletes a fingerprint from store func deleteRelationshipFingerprint(kv *versioned.KV) error { return kv.Delete(relationshipFingerprintKey, currentRelationshipVersion) diff --git a/e2e/ratchet/partner/relationship_test.go b/e2e/ratchet/partner/relationship_test.go index 2dc11017a9f4160586b82a0017daffb19fe9caf7..911a5f711d43eb1af403872d65d6e4ad6a1d2ad7 100644 --- a/e2e/ratchet/partner/relationship_test.go +++ b/e2e/ratchet/partner/relationship_test.go @@ -8,6 +8,9 @@ package partner import ( + "reflect" + "testing" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" util "gitlab.com/elixxir/client/storage/utility" @@ -19,8 +22,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" - "reflect" - "testing" ) // Subtest: unmarshal/marshal with one session in the buff @@ -89,7 +90,7 @@ func TestDeleteRelationship(t *testing.T) { t.Fatal(err) } - err := DeleteRelationship(mgr) + err := mgr.DeleteRelationship() if err != nil { t.Fatalf("DeleteRelationship error: Could not delete manager: %v", err) } @@ -842,7 +843,7 @@ func TestSessionBuff_TriggerNegotiation(t *testing.T) { } } -func makeTestRelationshipManager(t *testing.T) (*Manager, *versioned.KV) { +func makeTestRelationshipManager(t *testing.T) (*manager, *versioned.KV) { grp := cyclic.NewGroup( large.NewIntFromString("E2EE983D031DC1DB6F1A7A67DF0E9A8E5561DB8E8D49413394C049B"+ "7A8ACCEDC298708F121951D9CF920EC5D146727AA4AE535B0922C688B55B3DD2AE"+ @@ -876,7 +877,7 @@ func makeTestRelationshipManager(t *testing.T) (*Manager, *versioned.KV) { kv := versioned.NewKV(make(ekv.Memstore)) frng := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) - return &Manager{ + return &manager{ kv: kv, myID: myID, partner: id.NewIdFromString("zezima", id.User, t), diff --git a/e2e/ratchet/partner/utils_test.go b/e2e/ratchet/partner/utils_test.go index 7984535e240a2dfdc77450a941ba8874eb616229..910384d7ce98fa557f936f13e5b94bfbbe7650a6 100644 --- a/e2e/ratchet/partner/utils_test.go +++ b/e2e/ratchet/partner/utils_test.go @@ -2,6 +2,9 @@ package partner import ( "bytes" + "reflect" + "testing" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" util "gitlab.com/elixxir/client/storage/utility" @@ -13,8 +16,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" - "reflect" - "testing" ) type mockCyHandler struct { @@ -50,7 +51,7 @@ func getGroup() *cyclic.Group { } // newTestManager returns a new relationship for testing. -func newTestManager(t *testing.T) (*Manager, *versioned.KV) { +func newTestManager(t *testing.T) (manager, *versioned.KV) { if t == nil { panic("Cannot run this outside tests") } @@ -83,10 +84,12 @@ func newTestManager(t *testing.T) (*Manager, *versioned.KV) { mockCyHandler{}, grp, fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)) - return m, kv + newM := m.(*manager) + + return *newM, kv } -func managersEqual(expected, received *Manager, t *testing.T) bool { +func managersEqual(expected, received *manager, t *testing.T) bool { equal := true if !reflect.DeepEqual(expected.cyHandler, received.cyHandler) { t.Errorf("Did not Receive expected Manager.cyHandler."+ diff --git a/e2e/ratchet/ratchet.go b/e2e/ratchet/ratchet.go index 2396ceef7eccdbeebcd5b15b60ab14dbcabf5fb1..fd1d6f28994bb798ce0635f0d935a01f49bb7e35 100644 --- a/e2e/ratchet/ratchet.go +++ b/e2e/ratchet/ratchet.go @@ -8,6 +8,8 @@ package ratchet import ( + "sync" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -20,7 +22,6 @@ import ( "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" - "sync" ) const ( @@ -32,12 +33,12 @@ const ( var NoPartnerErrorStr = "No relationship with partner found" type Ratchet struct { - managers map[partner.ManagerIdentity]*partner.Manager + managers map[id.ID]partner.Manager mux sync.RWMutex - defaultID *id.ID - defaultDHPrivateKey *cyclic.Int - defaultDHPublicKey *cyclic.Int + myID *id.ID + advertisedDHPrivateKey *cyclic.Int + advertisedDHPublicKey *cyclic.Int grp *cyclic.Group cyHandler session.CypherHandler @@ -65,12 +66,12 @@ func New(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, kv = kv.Prefix(packagePrefix) r := &Ratchet{ - managers: make(map[partner.ManagerIdentity]*partner.Manager), + managers: make(map[id.ID]partner.Manager), services: make(map[string]message.Processor), - defaultID: myID, - defaultDHPrivateKey: privKey, - defaultDHPublicKey: pubKey, + myID: myID, + advertisedDHPrivateKey: privKey, + advertisedDHPublicKey: pubKey, kv: kv, @@ -94,16 +95,14 @@ func New(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, // AddPartner adds a partner. Automatically creates both send and receive // sessions using the passed cryptographic data and per the parameters sent -func (r *Ratchet) AddPartner(myID *id.ID, partnerID *id.ID, +func (r *Ratchet) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, - receiveParams session.Params) (*partner.Manager, error) { + receiveParams session.Params) (partner.Manager, error) { r.mux.Lock() defer r.mux.Unlock() - if myID == nil { - myID = r.defaultID - } + myID := r.myID jww.INFO.Printf("Adding Partner %s:\n\tMy Private Key: %s"+ "\n\tPartner Public Key: %s to %s", @@ -111,13 +110,13 @@ func (r *Ratchet) AddPartner(myID *id.ID, partnerID *id.ID, myPrivKey.TextVerbose(16, 0), partnerPubKey.TextVerbose(16, 0), myID) - mid := partner.MakeManagerIdentity(partnerID, myID) + mid := *partnerID if _, ok := r.managers[mid]; ok { return nil, errors.New("Cannot overwrite existing partner") } - m := partner.NewManager(r.kv, r.defaultID, partnerID, myPrivKey, partnerPubKey, - mySIDHPrivKey, partnerSIDHPubKey, + m := partner.NewManager(r.kv, r.myID, partnerID, myPrivKey, + partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, sendParams, receiveParams, r.cyHandler, r.grp, r.rng) r.managers[mid] = m @@ -133,15 +132,11 @@ func (r *Ratchet) AddPartner(myID *id.ID, partnerID *id.ID, } // GetPartner returns the partner per its ID, if it exists -func (r *Ratchet) GetPartner(partnerID *id.ID, myID *id.ID) (*partner.Manager, error) { +func (r *Ratchet) GetPartner(partnerID *id.ID) (partner.Manager, error) { r.mux.RLock() defer r.mux.RUnlock() - if myID == nil { - myID = r.defaultID - } - - m, ok := r.managers[partner.MakeManagerIdentity(partnerID, myID)] + m, ok := r.managers[*partnerID] if !ok { return nil, errors.New(NoPartnerErrorStr) @@ -151,53 +146,49 @@ func (r *Ratchet) GetPartner(partnerID *id.ID, myID *id.ID) (*partner.Manager, e } // DeletePartner removes the associated contact from the E2E store -func (r *Ratchet) DeletePartner(partnerId *id.ID, myID *id.ID) error { - if myID == nil { - myID = r.defaultID - } - - rShip := partner.MakeManagerIdentity(partnerId, myID) - m, ok := r.managers[rShip] +func (r *Ratchet) DeletePartner(partnerID *id.ID) error { + m, ok := r.managers[*partnerID] if !ok { return errors.New(NoPartnerErrorStr) } - if err := partner.ClearManager(m, r.kv); err != nil { - return errors.WithMessagef(err, "Could not remove partner %s from store", partnerId) + if err := m.ClearManager(); err != nil { + return errors.WithMessagef(err, + "Could not remove partner %s from store", + partnerID) } //delete services r.delete(m) - delete(r.managers, rShip) + delete(r.managers, *partnerID) return r.save() } // GetAllPartnerIDs returns a list of all partner IDs that the user has // an E2E relationship with. -func (r *Ratchet) GetAllPartnerIDs(myID *id.ID) []*id.ID { +func (r *Ratchet) GetAllPartnerIDs() []*id.ID { r.mux.RLock() defer r.mux.RUnlock() - partnerIds := make([]*id.ID, 0, len(r.managers)) + partnerIDs := make([]*id.ID, 0, len(r.managers)) for _, m := range r.managers { - if m.GetMyID().Cmp(myID) { - partnerIds = append(partnerIds, m.GetPartnerID()) - } - + partnerIDs = append(partnerIDs, m.GetPartnerID()) } - return partnerIds + return partnerIDs } -// GetDHPrivateKey returns the diffie hellman private key. +// GetDHPrivateKey returns the diffie hellman private key used +// to initially establish the ratchet. func (r *Ratchet) GetDHPrivateKey() *cyclic.Int { - return r.defaultDHPrivateKey + return r.advertisedDHPrivateKey } -// GetDHPublicKey returns the diffie hellman public key. +// GetDHPublicKey returns the diffie hellman public key used +// to initially establish the ratchet. func (r *Ratchet) GetDHPublicKey() *cyclic.Int { - return r.defaultDHPublicKey + return r.advertisedDHPublicKey } diff --git a/e2e/ratchet/ratchet_test.go b/e2e/ratchet/ratchet_test.go index b6b03da10664292e2fb81967f9b88c3396ac3ffe..2fa7f095f06a294587b2a3c89a0bc25dd9919dc7 100644 --- a/e2e/ratchet/ratchet_test.go +++ b/e2e/ratchet/ratchet_test.go @@ -9,6 +9,11 @@ package ratchet import ( "bytes" + "math/rand" + "reflect" + "sort" + "testing" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" @@ -19,10 +24,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" - "math/rand" - "reflect" - "sort" - "testing" ) // Tests happy path of NewStore. @@ -31,11 +32,11 @@ func TestNewStore(t *testing.T) { privKey := grp.NewInt(57) kv := versioned.NewKV(make(ekv.Memstore)) expectedStore := &Ratchet{ - managers: make(map[partner.ManagerIdentity]*partner.Manager), - defaultDHPrivateKey: privKey, - defaultDHPublicKey: diffieHellman.GeneratePublicKey(privKey, grp), - grp: grp, - kv: kv.Prefix(packagePrefix), + managers: make(map[id.ID]partner.Manager), + advertisedDHPrivateKey: privKey, + advertisedDHPublicKey: diffieHellman.GeneratePublicKey(privKey, grp), + grp: grp, + kv: kv.Prefix(packagePrefix), } expectedData, err := expectedStore.marshal() if err != nil { @@ -90,19 +91,19 @@ func TestStore_AddPartner(t *testing.T) { partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) p := session.GetDefaultParams() - partnerPubKey := diffieHellman.GeneratePublicKey(r.defaultDHPrivateKey, r.grp) + partnerPubKey := diffieHellman.GeneratePublicKey(r.advertisedDHPrivateKey, r.grp) // NOTE: e2e store doesn't contain a private SIDH key, that's // because they're completely address as part of the // initiation of the connection. _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) myPrivSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - expectedManager := partner.NewManager(kv, r.defaultID, partnerID, - r.defaultDHPrivateKey, partnerPubKey, myPrivSIDHKey, pubSIDHKey, + expectedManager := partner.NewManager(kv, r.myID, partnerID, + r.advertisedDHPrivateKey, partnerPubKey, myPrivSIDHKey, pubSIDHKey, p, p, r.cyHandler, r.grp, r.rng) receivedManager, err := r.AddPartner( - r.defaultID, partnerID, - partnerPubKey, r.defaultDHPrivateKey, + partnerID, + partnerPubKey, r.advertisedDHPrivateKey, pubSIDHKey, myPrivSIDHKey, p, p) if err != nil { t.Fatalf("AddPartner returned an error: %v", err) @@ -112,7 +113,7 @@ func TestStore_AddPartner(t *testing.T) { t.Errorf("Inconsistent data between partner.Managers") } - relationshipId := partner.MakeManagerIdentity(partnerID, r.defaultID) + relationshipId := *partnerID m, exists := r.managers[relationshipId] if !exists { @@ -134,7 +135,7 @@ func TestStore_DeletePartner(t *testing.T) { } partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - partnerPubKey := diffieHellman.GeneratePublicKey(r.defaultDHPrivateKey, r.grp) + partnerPubKey := diffieHellman.GeneratePublicKey(r.advertisedDHPrivateKey, r.grp) p := session.GetDefaultParams() // NOTE: e2e store doesn't contain a private SIDH key, that's // because they're completely address as part of the @@ -142,18 +143,18 @@ func TestStore_DeletePartner(t *testing.T) { _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) myPrivSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - _, err = r.AddPartner(r.defaultID, partnerID, r.defaultDHPrivateKey, + _, err = r.AddPartner(partnerID, r.advertisedDHPrivateKey, partnerPubKey, pubSIDHKey, myPrivSIDHKey, p, p) if err != nil { t.Fatalf("AddPartner returned an error: %v", err) } - err = r.DeletePartner(partnerID, r.defaultID) + err = r.DeletePartner(partnerID) if err != nil { t.Fatalf("DeletePartner received an error: %v", err) } - _, err = r.GetPartner(partnerID, r.defaultID) + _, err = r.GetPartner(partnerID) if err == nil { t.Errorf("Shouldn't be able to pull deleted partner from store") } @@ -168,17 +169,17 @@ func TestStore_GetPartner(t *testing.T) { t.Fatalf("Setup error: %v", err) } partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - partnerPubKey := diffieHellman.GeneratePublicKey(r.defaultDHPrivateKey, r.grp) + partnerPubKey := diffieHellman.GeneratePublicKey(r.advertisedDHPrivateKey, r.grp) p := session.GetDefaultParams() _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) myPrivSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - expectedManager, err := r.AddPartner(r.defaultID, partnerID, r.defaultDHPrivateKey, + expectedManager, err := r.AddPartner(partnerID, r.advertisedDHPrivateKey, partnerPubKey, pubSIDHKey, myPrivSIDHKey, p, p) if err != nil { t.Fatalf("AddPartner returned an error: %v", err) } - m, err := r.GetPartner(partnerID, r.defaultID) + m, err := r.GetPartner(partnerID) if err != nil { t.Errorf("GetPartner() produced an error: %v", err) } @@ -203,11 +204,11 @@ func TestRatchet_GetAllPartnerIDs(t *testing.T) { // Generate partners and add them ot the manager for i := 0; i < numTests; i++ { partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - partnerPubKey := diffieHellman.GeneratePublicKey(r.defaultDHPrivateKey, r.grp) + partnerPubKey := diffieHellman.GeneratePublicKey(r.advertisedDHPrivateKey, r.grp) p := session.GetDefaultParams() _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) myPrivSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - _, err := r.AddPartner(r.defaultID, partnerID, r.defaultDHPrivateKey, + _, err := r.AddPartner(partnerID, r.advertisedDHPrivateKey, partnerPubKey, pubSIDHKey, myPrivSIDHKey, p, p) if err != nil { t.Fatalf("AddPartner returned an error: %v", err) @@ -216,7 +217,7 @@ func TestRatchet_GetAllPartnerIDs(t *testing.T) { expectedPartners = append(expectedPartners, partnerID) } - receivedPartners := r.GetAllPartnerIDs(r.defaultID) + receivedPartners := r.GetAllPartnerIDs() // Sort these slices as GetAllPartnerIDs iterates over a map, which indices // at random in Go @@ -244,7 +245,7 @@ func TestStore_GetPartner_Error(t *testing.T) { } partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) - m, err := r.GetPartner(partnerID, r.defaultID) + m, err := r.GetPartner(partnerID) if err == nil { t.Error("GetPartner() did not produce an error.") } @@ -262,10 +263,10 @@ func TestStore_GetDHPrivateKey(t *testing.T) { t.Fatalf("Setup error: %v", err) } - if r.defaultDHPrivateKey != r.GetDHPrivateKey() { + if r.advertisedDHPrivateKey != r.GetDHPrivateKey() { t.Errorf("GetDHPrivateKey() returned incorrect key."+ "\n\texpected: %v\n\treceived: %v", - r.defaultDHPrivateKey, r.GetDHPrivateKey()) + r.advertisedDHPrivateKey, r.GetDHPrivateKey()) } } @@ -276,9 +277,9 @@ func TestStore_GetDHPublicKey(t *testing.T) { t.Fatalf("Setup error: %v", err) } - if r.defaultDHPublicKey != r.GetDHPublicKey() { + if r.advertisedDHPublicKey != r.GetDHPublicKey() { t.Errorf("GetDHPublicKey() returned incorrect key."+ "\n\texpected: %v\n\treceived: %v", - r.defaultDHPublicKey, r.GetDHPublicKey()) + r.advertisedDHPublicKey, r.GetDHPublicKey()) } } diff --git a/e2e/ratchet/serviceList.go b/e2e/ratchet/serviceList.go index 040a78622f7d89b813048b2cd00a61701351757b..0bd23650b751e167b92a7eb608b92d2a4b0c6483 100644 --- a/e2e/ratchet/serviceList.go +++ b/e2e/ratchet/serviceList.go @@ -15,19 +15,19 @@ type Services interface { processor message.Processor) } -func (r *Ratchet) add(m *partner.Manager) { +func (r *Ratchet) add(m partner.Manager) { r.servicesmux.RLock() defer r.servicesmux.RUnlock() for tag, process := range r.services { - r.sInteface.AddService(r.defaultID, m.MakeService(tag), process) + r.sInteface.AddService(r.myID, m.MakeService(tag), process) } } -func (r *Ratchet) delete(m *partner.Manager) { +func (r *Ratchet) delete(m partner.Manager) { r.servicesmux.RLock() defer r.servicesmux.RUnlock() for tag, process := range r.services { - r.sInteface.DeleteService(r.defaultID, m.MakeService(tag), process) + r.sInteface.DeleteService(r.myID, m.MakeService(tag), process) } } @@ -42,7 +42,7 @@ func (r *Ratchet) AddService(tag string, processor message.Processor) error { //add a service for every manager for _, m := range r.managers { - r.sInteface.AddService(r.defaultID, m.MakeService(tag), processor) + r.sInteface.AddService(r.myID, m.MakeService(tag), processor) } return nil @@ -61,7 +61,7 @@ func (r *Ratchet) RemoveService(tag string) error { delete(r.services, tag) for _, m := range r.managers { - r.sInteface.DeleteService(r.defaultID, m.MakeService(tag), oldServiceProcess) + r.sInteface.DeleteService(r.myID, m.MakeService(tag), oldServiceProcess) } return nil diff --git a/e2e/ratchet/storage.go b/e2e/ratchet/storage.go index d3b889a2698417413df6d268eb51da8c3171ce58..5ffea5fa63b6f9fcd685be70a8baae5feac592a3 100644 --- a/e2e/ratchet/storage.go +++ b/e2e/ratchet/storage.go @@ -2,6 +2,7 @@ package ratchet import ( "encoding/json" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix/message" @@ -27,10 +28,10 @@ func Load(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, kv = kv.Prefix(packagePrefix) r := &Ratchet{ - managers: make(map[partner.ManagerIdentity]*partner.Manager), + managers: make(map[id.ID]partner.Manager), services: make(map[string]message.Processor), - defaultID: myID, + myID: myID, kv: kv, @@ -42,17 +43,7 @@ func Load(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, obj, err := kv.Get(storeKey, currentStoreVersion) if err != nil { - //try to load an old one - obj, err = kv.Get(storeKey, 0) - if err != nil { - return nil, err - } else { - err = r.unmarshalOld(obj.Data) - if err != nil { - return nil, err - } - } - + return nil, err } else { err = r.unmarshal(obj.Data) if err != nil { @@ -91,8 +82,9 @@ func (r *Ratchet) save() error { } // ekv functions + func (r *Ratchet) marshal() ([]byte, error) { - contacts := make([]partner.ManagerIdentity, len(r.managers)) + contacts := make([]id.ID, len(r.managers)) index := 0 for rid, _ := range r.managers { @@ -103,9 +95,7 @@ func (r *Ratchet) marshal() ([]byte, error) { return json.Marshal(&contacts) } -// In the event an old structure was loaded, unmarshal it and upgrade it -// todo: test this with some old kv data -func (r *Ratchet) unmarshalOld(b []byte) error { +func (r *Ratchet) unmarshal(b []byte) error { var contacts []id.ID @@ -116,20 +106,21 @@ func (r *Ratchet) unmarshalOld(b []byte) error { } for i := range contacts { - //load the contact separately to ensure pointers do not get swapped + //load the contact separately to ensure pointers do + // not get swapped partnerID := (&contacts[i]).DeepCopy() - // Load the relationship. The relationship handles adding the fingerprints via the - // context object - manager, err := partner.LoadManager(r.kv, r.defaultID, partnerID, + // Load the relationship. The relationship handles + // adding the fingerprints via the context object + manager, err := partner.LoadManager(r.kv, r.myID, partnerID, r.cyHandler, r.grp, r.rng) if err != nil { - jww.FATAL.Panicf("Failed to load relationship for partner %s: %s", - partnerID, err.Error()) + jww.FATAL.Panicf("cannot load relationship for partner"+ + " %s: %s", partnerID, err.Error()) } if !manager.GetPartnerID().Cmp(partnerID) { - jww.FATAL.Panicf("Loaded a manager with the wrong partner "+ - "ID: \n\t loaded: %s \n\t present: %s", + jww.FATAL.Panicf("Loaded manager with the wrong "+ + "partner ID: \n\t loaded: %s \n\t present: %s", partnerID, manager.GetPartnerID()) } @@ -137,66 +128,16 @@ func (r *Ratchet) unmarshalOld(b []byte) error { r.add(manager) //assume - r.managers[partner.MakeManagerIdentity(partnerID, r.defaultID)] = manager - } - - r.defaultDHPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey) - if err != nil { - return errors.WithMessage(err, - "Failed to load e2e DH private key") - } - - r.defaultDHPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey) - if err != nil { - return errors.WithMessage(err, - "Failed to load e2e DH public key") - } - - return nil -} - -func (r *Ratchet) unmarshal(b []byte) error { - - var contacts []partner.ManagerIdentity - - err := json.Unmarshal(b, &contacts) - - if err != nil { - return err - } - - for i := range contacts { - //load the contact separately to ensure pointers do not get swapped - partnerID := contacts[i].GetPartner() - myID := contacts[i].GetMe() - // Load the relationship. The relationship handles adding the fingerprints via the - // context object - manager, err := partner.LoadManager(r.kv, myID, partnerID, - r.cyHandler, r.grp, r.rng) - if err != nil { - jww.FATAL.Panicf("Failed to load relationship for partner %s: %s", - partnerID, err.Error()) - } - - if !manager.GetPartnerID().Cmp(partnerID) { - jww.FATAL.Panicf("Loaded a manager with the wrong partner "+ - "ID: \n\t loaded: %s \n\t present: %s", - partnerID, manager.GetPartnerID()) - } - - //add services for the manager - r.add(manager) - - r.managers[contacts[i]] = manager + r.managers[*partnerID] = manager } - r.defaultDHPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey) + r.advertisedDHPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey) if err != nil { return errors.WithMessage(err, "Failed to load e2e DH private key") } - r.defaultDHPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey) + r.advertisedDHPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey) if err != nil { return errors.WithMessage(err, "Failed to load e2e DH public key") diff --git a/e2e/ratchet/utils_test.go b/e2e/ratchet/utils_test.go index 814155300b938aad2572863b09023d04f7afcb6e..9c2b763e93e4d6864d92632f009b593b31016549 100644 --- a/e2e/ratchet/utils_test.go +++ b/e2e/ratchet/utils_test.go @@ -1,6 +1,11 @@ package ratchet import ( + "io" + "reflect" + "strings" + "testing" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" "gitlab.com/elixxir/client/cmix/message" @@ -14,10 +19,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/primitives/id" - "io" - "reflect" - "strings" - "testing" ) func makeTestRatchet() (*Ratchet, *versioned.KV, error) { @@ -42,7 +43,7 @@ func makeTestRatchet() (*Ratchet, *versioned.KV, error) { return r, kv, err } -func managersEqual(expected, received *partner.Manager, t *testing.T) bool { +func managersEqual(expected, received partner.Manager, t *testing.T) bool { equal := true if !reflect.DeepEqual(expected.GetPartnerID(), received.GetPartnerID()) { t.Errorf("Did not Receive expected Manager.partnerID."+ diff --git a/e2e/receive/listener.go b/e2e/receive/listener.go index e0a66cfe1fd20aa35634fbf6135e1ac977e155f3..2bef0525c185a291ee861d9447dd9e18824a6109 100644 --- a/e2e/receive/listener.go +++ b/e2e/receive/listener.go @@ -22,13 +22,13 @@ type Listener interface { Name() string } -// ListenerFunc This function type defines callbacks that get passed when the listener is -// listened to. It will always be called in its own goroutine. It may be called -// multiple times simultaneously +// ListenerFunc This function type defines callbacks that get passed +// when the listener is listened to. It will always be called in its +// own goroutine. It may be called multiple times simultaneously type ListenerFunc func(item Message) -// ListenerID id object returned when a listener is created and is used to delete it from -// the system +// ListenerID id object returned when a listener is created and is +// used to delete it from the system type ListenerID struct { userID *id.ID messageType catalog.MessageType diff --git a/e2e/rekey/confirm.go b/e2e/rekey/confirm.go index 69c398e8ffce2c50ff360a502eba48a10f0350e2..a7094d9254ed15390d66ce0542109169341019d3 100644 --- a/e2e/rekey/confirm.go +++ b/e2e/rekey/confirm.go @@ -42,7 +42,7 @@ func handleConfirm(ratchet *ratchet.Ratchet, confirmation receive.Message) { } //get the partner - partner, err := ratchet.GetPartner(confirmation.Sender, confirmation.RecipientID) + partner, err := ratchet.GetPartner(confirmation.Sender) if err != nil { jww.ERROR.Printf( "[REKEY] Received Key Exchange Confirmation with unknown "+ diff --git a/e2e/rekey/confirm_test.go b/e2e/rekey/confirm_test.go index 3cfbfb57d27355d59d5f82b7dc59a8d0920c89c3..fe9115392b6376c87de4805c76a685dacbbe5881 100644 --- a/e2e/rekey/confirm_test.go +++ b/e2e/rekey/confirm_test.go @@ -8,6 +8,9 @@ package rekey import ( + "math/rand" + "testing" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/catalog" @@ -22,8 +25,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "math/rand" - "testing" ) // Smoke test for handleConfirm @@ -69,7 +70,8 @@ func TestHandleConfirm(t *testing.T) { // Add bob as a partner sendParams := session.GetDefaultParams() receiveParams := session.GetDefaultParams() - _, err = r.AddPartner(myID, bobID, bobPubKey, alicePrivKey, bobSIDHPubKey, aliceSIDHPrivKey, sendParams, receiveParams) + _, err = r.AddPartner(bobID, bobPubKey, alicePrivKey, + bobSIDHPubKey, aliceSIDHPrivKey, sendParams, receiveParams) if err != nil { t.Errorf("Failed to add partner to ratchet: %+v", err) } @@ -78,7 +80,7 @@ func TestHandleConfirm(t *testing.T) { aliceSIDHPrivKey, bobSIDHPubKey) // get Alice's manager for Bob - receivedManager, err := r.GetPartner(bobID, myID) + receivedManager, err := r.GetPartner(bobID) if err != nil { t.Errorf("Bob is not recognized as Alice's partner: %v", err) } @@ -112,7 +114,8 @@ func TestHandleConfirm(t *testing.T) { if newSession.NegotiationStatus() != session.Confirmed { t.Errorf("Session not in confirmed status!"+ "\n\tExpected: Confirmed"+ - "\n\tReceived: %s", confirmedSession.NegotiationStatus()) + "\n\tReceived: %s", + confirmedSession.NegotiationStatus()) } } diff --git a/e2e/rekey/exchange_test.go b/e2e/rekey/exchange_test.go index b31b232d381123c631e0ea6c8121a1263d23e8ef..6e4f3036144fb3fcf33617dfc26fcb9c3021bb27 100644 --- a/e2e/rekey/exchange_test.go +++ b/e2e/rekey/exchange_test.go @@ -9,6 +9,10 @@ package rekey import ( "fmt" + "math/rand" + "testing" + "time" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/catalog" @@ -23,9 +27,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "math/rand" - "testing" - "time" ) var r *ratchet.Ratchet @@ -82,7 +83,8 @@ func TestFullExchange(t *testing.T) { if err != nil { t.Errorf("Failed to create ratchet: %+v", err) } - r, err = ratchet.Load(kv, aliceID, grp, mockCyHandler{}, mockServiceHandler{}, rng) + r, err = ratchet.Load(kv, aliceID, grp, mockCyHandler{}, + mockServiceHandler{}, rng) if err != nil { t.Errorf("Failed to load ratchet: %+v", err) } @@ -90,13 +92,15 @@ func TestFullExchange(t *testing.T) { // Add Alice and Bob as partners sendParams := session.GetDefaultParams() receiveParams := session.GetDefaultParams() - _, err = r.AddPartner(aliceID, bobID, bobPubKey, + // NOTE: Shouldn't these use different ratchets? + // probably fine for this test... + _, err = r.AddPartner(bobID, bobPubKey, alicePrivKey, bobSIDHPubKey, aliceSIDHPrivKey, sendParams, receiveParams) if err != nil { t.Errorf("Failed to add partner to ratchet: %+v", err) } - _, err = r.AddPartner(bobID, aliceID, alicePubKey, + _, err = r.AddPartner(aliceID, alicePubKey, bobPrivKey, aliceSIDHPubKey, bobSIDHPrivKey, sendParams, receiveParams) if err != nil { @@ -106,11 +110,13 @@ func TestFullExchange(t *testing.T) { // Start the listeners for alice and bob rekeyParams := GetDefaultParams() rekeyParams.RoundTimeout = 1 * time.Second - _, err = Start(aliceSwitchboard, r, testSendE2E, &mockNetManager{}, grp, rekeyParams) + _, err = Start(aliceSwitchboard, r, testSendE2E, &mockNetManager{}, + grp, rekeyParams) if err != nil { t.Errorf("Failed to Start alice: %+v", err) } - _, err = Start(bobSwitchboard, r, testSendE2E, &mockNetManager{}, grp, rekeyParams) + _, err = Start(bobSwitchboard, r, testSendE2E, &mockNetManager{}, + grp, rekeyParams) if err != nil { t.Errorf("Failed to Start bob: %+v", err) } @@ -135,7 +141,7 @@ func TestFullExchange(t *testing.T) { } // get Alice's manager for reception from Bob - receivedManager, err := r.GetPartner(bobID, aliceID) + receivedManager, err := r.GetPartner(bobID) if err != nil { t.Errorf("Failed to get bob's manager: %v", err) } @@ -156,9 +162,11 @@ func TestFullExchange(t *testing.T) { // Check that the Alice's session for Bob is in the proper status newSession := receivedManager.GetReceiveSession(newSessionID) - if newSession == nil || newSession.NegotiationStatus() != session.Confirmed { + if newSession == nil || newSession.NegotiationStatus() != + session.Confirmed { t.Errorf("Session not in confirmed status!"+ "\n\tExpected: Confirmed"+ - "\n\tReceived: %s", confirmedSession.NegotiationStatus()) + "\n\tReceived: %s", + confirmedSession.NegotiationStatus()) } } diff --git a/e2e/rekey/rekey.go b/e2e/rekey/rekey.go index ec09947b0627e40e28c7c4bc6e30c253fb002c03..91209bd741f62d039fc9a46276d13ab7727a2a92 100644 --- a/e2e/rekey/rekey.go +++ b/e2e/rekey/rekey.go @@ -9,6 +9,8 @@ package rekey import ( "fmt" + "time" + "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -22,11 +24,10 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/primitives/states" - "time" ) func CheckKeyExchanges(instance *commsNetwork.Instance, grp *cyclic.Group, - sendE2E E2eSender, events event.Manager, manager *partner.Manager, + sendE2E E2eSender, events event.Manager, manager partner.Manager, param Params, sendTimeout time.Duration) { //get all sessions that may need a key exchange @@ -44,7 +45,7 @@ func CheckKeyExchanges(instance *commsNetwork.Instance, grp *cyclic.Group, // session. They run the same negotiation, the former does it on a newly created // session while the latter on an extant session func trigger(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSender, - events event.Manager, manager *partner.Manager, inputSession *session.Session, + events event.Manager, manager partner.Manager, inputSession *session.Session, sendTimeout time.Duration, params Params) { var negotiatingSession *session.Session diff --git a/e2e/rekey/trigger.go b/e2e/rekey/trigger.go index c993c514dc21f85709c591755e7b195a8f7c1102..c44fba7ff728fc81a8cfeeccc46eae85ea3a8974 100644 --- a/e2e/rekey/trigger.go +++ b/e2e/rekey/trigger.go @@ -9,6 +9,7 @@ package rekey import ( "fmt" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "github.com/pkg/errors" @@ -60,7 +61,7 @@ func handleTrigger(ratchet *ratchet.Ratchet, sender E2eSender, } //get the partner - partner, err := ratchet.GetPartner(request.Sender, request.RecipientID) + partner, err := ratchet.GetPartner(request.Sender) if err != nil { errMsg := fmt.Sprintf(errUnknown, request.Sender) jww.ERROR.Printf(errMsg) diff --git a/e2e/rekey/trigger_test.go b/e2e/rekey/trigger_test.go index a0feb8673988920a546ab7a31fca6c922c0658e4..7d6586ac6dc2d63c6ccab8f7699ecbdf7bfcaa1d 100644 --- a/e2e/rekey/trigger_test.go +++ b/e2e/rekey/trigger_test.go @@ -8,6 +8,10 @@ package rekey import ( + "math/rand" + "testing" + "time" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/catalog" @@ -23,9 +27,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "math/rand" - "testing" - "time" ) // Smoke test for handleTrigger @@ -83,13 +84,13 @@ func TestHandleTrigger(t *testing.T) { // Add bob as a partner sendParams := session2.GetDefaultParams() receiveParams := session2.GetDefaultParams() - _, err = r.AddPartner(aliceID, bobID, bobPubKey, + _, err = r.AddPartner(bobID, bobPubKey, alicePrivKey, bobSIDHPubKey, aliceSIDHPrivKey, sendParams, receiveParams) if err != nil { t.Errorf("Failed to add partner to ratchet: %+v", err) } - _, err = r.AddPartner(bobID, aliceID, alicePubKey, bobPrivKey, + _, err = r.AddPartner(aliceID, alicePubKey, bobPrivKey, aliceSIDHPubKey, bobSIDHPrivKey, sendParams, receiveParams) if err != nil { @@ -125,7 +126,7 @@ func TestHandleTrigger(t *testing.T) { // get Alice's manager for reception from Bob - receivedManager, err := r.GetPartner(bobID, aliceID) + receivedManager, err := r.GetPartner(bobID) if err != nil { t.Errorf("Failed to get bob's manager: %v", err) } diff --git a/e2e/rekey/utils_test.go b/e2e/rekey/utils_test.go index 2f817871e7bdb11b7b98a38f91dc3ae95130aab7..173c0f14f02060736cdd167c2748435ae01b1f8a 100644 --- a/e2e/rekey/utils_test.go +++ b/e2e/rekey/utils_test.go @@ -8,6 +8,10 @@ package rekey import ( + "math/rand" + "testing" + "time" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/catalog" @@ -33,9 +37,6 @@ import ( "gitlab.com/xx_network/primitives/ndf" "gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/region" - "math/rand" - "testing" - "time" ) func GeneratePartnerID(aliceKey, bobKey *cyclic.Int, @@ -74,11 +75,11 @@ func genSidhKeys() (*sidh.PrivateKey, *sidh.PublicKey, *sidh.PrivateKey, *sidh.P func testSendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, cmixParams cmix.CMIXParams) ([]id.Round, e2e.MessageID, time.Time, error) { rounds := []id.Round{id.Round(0), id.Round(1), id.Round(2)} - alicePartner, err := r.GetPartner(aliceID, bobID) + alicePartner, err := r.GetPartner(aliceID) if err != nil { print(err) } - bobPartner, err := r.GetPartner(bobID, aliceID) + bobPartner, err := r.GetPartner(bobID) if err != nil { print(err) } diff --git a/e2e/sendE2E.go b/e2e/sendE2E.go index 7f6547555fb76b6245be9fffd8a9c11ed758aae5..1a3c8b8850f98568d00316278b8e4e7b08de0d62 100644 --- a/e2e/sendE2E.go +++ b/e2e/sendE2E.go @@ -1,6 +1,9 @@ package e2e import ( + "sync" + "time" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" @@ -13,25 +16,22 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "sync" - "time" ) func (m *manager) SendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) { + payload []byte, params Params) ([]id.Round, e2e.MessageID, + time.Time, error) { - //check if the network is healthy if !m.net.IsHealthy() { return nil, e2e.MessageID{}, time.Time{}, errors.New("cannot " + "sendE2E when network is not healthy") } - //handle critical messages handleCritical := params.CMIX.Critical if handleCritical { m.crit.AddProcessing(mt, recipient, payload, params) - // set critical to false so the network layer doesnt make the messages - // critical as well + // set critical to false so the network layer doesnt + // make the messages critical as well params.CMIX.Critical = false } @@ -45,39 +45,39 @@ func (m *manager) SendE2E(mt catalog.MessageType, recipient *id.ID, } func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, - payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) { - //timestamp the message + payload []byte, params Params) ([]id.Round, e2e.MessageID, + time.Time, error) { ts := netTime.Now() - //partition the message - partitions, internalMsgId, err := m.partitioner.Partition(recipient, mt, ts, - payload) + partitions, internalMsgId, err := m.partitioner.Partition(recipient, + mt, ts, payload) if err != nil { - return nil, e2e.MessageID{}, time.Time{}, errors.WithMessage(err, "failed to send unsafe message") + err = errors.WithMessage(err, "failed to send unsafe message") + return nil, e2e.MessageID{}, time.Time{}, err } jww.INFO.Printf("E2E sending %d messages to %s", len(partitions), recipient) - //encrypt then send the partitions over cmix + // When sending E2E messages, we first partition into cMix packets and + // then send each partition over cMix. roundIds := make([]id.Round, len(partitions)) errCh := make(chan error, len(partitions)) - // get the key manager for the partner - partner, err := m.Ratchet.GetPartner(recipient, m.myDefaultID) + // The Key manager for the partner (recipient) ensures single + // use of each key negotiated for the ratchet. + partner, err := m.Ratchet.GetPartner(recipient) if err != nil { - return nil, e2e.MessageID{}, time.Time{}, errors.WithMessagef(err, - "Could not send End to End encrypted "+ - "message, no relationship found with %s", recipient) + err = errors.WithMessagef(err, "cannot send E2E message "+ + "no relationship found with %s", recipient) + return nil, e2e.MessageID{}, time.Time{}, err } - //Generate the message ID msgID := e2e.NewMessageID(partner.GetSendRelationshipFingerprint(), internalMsgId) wg := sync.WaitGroup{} - //handle sending for each partition for i, p := range partitions { if mt != catalog.KeyExchangeTrigger { // check if any rekeys need to happen and trigger them @@ -92,7 +92,6 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, m.events, partner, m.rekeyParams, 1*time.Minute) } - //get a key to end to end encrypt var keyGetter func() (*session.Cypher, error) if params.Rekey { keyGetter = partner.PopRekeyCypher @@ -100,23 +99,26 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, keyGetter = partner.PopSendCypher } - //fixme: remove this wait, it is weird. Why is it here? we cant remember. + // FIXME: remove this wait, it is weird. Why is it + // here? we cant remember. key, err := waitForKey(keyGetter, params.KeyGetRetryCount, params.KeyGeRetryDelay, params.CMIX.Stop, recipient, format.DigestContents(p), i) if err != nil { - return nil, e2e.MessageID{}, time.Time{}, errors.WithMessagef(err, + err = errors.WithMessagef(err, "Failed to get key for end to end encryption") + return nil, e2e.MessageID{}, time.Time{}, err } - //end to end encrypt the cmix message + // This does not encrypt for cMix but + // instead end to end encrypts the cmix message contentsEnc, mac := key.Encrypt(p) - jww.INFO.Printf("E2E sending %d/%d to %s with key fp: %s, msgID: %s (msgDigest %s)", + jww.INFO.Printf("E2E sending %d/%d to %s with key fp: "+ + "%s, msgID: %s (msgDigest %s)", i+i, len(partitions), recipient, key.Fingerprint(), msgID, format.DigestContents(p)) - //set up the service tags var s message.Service if i == len(partitions)-1 { s = partner.MakeService(params.LastServiceTag) @@ -124,12 +126,14 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, s = partner.MakeService(params.ServiceTag) } - //send the cmix message, each partition in its own thread + // We send each partition in it's own thread here, some + // may send in round X, others in X+1 or X+2, and so on. wg.Add(1) go func(i int) { var err error - roundIds[i], _, err = m.net.SendCMIX(recipient, key.Fingerprint(), - s, contentsEnc, mac, params.CMIX) + roundIds[i], _, err = m.net.Send(recipient, + key.Fingerprint(), s, contentsEnc, mac, + params.CMIX) if err != nil { errCh <- err } @@ -139,25 +143,25 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, wg.Wait() - //see if any parts failed to send numFail, errRtn := getSendErrors(errCh) if numFail > 0 { jww.INFO.Printf("Failed to E2E send %d/%d to %s", numFail, len(partitions), recipient) - return nil, e2e.MessageID{}, time.Time{}, errors.Errorf("Failed to E2E send %v/%v sub payloads:"+ + err = errors.Errorf("Failed to E2E send %v/%v sub payloads:"+ " %s", numFail, len(partitions), errRtn) + return nil, e2e.MessageID{}, time.Time{}, err } else { jww.INFO.Printf("Successfully E2E sent %d/%d to %s", len(partitions)-numFail, len(partitions), recipient) } - //return the rounds if everything send successfully - jww.INFO.Printf("Successful E2E Send of %d messages to %s with msgID %s", - len(partitions), recipient, msgID) + jww.INFO.Printf("Successful E2E Send of %d messages to %s with msgID "+ + "%s", len(partitions), recipient, msgID) return roundIds, msgID, ts, nil } -// waitForKey waits the designated amount of time for a +// waitForKey waits the designated amount of time for a key to become available +// with the partner. func waitForKey(keyGetter func() (*session.Cypher, error), numAttempts uint, wait time.Duration, stop *stoppable.Single, recipient *id.ID, digest string, partition int) (*session.Cypher, error) { @@ -169,7 +173,8 @@ func waitForKey(keyGetter func() (*session.Cypher, error), numAttempts uint, ticker := time.NewTicker(wait) defer ticker.Stop() - for keyTries := uint(1); err != nil && keyTries < numAttempts; keyTries++ { + for keyTries := uint(1); err != nil && + keyTries < numAttempts; keyTries++ { jww.WARN.Printf("Out of sending keys for %s "+ "(digest: %s, partition: %d), this can "+ "happen when sending messages faster than "+ diff --git a/e2e/sendUnsafe.go b/e2e/sendUnsafe.go index d9b13d697c6713e7fcc9e33c14b89d4fd1be5283..db59de2d697778f1bfb277ea21f60c4aed9b8731 100644 --- a/e2e/sendUnsafe.go +++ b/e2e/sendUnsafe.go @@ -1,6 +1,9 @@ package e2e import ( + "sync" + "time" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" @@ -9,14 +12,11 @@ import ( "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "sync" - "time" ) func (m *manager) SendUnsafe(mt catalog.MessageType, recipient *id.ID, payload []byte, params Params) ([]id.Round, time.Time, error) { - //check if the network is healthy if !m.net.IsHealthy() { return nil, time.Time{}, errors.New("cannot " + "sendE2E when network is not healthy") @@ -27,30 +27,26 @@ func (m *manager) SendUnsafe(mt catalog.MessageType, recipient *id.ID, func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID, payload []byte, params Params) ([]id.Round, time.Time, error) { - //timestamp the message ts := netTime.Now() - //partition the message partitions, _, err := m.partitioner.Partition(recipient, mt, ts, payload) if err != nil { - return nil, time.Time{}, errors.WithMessage(err, "failed to send unsafe message") + err = errors.WithMessage(err, "failed to send unsafe message") + return nil, time.Time{}, err } jww.WARN.Printf("unsafe sending %d messages to %s. Unsafe sends "+ "are unencrypted, only use for debugging", len(partitions), recipient) - //encrypt then send the partitions over cmix roundIds := make([]id.Round, len(partitions)) errCh := make(chan error, len(partitions)) wg := sync.WaitGroup{} - //handle sending for each partition for i, p := range partitions { - //set up the service tags srvc := message.Service{ Identifier: recipient[:], } @@ -60,11 +56,11 @@ func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID, srvc.Tag = ratchet.E2e } - //send the cmix message, each partition in its own thread wg.Add(1) go func(i int, payload []byte) { - unencryptedMAC, fp := e2e.SetUnencrypted(payload, m.myDefaultID) + unencryptedMAC, fp := e2e.SetUnencrypted(payload, + m.myID) var err error roundIds[i], _, err = m.net.Send(recipient, fp, @@ -83,8 +79,9 @@ func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID, if numFail > 0 { jww.INFO.Printf("Failed to unsafe send %d/%d to %s", numFail, len(partitions), recipient) - return nil, time.Time{}, errors.Errorf("Failed to unsafe send %v/%v sub payloads:"+ + err = errors.Errorf("Failed to unsafe send %v/%v sub payloads:"+ " %s", numFail, len(partitions), errRtn) + return nil, time.Time{}, err } else { jww.INFO.Printf("Successfully Unsafe Send %d/%d to %s", len(partitions)-numFail, len(partitions), recipient) diff --git a/e2e/unsafeProcessor.go b/e2e/unsafeProcessor.go index 64218bb2824e3f2af557670575ed8a8f8d337317..d49842fca45d63520c20a0e64a8793b48b1a107b 100644 --- a/e2e/unsafeProcessor.go +++ b/e2e/unsafeProcessor.go @@ -13,7 +13,8 @@ type UnsafeProcessor struct { tag string } -func (up *UnsafeProcessor) Process(ecrMsg format.Message, receptionID receptionID.EphemeralIdentity, +func (up *UnsafeProcessor) Process(ecrMsg format.Message, + receptionID receptionID.EphemeralIdentity, round historical.Round) { //check if the message is unencrypted unencrypted, sender := e2e.IsUnencrypted(ecrMsg) diff --git a/e2e/util.go b/e2e/util.go index 800058c50468ebc379f68790728548770fa42185..dad7da4702ad53ac2ee1a4c4fed55dfd5814b9e7 100644 --- a/e2e/util.go +++ b/e2e/util.go @@ -10,17 +10,19 @@ func (m *manager) GetGroup() *cyclic.Group { return m.grp } -// GetDefaultHistoricalDHPubkey returns the default user's Historical DH Public Key +// GetHistoricalDHPubkey returns the default user's Historical +// DH Public Key func (m *manager) GetHistoricalDHPubkey() *cyclic.Int { return m.Ratchet.GetDHPublicKey() } -// GetDefaultHistoricalDHPrivkey returns the default user's Historical DH Private Key +// GetHistoricalDHPrivkey returns the default user's Historical DH +// Private Key func (m *manager) GetHistoricalDHPrivkey() *cyclic.Int { return m.Ratchet.GetDHPrivateKey() } // GetDefaultID returns the default IDs func (m *manager) GetReceptionID() *id.ID { - return m.myDefaultID + return m.myID }