diff --git a/auth/cmix.go b/auth/cmix.go deleted file mode 100644 index 0f76dd7efc1f757613c0cd43897afb851f4bd93a..0000000000000000000000000000000000000000 --- a/auth/cmix.go +++ /dev/null @@ -1,62 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -// cmix.go cMix functions for the auth module - -package auth - -import ( - "fmt" - - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/elixxir/client/interfaces/preimage" - "gitlab.com/elixxir/primitives/format" - "gitlab.com/xx_network/primitives/id" -) - -// getMixPayloadSize calculates the payload size of a cMix Message based on the -// total message size. -// TODO: Maybe move this to primitives and export it? -// FIXME: This can only vary per cMix network target, and it could be scoped -// to a Client instance. -func getMixPayloadSize(primeSize int) int { - return 2*primeSize - format.AssociatedDataSize - 1 -} - -// sendAuthRequest is a helper to send the cMix Message after the request -// is created. -func sendAuthRequest(recipient *id.ID, contents, mac []byte, primeSize int, - fingerprint format.Fingerprint, net interfaces.NetworkManager, - cMixParams params.CMIX) (id.Round, error) { - cmixMsg := format.NewMessage(primeSize) - cmixMsg.SetKeyFP(fingerprint) - cmixMsg.SetMac(mac) - cmixMsg.SetContents(contents) - - jww.INFO.Printf("Requesting Auth with %s, msgDigest: %s", - recipient, cmixMsg.Digest()) - - cMixParams.IdentityPreimage = preimage.GenerateRequest(recipient) - cMixParams.DebugTag = "auth.Request" - round, _, err := net.SendCMIX(cmixMsg, recipient, cMixParams) - if err != nil { - // if the send fails just set it to failed, it will - // but automatically retried - return 0, errors.WithMessagef(err, "Auth Request with %s "+ - "(msgDigest: %s) failed to transmit: %+v", recipient, - cmixMsg.Digest(), err) - } - - em := fmt.Sprintf("Auth Request with %s (msgDigest: %s) sent"+ - " on round %d", recipient, cmixMsg.Digest(), round) - jww.INFO.Print(em) - net.GetEventManager().Report(1, "Auth", "RequestSent", em) - return round, nil -} diff --git a/auth/manager.go b/auth/manager.go index a2ba826141ccbcf3a25bbae0c1df00afbda42d79..2d817ec301fe4a24f26a41e3b5384ddb43bc3661 100644 --- a/auth/manager.go +++ b/auth/manager.go @@ -8,10 +8,15 @@ package auth import ( + "gitlab.com/elixxir/client/auth/store" + "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" + "gitlab.com/elixxir/client/network" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/switchboard" + "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" ) @@ -21,16 +26,25 @@ type Manager struct { confirmCallbacks *callbackMap resetCallbacks *callbackMap - rawMessages chan message.Receive + net network.Manager + e2e e2e.Handler + rng *fastRNG.StreamGenerator - storage *storage.Session - net interfaces.NetworkManager - rng *fastRNG.StreamGenerator - backupTrigger interfaces.TriggerBackup + store *store.Store + grp *cyclic.Group + event event.Manager + + registeredIDs map[id.ID]keypair replayRequests bool } +type keypair struct { + privkey *cyclic.Int + //generated from pubkey on instantiation + pubkey *cyclic.Int +} + func NewManager(sw interfaces.Switchboard, storage *storage.Session, net interfaces.NetworkManager, rng *fastRNG.StreamGenerator, backupTrigger interfaces.TriggerBackup, replayRequests bool) *Manager { diff --git a/auth/receivedRequest.go b/auth/receivedRequest.go new file mode 100644 index 0000000000000000000000000000000000000000..bb92273031b13c3ef26655e1d7fb21e9d51080a2 --- /dev/null +++ b/auth/receivedRequest.go @@ -0,0 +1,109 @@ +package auth + +import ( + "encoding/base64" + "fmt" + "github.com/cloudflare/circl/dh/sidh" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/network/historical" + "gitlab.com/elixxir/client/network/identity/receptionID" + cAuth "gitlab.com/elixxir/crypto/e2e/auth" + "gitlab.com/elixxir/primitives/fact" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/id" +) + +type receivedRequestService struct { + m *Manager +} + +func (rrs *receivedRequestService) Process(message format.Message, + receptionID receptionID.EphemeralIdentity, round historical.Round) { + + //decode the outer format + baseFmt, partnerPubKey, err := handleBaseFormat( + message, rrs.m.grp) + if err != nil { + jww.WARN.Printf("Failed to handle auth request: %s", err) + return + } + + //lookup the keypair + kp := rrs.m.registeredIDs[*receptionID.Source] + + jww.TRACE.Printf("processing requests: \n\t MYPUBKEY: %s "+ + "\n\t PARTNERPUBKEY: %s \n\t ECRPAYLOAD: %s \n\t MAC: %s", + kp.pubkey.TextVerbose(16, 0), + partnerPubKey.TextVerbose(16, 0), + base64.StdEncoding.EncodeToString(baseFmt.data), + base64.StdEncoding.EncodeToString(message.GetMac())) + + //Attempt to decrypt the payload + success, payload := cAuth.Decrypt(kp.privkey, partnerPubKey, + baseFmt.GetEcrPayload(), message.GetMac(), rrs.m.grp) + + if !success { + jww.WARN.Printf("Received auth request of %s failed its mac "+ + "check", receptionID.Source) + return + } + + //extract data from the decrypted payload + partnerID, partnerSIDHPubKey, facts, err := processDecryptedMessage(payload) + if err != nil { + jww.WARN.Printf("Failed to decode the auth request: %+v", err) + return + } + + em := fmt.Sprintf("Received AuthRequest from %s,"+ + " msgDigest: %s", partnerID, format.DigestContents(message.GetContents())) + jww.INFO.Print(em) + rrs.m.event.Report(1, "Auth", "RequestReceived", em) + + // check the uniqueness of the request. Requests can be duplicated, so we must + // verify this is is not a duplicate, and drop if it is + fp := cAuth.CreateNegotiationFingerprint(partnerPubKey, + partnerSIDHPubKey) + newFP, latest := rrs.m.store.CheckIfNegotiationIsNew(partnerID, + receptionID.Source, fp) + +} + +func processDecryptedMessage(b []byte) (*id.ID, *sidh.PublicKey, fact.FactList, + error) { + //decode the ecr format + ecrFmt, err := unmarshalEcrFormat(b) + if err != nil { + return nil, nil, nil, errors.WithMessage(err, "Failed to "+ + "unmarshal auth request's encrypted payload") + } + + partnerSIDHPubKey, err := ecrFmt.GetSidhPubKey() + if err != nil { + return nil, nil, nil, errors.WithMessage(err, "Could not "+ + "unmarshal partner SIDH Pubkey") + } + + //decode the request format + requestFmt, err := newRequestFormat(ecrFmt) + if err != nil { + return nil, nil, nil, errors.WithMessage(err, "Failed to "+ + "unmarshal auth request's internal payload") + } + + partnerID, err := requestFmt.GetID() + if err != nil { + return nil, nil, nil, errors.WithMessage(err, "Failed to "+ + "unmarshal auth request's sender ID") + } + + facts, _, err := fact.UnstringifyFactList( + string(requestFmt.msgPayload)) + if err != nil { + return nil, nil, nil, errors.WithMessage(err, "Failed to "+ + "unmarshal auth request's facts") + } + + return partnerID, partnerSIDHPubKey, facts, nil +} diff --git a/auth/request.go b/auth/request.go index e3d987e577698225806423ccb1f26a8897711966..daaa3f071e334a08aa3ab8545000f6dcb089a93d 100644 --- a/auth/request.go +++ b/auth/request.go @@ -8,9 +8,14 @@ package auth import ( + "fmt" auth2 "gitlab.com/elixxir/client/auth/store" "gitlab.com/elixxir/client/catalog" e2e2 "gitlab.com/elixxir/client/e2e/ratchet" + "gitlab.com/elixxir/client/network" + "gitlab.com/elixxir/client/network/message" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/crypto/signature/rsa" "io" "strings" @@ -32,156 +37,101 @@ import ( const terminator = ";" -func RequestAuth(partner, me contact.Contact, rng io.Reader, - storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { +func (m *Manager) RequestAuth(partner, me contact.Contact, + originDHPrivKey *cyclic.Int) (id.Round, error) { // check that an authenticated channel does not already exist - if _, err := storage.E2e().GetPartner(partner.ID); err == nil || + if _, err := m.e2e.GetPartner(partner.ID, me.ID); err == nil || !strings.Contains(err.Error(), e2e2.NoPartnerErrorStr) { return 0, errors.Errorf("Authenticated channel already " + "established with partner") } - return requestAuth(partner, me, rng, false, storage, net) -} - -func ResetSession(partner, me contact.Contact, rng io.Reader, - storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { - - // Delete authenticated channel if it exists. - if err := storage.E2e().DeletePartner(partner.ID); err != nil { - jww.WARN.Printf("Unable to delete partner when "+ - "resetting session: %+v", err) - } else { - // Delete any stored sent/received requests - storage.Auth().Delete(partner.ID) - } - - rqType, _, _, err := storage.Auth().GetRequest(partner.ID) - if err == nil && rqType == auth2.Sent { - return 0, errors.New("Cannot reset a session after " + - "sending request, caller must resend request instead") - } - - // Try to initiate a clean session request - return requestAuth(partner, me, rng, true, storage, net) + return m.requestAuth(partner, me, originDHPrivKey) } // requestAuth internal helper -func requestAuth(partner, me contact.Contact, rng io.Reader, reset bool, - storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { - - /*edge checks generation*/ - // check that the request is being sent from the proper ID - if !me.ID.Cmp(storage.GetUser().ReceptionID) { - return 0, errors.Errorf("Authenticated channel request " + - "can only be sent from user's identity") - } - - //denote if this is a resend of an old request - resend := false - - //lookup if an ongoing request is occurring - rqType, sr, _, err := storage.Auth().GetRequest(partner.ID) - if err != nil && !strings.Contains(err.Error(), auth2.NoRequest) { - return 0, errors.WithMessage(err, - "Cannot send a request after receiving unknown error "+ - "on requesting contact status") - } else if err == nil { - switch rqType { - case auth2.Receive: - // TODO: We've already received a request, so send a - // confirmation instead? - return 0, errors.Errorf("Cannot send a request after " + - "receiving a request") - case auth2.Sent: - resend = true - default: - return 0, errors.Errorf("Cannot send a request after "+ - "a stored request with unknown rqType: %d", - rqType) - } - } - - /*cryptographic generation*/ - var dhPriv, dhPub *cyclic.Int - var sidhPriv *sidh.PrivateKey - var sidhPub *sidh.PublicKey - - // NOTE: E2E group is the group used for DH key exchange, not cMix - dhGrp := storage.E2e().GetGroup() - // origin DH Priv key is the DH Key corresponding to the public key - // registered with user discovery - originDHPrivKey := storage.E2e().GetDHPrivateKey() - - // If we are resending (valid sent request), reuse those keys - if resend { - dhPriv = sr.GetMyPrivKey() - dhPub = sr.GetMyPubKey() - sidhPriv = sr.GetMySIDHPrivKey() - sidhPub = sr.GetMySIDHPubKey() - - } else { - dhPriv, dhPub = genDHKeys(dhGrp, rng) - sidhPriv, sidhPub = util.GenerateSIDHKeyPair( - sidh.KeyVariantSidhA, rng) - } - - jww.TRACE.Printf("RequestAuth MYPUBKEY: %v", dhPub.Bytes()) - jww.TRACE.Printf("RequestAuth THEIRPUBKEY: %v", - partner.DhPubKey.Bytes()) +func (m *Manager) requestAuth(partner, me contact.Contact, + originDHPrivKey *cyclic.Int) (id.Round, error) { - cMixPrimeSize := storage.Cmix().GetGroup().GetP().ByteLen() - cMixPayloadSize := getMixPayloadSize(cMixPrimeSize) + //do key generation + rng := m.rng.GetStream() + defer rng.Close() - sender := storage.GetUser().ReceptionID + dhPriv, dhPub := genDHKeys(m.grp, rng) + sidhPriv, sidhPub := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) - //generate ownership proof ownership := cAuth.MakeOwnershipProof(originDHPrivKey, partner.DhPubKey, - dhGrp) + m.grp) confirmFp := cAuth.MakeOwnershipProofFP(ownership) - // cMix fingerprint so the recipient can recognize this is a - // request message. + // Add the sent request and use the return to build the send. This will + // replace the send with an old one if one was in process, wasting the key + // generation above. This is considered a reasonable loss due to the increase + // in code simplicity of this approach + sr, err := m.store.AddSent(partner.ID, me.ID, partner.DhPubKey, dhPriv, dhPub, + sidhPriv, sidhPub, confirmFp) + if err != nil { + if sr == nil { + return 0, err + } else { + jww.INFO.Printf("Resending request to %s from %s because "+ + "one was already sent", partner.ID, me) + } + } + + // cMix fingerprint. Used in old versions by the recipient can recognize + // this is a request message. Unchanged for backwards compatability + // (the SIH is used now) requestfp := cAuth.MakeRequestFingerprint(partner.DhPubKey) // My fact data so we can display in the interface. msgPayload := []byte(me.Facts.Stringify() + terminator) // Create the request packet. - request, mac, err := createRequestAuth(sender, msgPayload, ownership, + request, mac, err := createRequestAuth(partner.ID, msgPayload, ownership, dhPriv, dhPub, partner.DhPubKey, sidhPub, - dhGrp, cMixPayloadSize) + m.grp, m.net.GetMaxMessageLength()) if err != nil { return 0, err } contents := request.Marshal() - storage.GetEdge().Add(edge.Preimage{ - Data: preimage.Generate(confirmFp[:], catalog.Confirm), - Type: catalog.Confirm, - Source: partner.ID[:], - }, me.ID) + //todo-register correct service + m.net.AddService(me.ID, message.Service{ + Identifier: confirmFp[:], + Tag: catalog.Confirm, + Metadata: partner.ID[:], + }, nil) jww.TRACE.Printf("RequestAuth ECRPAYLOAD: %v", request.GetEcrPayload()) jww.TRACE.Printf("RequestAuth MAC: %v", mac) - /*store state*/ - //fixme: channel is bricked if the first store succedes but the second - // fails - //store the in progress auth if this is not a resend. - if !resend { - err = storage.Auth().AddSent(partner.ID, partner.DhPubKey, - dhPriv, dhPub, sidhPriv, sidhPub, confirmFp) - if err != nil { - return 0, errors.Errorf( - "Failed to store auth request: %s", err) - } + jww.INFO.Printf("Requesting Auth with %s, msgDigest: %s", + partner.ID, format.DigestContents(contents)) + + p := network.GetDefaultCMIXParams() + p.DebugTag = "auth.Request" + s := message.Service{ + Identifier: partner.ID.Marshal(), + Tag: catalog.Default, + Metadata: nil, } + round, _, err := m.net.SendCMIX(partner.ID, requestfp, s, contents, mac, p) + if err != nil { + // if the send fails just set it to failed, it will + // but automatically retried + return 0, errors.WithMessagef(err, "Auth Request with %s "+ + "(msgDigest: %s) failed to transmit: %+v", partner.ID, + format.DigestContents(contents), err) + } + + em := fmt.Sprintf("Auth Request with %s (msgDigest: %s) sent"+ + " on round %d", partner.ID, format.DigestContents(contents), round) + jww.INFO.Print(em) + m.event.Report(1, "Auth", "RequestSent", em) + return round, nil - cMixParams := params.GetDefaultCMIX() - rndID, err := sendAuthRequest(partner.ID, contents, mac, cMixPrimeSize, - requestfp, net, cMixParams) - return rndID, err } // genDHKeys is a short helper to generate a Diffie-Helman Keypair diff --git a/auth/reset.go b/auth/reset.go new file mode 100644 index 0000000000000000000000000000000000000000..2a28016164b72f03816cbb6cdeba25686b6a1d8e --- /dev/null +++ b/auth/reset.go @@ -0,0 +1,32 @@ +package auth + +import ( + jww "github.com/spf13/jwalterweatherman" + auth2 "gitlab.com/elixxir/client/auth/store" + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/xx_network/primitives/id" + "io" +) + +func (m *Manager) ResetSession(partner, me contact.Contact, rng io.Reader) (id.Round, error) { + + // Delete authenticated channel if it exists. + if err := storage.E2e().DeletePartner(partner.ID); err != nil { + jww.WARN.Printf("Unable to delete partner when "+ + "resetting session: %+v", err) + } else { + // Delete any stored sent/received requests + storage.Auth().Delete(partner.ID) + } + + rqType, _, _, err := storage.Auth().GetRequest(partner.ID) + if err == nil && rqType == auth2.Sent { + return 0, errors.New("Cannot reset a session after " + + "sending request, caller must resend request instead") + } + + // Try to initiate a clean session request + return requestAuth(partner, me, rng, true, storage, net) +} diff --git a/auth/store/confirmation.go b/auth/store/confirmation.go index 6bd37b62dada4e1e5d3b6ebed7e1aa85700d283b..a321c354c5258f7e0613fd4d4cf67429672b9a88 100644 --- a/auth/store/confirmation.go +++ b/auth/store/confirmation.go @@ -56,6 +56,6 @@ func (s *Store) deleteConfirmation(partner *id.ID, fingerprint []byte) error { // makeConfirmationKey generates the key used to load and store confirmations // for the partner and fingerprint. func makeConfirmationKey(partner *id.ID, fingerprint []byte) string { - return confirmationKeyPrefix + partner.String() + "/" + - base64.StdEncoding.EncodeToString(fingerprint) + return confirmationKeyPrefix + base64.StdEncoding.EncodeToString( + partner.Marshal()) + "/" + base64.StdEncoding.EncodeToString(fingerprint) } diff --git a/auth/store/previousNegotiations.go b/auth/store/previousNegotiations.go index db49a7b25c7e8223299eff7b93d943d6a9dd92fe..80db8cab9fe42d37116af2c4a35311e1484dfc95 100644 --- a/auth/store/previousNegotiations.go +++ b/auth/store/previousNegotiations.go @@ -5,13 +5,6 @@ // LICENSE file // //////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -//////////////////////////////////////////////////////////////////////////////// - package store import ( @@ -34,16 +27,16 @@ const ( currentNegotiationFingerprintsVersion = 0 ) -// AddIfNew adds a new negotiation fingerprint if it is new. +// CheckIfNegotiationIsNew adds a new negotiation fingerprint if it is new. // If the partner does not exist, it will add it and the new fingerprint and -// return newFingerprint = true, latest = true. +// return newFingerprint = true. // If the partner exists and the fingerprint does not exist, add it adds it as // the latest fingerprint and returns newFingerprint = true, latest = true // If the partner exists and the fingerprint exists, return // newFingerprint = false, latest = false or latest = true if it is the last one // in the list. -func (s *Store) AddIfNew(partner, myID *id.ID, negotiationFingerprint []byte) ( - newFingerprint, latest bool) { +func (s *Store) CheckIfNegotiationIsNew(partner, myID *id.ID, negotiationFingerprint []byte) ( + newFingerprint bool, position uint) { s.mux.Lock() defer s.mux.Unlock() @@ -52,10 +45,10 @@ func (s *Store) AddIfNew(partner, myID *id.ID, negotiationFingerprint []byte) ( aid := makeAuthIdentity(partner, myID) _, exists := s.previousNegotiations[aid] if !exists { - s.previousNegotiations[aid] = struct{}{} + s.previousNegotiations[aid] = true // Save fingerprint to storage - err := s.saveNegotiationFingerprints(partner, myID, negotiationFingerprint) + err := saveNegotiationFingerprints(partner, myID, s.kv, negotiationFingerprint) if err != nil { jww.FATAL.Panicf("Failed to save negotiation sentByFingerprints for "+ "partner %s: %+v", partner, err) @@ -75,7 +68,7 @@ func (s *Store) AddIfNew(partner, myID *id.ID, negotiationFingerprint []byte) ( } // get the fingerprint list from storage - fingerprints, err := s.loadNegotiationFingerprints(partner, myID) + fingerprints, err := loadNegotiationFingerprints(partner, myID, s.kv, myID.Cmp(s.defaultID)) if err != nil { jww.FATAL.Panicf("Failed to load negotiation sentByFingerprints for "+ "partner %s: %+v", partner, err) @@ -97,7 +90,7 @@ func (s *Store) AddIfNew(partner, myID *id.ID, negotiationFingerprint []byte) ( // If the partner does exist and the fingerprint does not exist, then add // the fingerprint to the list as latest fingerprints = append(fingerprints, negotiationFingerprint) - err = s.saveNegotiationFingerprints(partner, myID, fingerprints...) + err = saveNegotiationFingerprints(partner, myID, s.kv, fingerprints...) if err != nil { jww.FATAL.Panicf("Failed to save negotiation sentByFingerprints for "+ "partner %s: %+v", partner, err) @@ -109,48 +102,6 @@ func (s *Store) AddIfNew(partner, myID *id.ID, negotiationFingerprint []byte) ( return } -// deletePreviousNegotiationPartner removes the partner, its sentByFingerprints, and -// its confirmations from memory and storage. -func (s *Store) deletePreviousNegotiationPartner(partner, myID *id.ID) error { - - aid := makeAuthIdentity(partner, myID) - - // Do nothing if the partner does not exist - if _, exists := s.previousNegotiations[aid]; !exists { - return nil - } - - // Delete partner from memory - delete(s.previousNegotiations, aid) - - // Delete partner from storage and return an error - err := s.savePreviousNegotiations() - if err != nil { - return err - } - - // Check if sentByFingerprints exist - fingerprints, err := s.loadNegotiationFingerprints(partner, myID) - - // If sentByFingerprints exist for this partner, delete them from storage and any - // accompanying confirmations - if err == nil { - // Delete the fingerprint list from storage but do not return the error - // until after attempting to delete the confirmations - err = s.kv.Delete(makeNegotiationFingerprintsKey(partner, myID), - currentNegotiationFingerprintsVersion) - - // Delete all confirmations from storage - for _, fp := range fingerprints { - // Ignore the error since confirmations rarely exist - _ = s.deleteConfirmation(partner, fp) - } - } - - // Return any error from loading or deleting sentByFingerprints - return err -} - // savePreviousNegotiations saves the list of previousNegotiations partners to // storage. func (s *Store) savePreviousNegotiations() error { @@ -165,7 +116,7 @@ func (s *Store) savePreviousNegotiations() error { // newOrLoadPreviousNegotiations loads the list of previousNegotiations partners // from storage. -func (s *Store) newOrLoadPreviousNegotiations() (map[authIdentity]struct{}, error) { +func (s *Store) newOrLoadPreviousNegotiations() (map[authIdentity]bool, error) { obj, err := s.kv.Get(negotiationPartnersKey, negotiationPartnersVersion) if err != nil { @@ -175,7 +126,7 @@ func (s *Store) newOrLoadPreviousNegotiations() (map[authIdentity]struct{}, erro if err != nil { if strings.Contains(err.Error(), "object not found") || strings.Contains(err.Error(), "no such file or directory") { - return make(map[authIdentity]struct{}), nil + return make(map[authIdentity]bool), nil } else { return nil, err } @@ -190,7 +141,7 @@ func (s *Store) newOrLoadPreviousNegotiations() (map[authIdentity]struct{}, erro } // marshalPreviousNegotiations marshals the list of partners into a byte slice. -func marshalPreviousNegotiations(partners map[authIdentity]struct{}) []byte { +func marshalPreviousNegotiations(partners map[authIdentity]bool) []byte { toMarshal := make([]authIdentity, 0, len(partners)) for aid := range partners { @@ -207,7 +158,7 @@ func marshalPreviousNegotiations(partners map[authIdentity]struct{}) []byte { // unmarshalPreviousNegotiations unmarshalls the marshalled json into a //// list of partner IDs. -func unmarshalPreviousNegotiations(b []byte) (map[authIdentity]struct{}, +func unmarshalPreviousNegotiations(b []byte) (map[authIdentity]bool, error) { unmarshal := make([]authIdentity, 0) @@ -215,10 +166,10 @@ func unmarshalPreviousNegotiations(b []byte) (map[authIdentity]struct{}, return nil, err } - partners := make(map[authIdentity]struct{}) + partners := make(map[authIdentity]bool) for _, aid := range unmarshal { - partners[aid] = struct{}{} + partners[aid] = true } return partners, nil @@ -226,11 +177,11 @@ func unmarshalPreviousNegotiations(b []byte) (map[authIdentity]struct{}, // unmarshalOldPreviousNegotiations unmarshalls the marshalled json into a // list of partner IDs. -func unmarshalOldPreviousNegotiations(buf []byte, defaultID *id.ID) map[authIdentity]struct{} { +func unmarshalOldPreviousNegotiations(buf []byte, defaultID *id.ID) map[authIdentity]bool { buff := bytes.NewBuffer(buf) numberOfPartners := binary.LittleEndian.Uint64(buff.Next(8)) - partners := make(map[authIdentity]struct{}, numberOfPartners) + partners := make(map[authIdentity]bool, numberOfPartners) for i := uint64(0); i < numberOfPartners; i++ { partner, err := id.Unmarshal(buff.Next(id.ArrIDLen)) @@ -239,7 +190,7 @@ func unmarshalOldPreviousNegotiations(buf []byte, defaultID *id.ID) map[authIden "Failed to unmarshal negotiation partner ID: %+v", err) } - partners[makeAuthIdentity(partner, defaultID)] = struct{}{} + partners[makeAuthIdentity(partner, defaultID)] = false } return partners @@ -247,8 +198,8 @@ func unmarshalOldPreviousNegotiations(buf []byte, defaultID *id.ID) map[authIden // saveNegotiationFingerprints saves the list of sentByFingerprints for the given // partner to storage. -func (s *Store) saveNegotiationFingerprints( - partner, myID *id.ID, fingerprints ...[]byte) error { +func saveNegotiationFingerprints( + partner, myID *id.ID, kv *versioned.KV, fingerprints ...[]byte) error { obj := &versioned.Object{ Version: currentNegotiationFingerprintsVersion, @@ -256,23 +207,23 @@ func (s *Store) saveNegotiationFingerprints( Data: marshalNegotiationFingerprints(fingerprints...), } - return s.kv.Set(makeNegotiationFingerprintsKey(partner, myID), + return kv.Set(makeNegotiationFingerprintsKey(partner, myID), currentNegotiationFingerprintsVersion, obj) } // loadNegotiationFingerprints loads the list of sentByFingerprints for the given // partner from storage. -func (s *Store) loadNegotiationFingerprints(partner, myID *id.ID) ([][]byte, error) { - obj, err := s.kv.Get(makeNegotiationFingerprintsKey(partner, myID), +func loadNegotiationFingerprints(partner, myID *id.ID, kv *versioned.KV, possibleOld bool) ([][]byte, error) { + obj, err := kv.Get(makeNegotiationFingerprintsKey(partner, myID), currentNegotiationFingerprintsVersion) if err != nil { - if myID.Cmp(s.defaultID) { - obj, err = s.kv.Get(makeOldNegotiationFingerprintsKey(partner), + if possibleOld { + obj, err = kv.Get(makeOldNegotiationFingerprintsKey(partner), currentNegotiationFingerprintsVersion) if err != nil { return nil, err } - if err = s.kv.Set(makeNegotiationFingerprintsKey(partner, myID), + if err = kv.Set(makeNegotiationFingerprintsKey(partner, myID), currentNegotiationFingerprintsVersion, obj); err != nil { return nil, err } diff --git a/auth/store/previousNegotiations_test.go b/auth/store/previousNegotiations_test.go index b227fb5c501ac1cf8825e4ce2328d5211421ec16..01c04ae40e9bef96567a31b7c5b57899a2b19445 100644 --- a/auth/store/previousNegotiations_test.go +++ b/auth/store/previousNegotiations_test.go @@ -23,7 +23,7 @@ import ( "testing" ) -// Tests the four possible cases of Store.AddIfNew: +// Tests the four possible cases of Store.CheckIfNegotationIsNew: // 1. If the partner does not exist, add partner with the new fingerprint. // Returns newFingerprint = true, latest = true. // 2. If the partner exists and the fingerprint does not, add the fingerprint. @@ -141,7 +141,7 @@ func TestStore_AddIfNew(t *testing.T) { } } - newFingerprint, latest := s.AddIfNew(tt.partner, tt.fp) + newFingerprint, latest := s.CheckIfNegotationIsNew(tt.partner, tt.fp) if newFingerprint != tt.newFingerprint { t.Errorf("Unexpected value for newFingerprint."+ diff --git a/auth/store/receivedRequest.go b/auth/store/receivedRequest.go index 2dd7153d930bd8251f082ad297df9689b7fa938c..701fad374c26a515ec0a17a78954e0072bbdc0f9 100644 --- a/auth/store/receivedRequest.go +++ b/auth/store/receivedRequest.go @@ -128,3 +128,7 @@ func (rr *ReceivedRequest) delete() { func (rr *ReceivedRequest) getType() RequestType { return Receive } + +func (rr *ReceivedRequest) isTemporary() bool { + return rr.kv.IsMemStore() +} diff --git a/auth/store/sentRequest.go b/auth/store/sentRequest.go index 02721bdd251ca1503f71041e420c5c6447ddfa47..674c3b0552af4fe3a102d26c33ae7a43ba456c96 100644 --- a/auth/store/sentRequest.go +++ b/auth/store/sentRequest.go @@ -279,3 +279,7 @@ func (sr *SentRequest) getAuthID() authIdentity { func (sr *SentRequest) getType() RequestType { return Sent } + +func (sr *SentRequest) isTemporary() bool { + return sr.kv.IsMemStore() +} diff --git a/auth/store/sentRequestHandler.go b/auth/store/sentRequestHandler.go index d6d4b77a2df617804ee3ddbf99b2a186025d1e63..1f22c53a2647819d82aa609d3b7b38f2a5be045c 100644 --- a/auth/store/sentRequestHandler.go +++ b/auth/store/sentRequestHandler.go @@ -1,5 +1,6 @@ package store +// SentRequestHandler allows the lower fevel to assign and remove services type SentRequestHandler interface { Add(sr *SentRequest) Delete(sr *SentRequest) diff --git a/auth/store/store.go b/auth/store/store.go index 03438e9705be05c7a62983dbb94bdb0d95d19800..eb4d5a610ecae9f46b66f2cdb03b483d27599eef 100644 --- a/auth/store/store.go +++ b/auth/store/store.go @@ -34,7 +34,7 @@ type Store struct { receivedByID map[authIdentity]*ReceivedRequest sentByID map[authIdentity]*SentRequest - previousNegotiations map[authIdentity]struct{} + previousNegotiations map[authIdentity]bool defaultID *id.ID @@ -52,7 +52,7 @@ func NewStore(kv *versioned.KV, grp *cyclic.Group, srh SentRequestHandler) error grp: grp, receivedByID: make(map[authIdentity]*ReceivedRequest), sentByID: make(map[authIdentity]*SentRequest), - previousNegotiations: make(map[authIdentity]struct{}), + previousNegotiations: make(map[authIdentity]bool), srh: srh, } @@ -75,7 +75,7 @@ func LoadStore(kv *versioned.KV, defaultID *id.ID, grp *cyclic.Group, srh SentRe grp: grp, receivedByID: make(map[authIdentity]*ReceivedRequest), sentByID: make(map[authIdentity]*SentRequest), - previousNegotiations: make(map[authIdentity]struct{}), + previousNegotiations: make(map[authIdentity]bool), defaultID: defaultID, srh: srh, } @@ -151,22 +151,26 @@ func LoadStore(kv *versioned.KV, defaultID *id.ID, grp *cyclic.Group, srh SentRe func (s *Store) save() error { requestIDList := make([]requestDisk, 0, len(s.receivedByID)+len(s.sentByID)) - for _, r := range s.receivedByID { - rDisk := requestDisk{ - T: uint(r.getType()), - ID: r.partner.ID.Marshal(), - MyID: r.myID.Marshal(), + for _, rr := range s.receivedByID { + if !rr.isTemporary() { + rDisk := requestDisk{ + T: uint(rr.getType()), + ID: rr.partner.ID.Marshal(), + MyID: rr.myID.Marshal(), + } + requestIDList = append(requestIDList, rDisk) } - requestIDList = append(requestIDList, rDisk) } - for _, r := range s.sentByID { - rDisk := requestDisk{ - T: uint(r.getType()), - ID: r.partner.Marshal(), - MyID: r.myID.Marshal(), + for _, sr := range s.sentByID { + if !sr.isTemporary() { + rDisk := requestDisk{ + T: uint(sr.getType()), + ID: sr.partner.Marshal(), + MyID: sr.myID.Marshal(), + } + requestIDList = append(requestIDList, rDisk) } - requestIDList = append(requestIDList, rDisk) } data, err := json.Marshal(&requestIDList) @@ -190,13 +194,13 @@ func (s *Store) AddSent(partner, myID *id.ID, partnerHistoricalPubKey, myPrivKey aid := makeAuthIdentity(partner, myID) - if _, ok := s.sentByID[aid]; ok { - return nil, errors.Errorf("Cannot make new sentRequest for partner "+ - "%s, one already exists", partner) + if sentRq, ok := s.sentByID[aid]; ok { + return sentRq, errors.Errorf("Cannot make new sentRequest for partner "+ + "%s, a sent request already exists", partner) } if _, ok := s.receivedByID[aid]; ok { return nil, errors.Errorf("Cannot make new sentRequest for partner "+ - "%s, one already exists", partner) + "%s, a received reqyest already exists", partner) } sr, err := newSentRequest(s.kv, partner, myID, partnerHistoricalPubKey, myPrivKey, @@ -208,6 +212,10 @@ func (s *Store) AddSent(partner, myID *id.ID, partnerHistoricalPubKey, myPrivKey s.sentByID[sr.getAuthID()] = sr s.srh.Add(sr) + if err = s.save(); err != nil { + jww.FATAL.Panicf("Failed to save Sent Request Map after adding "+ + "partner %s to %s", partner, myID) + } return sr, nil } @@ -227,13 +235,12 @@ func (s *Store) AddReceived(myID *id.ID, c contact.Contact, key *sidh.PublicKey) return errors.Errorf("Cannot add contact for partner "+ "%s, one already exists", c.ID) } - r := newReceivedRequest(s.kv, myID, c, key) s.receivedByID[r.aid] = r if err := s.save(); err != nil { jww.FATAL.Panicf("Failed to save Sent Request Map after adding "+ - "partner %s", c.ID) + "partner %s to %s", c.ID, myID) } return nil @@ -346,21 +353,3 @@ func (s *Store) GetReceivedRequest(partner, myID *id.ID) (contact.Contact, error return r.partner, nil } - -// Done is one of two calls after using a request. This one is to be used when -// the use is unsuccessful. It will allow any thread waiting on access to -// continue using the structure. -// It does not return an error because an error is not handleable. -func (s *Store) Done(rr *ReceivedRequest) { - s.mux.RLock() - r, ok := s.receivedByID[rr.aid] - s.mux.RUnlock() - - r.mux.Unlock() - - if !ok { - jww.ERROR.Panicf("Request cannot be finished, not "+ - "found: %s, %s", rr.partner, rr.myID) - return - } -} diff --git a/auth/store/store_test.go b/auth/store/store_test.go index 20f09f27928df8eb620a4832b76cff2a054582b0..43a2dd69fc35c13975bc64ee377814b06887551e 100644 --- a/auth/store/store_test.go +++ b/auth/store/store_test.go @@ -88,7 +88,7 @@ func TestLoadStore(t *testing.T) { t.Fatalf("AddSent() produced an error: %+v", err) } - s.AddIfNew( + s.CheckIfNegotationIsNew( sr.partner, auth.CreateNegotiationFingerprint(privKeys[0], sidhPubKey)) // Attempt to load the store diff --git a/catalog/messageTypes.go b/catalog/messageTypes.go index a5fc5c9b442417b7e6d642267bf3ed70ca53b06c..969e6c703d1f56ab5db32bcbebfed0acf0d74c42 100644 --- a/catalog/messageTypes.go +++ b/catalog/messageTypes.go @@ -16,11 +16,20 @@ const ( /*End to End Rekey message types*/ - // KeyExchangeTrigger - Trigger a rekey, this message is used locally in client only + // KeyExchangeTrigger - Trigger a rekey, this message is used locally in + // client only KeyExchangeTrigger = 30 - // KeyExchangeConfirm - Rekey confirmation message. Sent by partner to confirm completion of a rekey + // KeyExchangeConfirm - Rekey confirmation message. Sent by partner to + //confirm completion of a rekey KeyExchangeConfirm = 31 + // KeyExchangeTriggerEphemeral - Trigger a rekey, this message is used + //locally in client only. For ephemeral only e2e instances. + KeyExchangeTriggerEphemeral = 32 + // KeyExchangeConfirmEphemeral - Rekey confirmation message. Sent by partner + // to confirm completion of a rekey. For ephemeral only e2e instances. + KeyExchangeConfirmEphemeral = 33 + /* Group chat message types */ // GroupCreationRequest - A group chat request message sent to all members in a group. diff --git a/e2e/interface.go b/e2e/interface.go index c2d00e3e24b9da5eb253f02198b1c5ff21ca7414..96496eda48a4e13722df818ff2599ddd66e38541 100644 --- a/e2e/interface.go +++ b/e2e/interface.go @@ -101,7 +101,7 @@ type Handler interface { AddPartner(myID *id.ID, partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, - receiveParams session.Params, temporary bool) (*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 @@ -149,4 +149,18 @@ type Handler interface { // EnableUnsafeReception enables the reception of unsafe message by // registering bespoke services for reception. For debugging only! EnableUnsafeReception() + + /* === Utility ========================================================== */ + + // GetGroup returns the cyclic group used for end to end encruption + GetGroup() *cyclic.Group + + // GetDefaultHistoricalDHPubkey returns the default user's Historical DH Public Key + GetDefaultHistoricalDHPubkey() *cyclic.Int + + // GetDefaultHistoricalDHPrivkey returns the default user's Historical DH Private Key + GetDefaultHistoricalDHPrivkey() *cyclic.Int + + // GetDefaultID returns the default IDs + GetDefaultID() *id.ID } diff --git a/e2e/manager.go b/e2e/manager.go index 1a35f15746b91088579b90936eec88c65cbc6d14..0dd00ab243d25e5e83a561d4ca53e7d23eb29b55 100644 --- a/e2e/manager.go +++ b/e2e/manager.go @@ -1,6 +1,8 @@ package e2e import ( + "encoding/json" + "github.com/pkg/errors" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/e2e/parse" "gitlab.com/elixxir/client/e2e/ratchet" @@ -28,12 +30,29 @@ type manager struct { events event.Manager grp *cyclic.Group crit *critical + rekeyParams rekey.Params } +const e2eRekeyParamsKey = "e2eRekeyParams" +const e2eRekeyParamsVer = 0 + // Init Creates stores. After calling, use load // Passes a default ID and public key which is used for relationship with // partners when no default ID is selected -func Init(kv *versioned.KV, myDefaultID *id.ID, privKey *cyclic.Int, grp *cyclic.Group) error { +func Init(kv *versioned.KV, myDefaultID *id.ID, privKey *cyclic.Int, + grp *cyclic.Group, rekeyParams rekey.Params) error { + rekeyParamsData, err := json.Marshal(rekeyParams) + if err != nil { + return errors.WithMessage(err, "Failed to marshal rekeyParams") + } + err = kv.Set(e2eRekeyParamsKey, e2eRekeyParamsVer, &versioned.Object{ + Version: e2eRekeyParamsVer, + Timestamp: time.Now(), + Data: rekeyParamsData, + }) + if err != nil { + return errors.WithMessage(err, "Failed to save rekeyParams") + } return ratchet.New(kv, myDefaultID, privKey, grp) } @@ -51,6 +70,7 @@ func Load(kv *versioned.KV, net network.Manager, myDefaultID *id.ID, myDefaultID: myDefaultID, events: events, grp: grp, + rekeyParams: rekey.Params{}, } var err error @@ -61,6 +81,16 @@ func Load(kv *versioned.KV, net network.Manager, myDefaultID *id.ID, 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") + } + err = json.Unmarshal(rekeyParams.Data, &m.rekeyParams) + if err != nil { + return nil, errors.WithMessage(err, "Failed to unmarshal rekeyParams data") + } + //attach critical messages m.crit = newCritical(kv, net.AddHealthCallback, net.GetInstance().GetRoundEvents(), m.SendE2E) diff --git a/e2e/ratchet/ratchet.go b/e2e/ratchet/ratchet.go index 0c1bb6591fe5e2c69f7b2c90f46152052f103a96..695af6272ee25811d9e97f92877aef423ed93cc8 100644 --- a/e2e/ratchet/ratchet.go +++ b/e2e/ratchet/ratchet.go @@ -48,8 +48,7 @@ type Ratchet struct { sInteface Services servicesmux sync.RWMutex - kv *versioned.KV - memKv *versioned.KV + kv *versioned.KV } // New creates a new store for the passed user id and private key. @@ -98,7 +97,7 @@ func New(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, func (r *Ratchet) AddPartner(myID *id.ID, partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, - receiveParams session.Params, temporary bool) (*partner.Manager, error) { + receiveParams session.Params) (*partner.Manager, error) { r.mux.Lock() defer r.mux.Unlock() @@ -117,14 +116,7 @@ func (r *Ratchet) AddPartner(myID *id.ID, partnerID *id.ID, if _, ok := r.managers[mid]; ok { return nil, errors.New("Cannot overwrite existing partner") } - - //pass a memory kv if it is supposed to be temporary - kv := r.kv - if temporary { - kv = r.memKv - } - - m := partner.NewManager(kv, r.defaultID, partnerID, myPrivKey, partnerPubKey, + m := partner.NewManager(r.kv, r.defaultID, partnerID, myPrivKey, partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, sendParams, receiveParams, r.cyHandler, r.grp, r.rng) diff --git a/e2e/ratchet/storage.go b/e2e/ratchet/storage.go index 0afc09c2a4a557d7fd39dd02f666a959567cc485..1b53cb99ea1f51b1bb106a8bb62d74ca11bc41eb 100644 --- a/e2e/ratchet/storage.go +++ b/e2e/ratchet/storage.go @@ -11,7 +11,6 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" - "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" ) @@ -33,8 +32,7 @@ func Load(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, defaultID: myID, - kv: kv, - memKv: versioned.NewKV(make(ekv.Memstore)), + kv: kv, cyHandler: cyHandler, grp: grp, @@ -97,11 +95,9 @@ func (r *Ratchet) marshal() ([]byte, error) { contacts := make([]partner.ManagerIdentity, len(r.managers)) index := 0 - for rid, m := range r.managers { - if !m.IsTemporary() { - contacts[index] = rid - index++ - } + for rid, _ := range r.managers { + contacts[index] = rid + index++ } return json.Marshal(&contacts) diff --git a/e2e/rekey/confirm_test.go b/e2e/rekey/confirm_test.go index 8da1485ab2447e9d1feee0c2db0d1039049fbe62..3cfbfb57d27355d59d5f82b7dc59a8d0920c89c3 100644 --- a/e2e/rekey/confirm_test.go +++ b/e2e/rekey/confirm_test.go @@ -69,7 +69,7 @@ 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, false) + _, err = r.AddPartner(myID, bobID, bobPubKey, alicePrivKey, bobSIDHPubKey, aliceSIDHPrivKey, sendParams, receiveParams) if err != nil { t.Errorf("Failed to add partner to ratchet: %+v", err) } diff --git a/e2e/rekey/exchange.go b/e2e/rekey/exchange.go index c5e111e5c8cc9f500aea1ef7f1a2b6544919f5b3..2bfd86e89bea4ea607fd2394b8b8e6d8dd91ee36 100644 --- a/e2e/rekey/exchange.go +++ b/e2e/rekey/exchange.go @@ -19,10 +19,6 @@ import ( "time" ) -const keyExchangeTriggerName = "KeyExchangeTrigger" -const keyExchangeConfirmName = "KeyExchangeConfirm" -const keyExchangeMulti = "KeyExchange" - type E2eSender func(mt catalog.MessageType, recipient *id.ID, payload []byte, cmixParams network.CMIXParams) ( []id.Round, e2e.MessageID, time.Time, error) @@ -32,11 +28,11 @@ func Start(switchboard *receive.Switchboard, ratchet *ratchet.Ratchet, // register the rekey trigger thread triggerCh := make(chan receive.Message, 100) - triggerID := switchboard.RegisterChannel(keyExchangeTriggerName, - &id.ID{}, catalog.KeyExchangeTrigger, triggerCh) + triggerID := switchboard.RegisterChannel(params.TriggerName, + &id.ID{}, params.Trigger, triggerCh) // create the trigger stoppable - triggerStop := stoppable.NewSingle(keyExchangeTriggerName) + triggerStop := stoppable.NewSingle(params.TriggerName) cleanupTrigger := func() { switchboard.Unregister(triggerID) @@ -48,11 +44,11 @@ func Start(switchboard *receive.Switchboard, ratchet *ratchet.Ratchet, //register the rekey confirm thread confirmCh := make(chan receive.Message, 100) - confirmID := switchboard.RegisterChannel(keyExchangeConfirmName, - &id.ID{}, catalog.KeyExchangeConfirm, confirmCh) + confirmID := switchboard.RegisterChannel(params.ConfirmName, + &id.ID{}, params.Confirm, confirmCh) // register the confirm stoppable - confirmStop := stoppable.NewSingle(keyExchangeConfirmName) + confirmStop := stoppable.NewSingle(params.ConfirmName) cleanupConfirm := func() { switchboard.Unregister(confirmID) } @@ -61,7 +57,7 @@ func Start(switchboard *receive.Switchboard, ratchet *ratchet.Ratchet, go startConfirm(ratchet, confirmCh, confirmStop, cleanupConfirm) //bundle the stoppables and return - exchangeStop := stoppable.NewMulti(keyExchangeMulti) + exchangeStop := stoppable.NewMulti(params.StoppableName) exchangeStop.Add(triggerStop) exchangeStop.Add(confirmStop) return exchangeStop, nil diff --git a/e2e/rekey/params.go b/e2e/rekey/params.go index 3579c44716ec967b1f29ceb9960ea1e4291b9aeb..0611e67e84b4875bae35f29855fbddc0e007fe83 100644 --- a/e2e/rekey/params.go +++ b/e2e/rekey/params.go @@ -1,13 +1,44 @@ package rekey -import "time" +import ( + "gitlab.com/elixxir/client/catalog" + "time" +) + +const keyExchangeTriggerName = "KeyExchangeTrigger" +const keyExchangeConfirmName = "KeyExchangeConfirm" +const keyExchangeMulti = "KeyExchange" + +const keyExchangeTriggerEphemeralName = "KeyExchangeTriggerEphemeral" +const keyExchangeConfirmEphemeralName = "KeyExchangeConfirmEphemeral" +const keyExchangeEphemeralMulti = "KeyExchangeEphemeral" type Params struct { - RoundTimeout time.Duration + RoundTimeout time.Duration + TriggerName string + Trigger catalog.MessageType + ConfirmName string + Confirm catalog.MessageType + StoppableName string } func GetDefaultParams() Params { return Params{ - RoundTimeout: time.Minute, + RoundTimeout: time.Minute, + TriggerName: keyExchangeTriggerName, + Trigger: catalog.KeyExchangeTrigger, + ConfirmName: keyExchangeConfirmName, + Confirm: catalog.KeyExchangeConfirm, + StoppableName: keyExchangeMulti, } } + +func GetDefaultEphemeralParams() Params { + p := GetDefaultParams() + p.TriggerName = keyExchangeTriggerEphemeralName + p.Trigger = catalog.KeyExchangeTriggerEphemeral + p.ConfirmName = keyExchangeConfirmEphemeralName + p.Confirm = catalog.KeyExchangeConfirmEphemeral + p.StoppableName = keyExchangeEphemeralMulti + return p +} diff --git a/e2e/rekey/rekey.go b/e2e/rekey/rekey.go index b25764b6100a0e865053fc75fef6c30ec84cf395..3b314153b366a29000e597135a21b99281c37d3d 100644 --- a/e2e/rekey/rekey.go +++ b/e2e/rekey/rekey.go @@ -12,7 +12,6 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/e2e/ratchet/partner" session "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/event" @@ -28,7 +27,7 @@ import ( func CheckKeyExchanges(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSender, events event.Manager, manager *partner.Manager, - sendTimeout time.Duration) { + param Params, sendTimeout time.Duration) { //get all sessions that may need a key exchange sessions := manager.TriggerNegotiations() @@ -36,7 +35,7 @@ func CheckKeyExchanges(instance *commsNetwork.Instance, grp *cyclic.Group, //start an exchange for every session that needs one for _, sess := range sessions { go trigger(instance, grp, sendE2E, events, manager, sess, - sendTimeout) + sendTimeout, param) } } @@ -46,7 +45,7 @@ func CheckKeyExchanges(instance *commsNetwork.Instance, grp *cyclic.Group, // 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, - sendTimeout time.Duration) { + sendTimeout time.Duration, params Params) { var negotiatingSession *session.Session jww.INFO.Printf("[REKEY] Negotiation triggered for session %s with "+ @@ -81,7 +80,7 @@ func trigger(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSend } // send the rekey notification to the partner - err := negotiate(instance, grp, sendE2E, negotiatingSession, + err := negotiate(instance, grp, sendE2E, params, negotiatingSession, sendTimeout) // if sending the negotiation fails, revert the state of the session to @@ -94,7 +93,7 @@ func trigger(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSend } func negotiate(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSender, - sess *session.Session, sendTimeout time.Duration) error { + param Params, sess *session.Session, sendTimeout time.Duration) error { //generate public key pubKey := diffieHellman.GeneratePublicKey(sess.GetMyPrivKey(), grp) @@ -123,7 +122,7 @@ func negotiate(instance *commsNetwork.Instance, grp *cyclic.Group, sendE2E E2eSe params := network.GetDefaultCMIXParams() params.DebugTag = "kx.Request" - rounds, msgID, _, err := sendE2E(catalog.KeyExchangeTrigger, sess.GetPartner(), + rounds, msgID, _, err := sendE2E(param.Trigger, sess.GetPartner(), payload, params) // If the send fails, returns the error so it can be handled. The caller // should ensure the calling session is in a state where the Rekey will diff --git a/e2e/rekey/trigger.go b/e2e/rekey/trigger.go index 8d37e0e2f8f4f7b2764a91b4b1e0c0adf46ff7ce..4eb03ca19dbd15ee79fb2ac2c1c78c63f12a254b 100644 --- a/e2e/rekey/trigger.go +++ b/e2e/rekey/trigger.go @@ -13,7 +13,6 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/e2e/ratchet" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/e2e/receive" @@ -120,7 +119,7 @@ func handleTrigger(ratchet *ratchet.Ratchet, sender E2eSender, params := network.GetDefaultCMIXParams() params.Critical = true //ignore results, the passed sender interface makes it a critical message - _, _, _, _ = sender(catalog.KeyExchangeConfirm, request.Sender, payload, + _, _, _, _ = sender(param.Confirm, request.Sender, payload, params) return nil diff --git a/e2e/sendE2E.go b/e2e/sendE2E.go index 144dd3c8c86b01a641596af034e91f1ac8e5b2b8..287c69f5766a6aa5e751dd09d65e61ba8583262d 100644 --- a/e2e/sendE2E.go +++ b/e2e/sendE2E.go @@ -89,7 +89,7 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, return m.SendE2E(mt, recipient, payload, par) } rekey.CheckKeyExchanges(m.net.GetInstance(), m.grp, rekeySendFunc, - m.events, partner, 1*time.Minute) + m.events, partner, m.rekeyParams, 1*time.Minute) } //get a key to end to end encrypt diff --git a/e2e/util.go b/e2e/util.go new file mode 100644 index 0000000000000000000000000000000000000000..8acd9cac3415a76f21fa4e7ca41f4dc9f10d06ed --- /dev/null +++ b/e2e/util.go @@ -0,0 +1,26 @@ +package e2e + +import ( + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/xx_network/primitives/id" +) + +// GetGroup returns the cyclic group used for end to end encruption +func (m *manager) GetGroup() *cyclic.Group { + return m.grp +} + +// GetDefaultHistoricalDHPubkey returns the default user's Historical DH Public Key +func (m *manager) GetDefaultHistoricalDHPubkey() *cyclic.Int { + return m.Ratchet.GetDHPublicKey() +} + +// GetDefaultHistoricalDHPrivkey returns the default user's Historical DH Private Key +func (m *manager) GetDefaultHistoricalDHPrivkey() *cyclic.Int { + return m.Ratchet.GetDHPrivateKey() +} + +// GetDefaultID returns the default IDs +func (m *manager) GetDefaultID() *id.ID { + return m.myDefaultID +}