diff --git a/auth/request.go b/auth/request.go index 75459786839b8fd6730b9bc58bb44cca67cbb7c5..91cda7a3f324bf7f14ae6b8052e3caccf725767c 100644 --- a/auth/request.go +++ b/auth/request.go @@ -8,6 +8,7 @@ package auth import ( + e2e2 "gitlab.com/elixxir/client/e2e/ratchet" "io" "strings" @@ -19,7 +20,6 @@ import ( "gitlab.com/elixxir/client/interfaces/preimage" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/auth" - "gitlab.com/elixxir/client/storage/e2e" "gitlab.com/elixxir/client/storage/edge" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/crypto/contact" @@ -35,7 +35,7 @@ func RequestAuth(partner, me contact.Contact, rng io.Reader, storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { // check that an authenticated channel does not already exist if _, err := storage.E2e().GetPartner(partner.ID); err == nil || - !strings.Contains(err.Error(), e2e.NoPartnerErrorStr) { + !strings.Contains(err.Error(), e2e2.NoPartnerErrorStr) { return 0, errors.Errorf("Authenticated channel already " + "established with partner") } diff --git a/e2e/interface.go b/e2e/interface.go new file mode 100644 index 0000000000000000000000000000000000000000..2ccf9f6076e0e81d5c5c2563c57bb34dbbba5065 --- /dev/null +++ b/e2e/interface.go @@ -0,0 +1,28 @@ +package e2e + +import ( + "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/interfaces/message" + message2 "gitlab.com/elixxir/client/network/message" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/e2e" + "gitlab.com/xx_network/primitives/id" + "time" +) + +type Handler interface { + SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) + SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error) + AddPartner(partnerID *id.ID, partnerPubKey, + myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, + sendParams, receiveParams params.E2ESessionParams) + GetPartner(partnerID *id.ID) (*Manager, error) + DeletePartner(partnerId *id.ID) + GetAllPartnerIDs() []*id.ID + //aproach 2 + AddService(tag string, source []byte, processor message2.Processor) + RemoveService(tag string, source []byte) +} +type Manager interface { +} diff --git a/storage/e2e/context.go b/e2e/ratchet/context.go similarity index 97% rename from storage/e2e/context.go rename to e2e/ratchet/context.go index beb7211ed6f8b1caca614a46bb76a03c76651c84..27279e4fd5c23f92f764cdac7e29bce2b66356ac 100644 --- a/storage/e2e/context.go +++ b/e2e/ratchet/context.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package ratchet import ( "gitlab.com/elixxir/crypto/cyclic" diff --git a/storage/e2e/fingerprintAccess.go b/e2e/ratchet/fingerprintAccess.go similarity index 81% rename from storage/e2e/fingerprintAccess.go rename to e2e/ratchet/fingerprintAccess.go index 82e130ed4da604ffe310f1f81362d08ab1c01130..aefb0fd56b4539de14022b3b45d1ee691d96fad3 100644 --- a/storage/e2e/fingerprintAccess.go +++ b/e2e/ratchet/fingerprintAccess.go @@ -5,11 +5,15 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package ratchet + +import ( + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" +) type fingerprintAccess interface { // Receives a list of fingerprints to add. Overrides on collision. - add([]*Key) + add([]*session2.Cypher) // Receives a list of fingerprints to delete. Ignores any not available Keys - remove([]*Key) + remove([]*session2.Cypher) } diff --git a/storage/e2e/manager.go b/e2e/ratchet/partner/manager.go similarity index 77% rename from storage/e2e/manager.go rename to e2e/ratchet/partner/manager.go index 610c1b75f2e2c273f745e0824ad60325aae1462d..29f30fd12e6313575901f2342a6d570c39ec9930 100644 --- a/storage/e2e/manager.go +++ b/e2e/ratchet/partner/manager.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package partner import ( "bytes" @@ -14,11 +14,14 @@ import ( "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/e2e/ratchet" + "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/preimage" "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" "golang.org/x/crypto/blake2b" ) @@ -28,9 +31,9 @@ const originMyPrivKeyKey = "originMyPrivKey" const originPartnerPubKey = "originPartnerPubKey" type Manager struct { - ctx *context - kv *versioned.KV + kv *versioned.KV + myID *id.ID partner *id.ID originMyPrivKey *cyclic.Int @@ -41,30 +44,33 @@ type Manager struct { receive *relationship send *relationship + + grp *cyclic.Group + cyHandler session.CypherHandler + rng *fastRNG.StreamGenerator } -// newManager creates the relationship and its first Send and Receive sessions. -func newManager(ctx *context, kv *versioned.KV, partnerID *id.ID, myPrivKey, +// NewManager creates the relationship and its first Send and Receive sessions. +func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, partnerPubKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey, sendParams, - receiveParams params.E2ESessionParams) *Manager { + receiveParams session.Params, cyHandler session.CypherHandler, + grp *cyclic.Group, rng *fastRNG.StreamGenerator) *Manager { - kv = kv.Prefix(fmt.Sprintf(managerPrefix, partnerID)) + kv = kv.Prefix(makeManagerPrefix(partnerID)) m := &Manager{ - ctx: ctx, kv: kv, originMyPrivKey: myPrivKey, originPartnerPubKey: partnerPubKey, originMySIDHPrivKey: mySIDHPrivKey, originPartnerSIDHPubKey: partnerSIDHPubKey, + myID: myID, partner: partnerID, + cyHandler: cyHandler, + grp: grp, + rng: rng, } - - if ctx.grp == nil { - panic("group not set") - } - if err := utility.StoreCyclicKey(kv, myPrivKey, originMyPrivKeyKey); err != nil { jww.FATAL.Panicf("Failed to store %s: %+v", originMyPrivKeyKey, err) @@ -75,28 +81,34 @@ func newManager(ctx *context, kv *versioned.KV, partnerID *id.ID, myPrivKey, err) } - m.send = NewRelationship(m, Send, sendParams) - m.receive = NewRelationship(m, Receive, receiveParams) + m.send = NewRelationship(m.kv, session.Send, myID, partnerID, myPrivKey, + partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, sendParams, cyHandler, + grp, rng) + m.receive = NewRelationship(m.kv, session.Receive, myID, partnerID, + myPrivKey, partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, + receiveParams, cyHandler, grp, rng) return m } //loads a relationship and all buffers and sessions from disk -func loadManager(ctx *context, kv *versioned.KV, partnerID *id.ID) (*Manager, error) { +func loadManager(kv *versioned.KV, myID, partnerID *id.ID, + cyHandler session.CypherHandler, grp *cyclic.Group, + rng *fastRNG.StreamGenerator) (*Manager, error) { kv = kv.Prefix(fmt.Sprintf(managerPrefix, partnerID)) m := &Manager{ - ctx: ctx, - partner: partnerID, - kv: kv, - } - - if ctx.grp == nil { - panic("group not set") + kv: kv, + myID: myID, + partner: partnerID, + cyHandler: cyHandler, + grp: grp, + rng: rng, } var err error + m.originMyPrivKey, err = utility.LoadCyclicKey(kv, originMyPrivKeyKey) if err != nil { jww.FATAL.Panicf("Failed to load %s: %+v", originMyPrivKeyKey, @@ -109,14 +121,16 @@ func loadManager(ctx *context, kv *versioned.KV, partnerID *id.ID) (*Manager, er err) } - m.send, err = LoadRelationship(m, Send) + m.send, err = LoadRelationship(m.kv, session.Send, 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 Send session buffer") } - m.receive, err = LoadRelationship(m, Receive) + 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 "+ @@ -151,13 +165,13 @@ func clearManager(m *Manager, kv *versioned.KV) error { // 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, - partnerSIDHPubKey *sidh.PublicKey, e2eParams params.E2ESessionParams, - source *Session) (*Session, bool) { + partnerSIDHPubKey *sidh.PublicKey, e2eParams session.Params, + source *session2.Session) (*session2.Session, bool) { // Check if the session already exists - baseKey := GenerateE2ESessionBaseKey(source.myPrivKey, partnerPubKey, + baseKey := session2.GenerateE2ESessionBaseKey(source.myPrivKey, partnerPubKey, m.ctx.grp, source.mySIDHPrivKey, partnerSIDHPubKey) - sessionID := getSessionIDFromBaseKey(baseKey) + sessionID := session.getSessionIDFromBaseKey(baseKey) if s := m.receive.GetByID(sessionID); s != nil { return s, true @@ -166,7 +180,7 @@ func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int, // Add the session to the buffer session := m.receive.AddSession(source.myPrivKey, partnerPubKey, baseKey, source.mySIDHPrivKey, partnerSIDHPubKey, - source.GetID(), Confirmed, e2eParams) + source.GetID(), session2.Confirmed, e2eParams) return session, false } @@ -176,19 +190,19 @@ func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int, // private key is optional. A private key will be generated if none is passed. func (m *Manager) NewSendSession(myPrivKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, - e2eParams params.E2ESessionParams) *Session { + e2eParams params.E2ESessionParams) *session2.Session { // Find the latest public key from the other party sourceSession := m.receive.getNewestRekeyableSession() // Add the session to the Send session buffer and return return m.send.AddSession(myPrivKey, sourceSession.partnerPubKey, nil, mySIDHPrivKey, sourceSession.partnerSIDHPubKey, - sourceSession.GetID(), Sending, e2eParams) + sourceSession.GetID(), session2.Sending, e2eParams) } // GetKeyForSending gets the correct session to Send with depending on the type // of Send. -func (m *Manager) GetKeyForSending(st params.SendType) (*Key, error) { +func (m *Manager) GetKeyForSending(st params.SendType) (*session2.Cypher, error) { switch st { case params.Standard: return m.send.getKeyForSending() @@ -207,7 +221,7 @@ func (m *Manager) GetPartnerID() *id.ID { // GetSendSession gets the Send session of the passed ID. Returns nil if no // session is found. -func (m *Manager) GetSendSession(sid SessionID) *Session { +func (m *Manager) GetSendSession(sid session2.SessionID) *session2.Session { return m.send.GetByID(sid) } @@ -219,18 +233,18 @@ func (m *Manager) GetSendRelationshipFingerprint() []byte { // GetReceiveSession gets the Receive session of the passed ID. Returns nil if // no session is found. -func (m *Manager) GetReceiveSession(sid SessionID) *Session { +func (m *Manager) GetReceiveSession(sid session2.SessionID) *session2.Session { return m.receive.GetByID(sid) } // Confirm confirms a Send session is known about by the partner. -func (m *Manager) Confirm(sid SessionID) error { +func (m *Manager) Confirm(sid session2.SessionID) error { return m.send.Confirm(sid) } // TriggerNegotiations returns a list of key exchange operations if any are // necessary. -func (m *Manager) TriggerNegotiations() []*Session { +func (m *Manager) TriggerNegotiations() []*session2.Session { return m.send.TriggerNegotiation() } @@ -298,3 +312,7 @@ func (m *Manager) GetFileTransferPreimage() []byte { func (m *Manager) GetGroupRequestPreimage() []byte { return preimage.Generate(m.GetRelationshipFingerprintBytes(), preimage.GroupRq) } + +func makeManagerPrefix(pid *id.ID) string { + return fmt.Sprintf(managerPrefix, pid) +} \ No newline at end of file diff --git a/storage/e2e/manager_test.go b/e2e/ratchet/partner/manager_test.go similarity index 94% rename from storage/e2e/manager_test.go rename to e2e/ratchet/partner/manager_test.go index 24c0f9ab85fbca4bd0e3d0166c8ae6a1ab7382cd..a8863497731756c99ca5fcff9e93d4318acad3df 100644 --- a/storage/e2e/manager_test.go +++ b/e2e/ratchet/partner/manager_test.go @@ -5,12 +5,14 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package partner import ( "bytes" "encoding/base64" "fmt" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" + "gitlab.com/elixxir/client/e2e/ratchet/session" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" @@ -25,7 +27,7 @@ import ( // Tests happy path of newManager. func Test_newManager(t *testing.T) { // Set up expected and test values - s, ctx := makeTestSession() + s, ctx := session.makeTestSession() kv := versioned.NewKV(make(ekv.Memstore)) partnerID := id.NewIdFromUInt(100, id.User, t) expectedM := &Manager{ @@ -37,9 +39,9 @@ func Test_newManager(t *testing.T) { originPartnerSIDHPubKey: s.partnerSIDHPubKey, originMySIDHPrivKey: s.mySIDHPrivKey, } - expectedM.send = NewRelationship(expectedM, Send, + expectedM.send = NewRelationship(expectedM, session2.Send, params.GetDefaultE2ESessionParams()) - expectedM.receive = NewRelationship(expectedM, Receive, + expectedM.receive = NewRelationship(expectedM, session2.Receive, params.GetDefaultE2ESessionParams()) // Create new relationship @@ -101,7 +103,7 @@ func TestManager_ClearManager(t *testing.T) { func TestManager_NewReceiveSession(t *testing.T) { // Set up test values m, _ := newTestManager(t) - s, _ := makeTestSession() + s, _ := session.makeTestSession() se, exists := m.NewReceiveSession(s.partnerPubKey, s.partnerSIDHPubKey, s.e2eParams, s) @@ -136,7 +138,7 @@ func TestManager_NewReceiveSession(t *testing.T) { func TestManager_NewSendSession(t *testing.T) { // Set up test values m, _ := newTestManager(t) - s, _ := makeTestSession() + s, _ := session.makeTestSession() se := m.NewSendSession(s.myPrivKey, s.mySIDHPrivKey, s.e2eParams) if !m.partner.Cmp(se.GetPartner()) { @@ -159,7 +161,7 @@ func TestManager_GetKeyForSending(t *testing.T) { // Set up test values m, _ := newTestManager(t) p := params.GetDefaultE2E() - expectedKey := &Key{ + expectedKey := &session2.Cypher{ session: m.send.sessions[0], } @@ -175,7 +177,7 @@ func TestManager_GetKeyForSending(t *testing.T) { } p.Type = params.KeyExchange - m.send.sessions[0].negotiationStatus = NewSessionTriggered + m.send.sessions[0].negotiationStatus = session2.NewSessionTriggered expectedKey.keyNum++ key, err = m.GetKeyForSending(p.Type) @@ -248,7 +250,7 @@ func TestManager_GetReceiveSession(t *testing.T) { // Tests happy path of Manager.Confirm. func TestManager_Confirm(t *testing.T) { m, _ := newTestManager(t) - m.send.sessions[0].negotiationStatus = Sent + m.send.sessions[0].negotiationStatus = session2.Sent err := m.Confirm(m.send.sessions[0].GetID()) if err != nil { t.Errorf("Confirm produced an error: %v", err) @@ -258,7 +260,7 @@ func TestManager_Confirm(t *testing.T) { // Tests happy path of Manager.TriggerNegotiations. func TestManager_TriggerNegotiations(t *testing.T) { m, _ := newTestManager(t) - m.send.sessions[0].negotiationStatus = Unconfirmed + m.send.sessions[0].negotiationStatus = session2.Unconfirmed sessions := m.TriggerNegotiations() if !reflect.DeepEqual(m.send.sessions, sessions) { t.Errorf("TriggerNegotiations() returned incorrect sessions."+ @@ -269,7 +271,7 @@ func TestManager_TriggerNegotiations(t *testing.T) { // newTestManager returns a new relationship for testing. func newTestManager(t *testing.T) (*Manager, *versioned.KV) { prng := rand.New(rand.NewSource(netTime.Now().UnixNano())) - s, ctx := makeTestSession() + s, ctx := session.makeTestSession() kv := versioned.NewKV(make(ekv.Memstore)) partnerID := id.NewIdFromUInts([4]uint64{prng.Uint64(), prng.Uint64(), prng.Uint64(), prng.Uint64()}, id.User, t) diff --git a/storage/e2e/relationship.go b/e2e/ratchet/partner/relationship.go similarity index 67% rename from storage/e2e/relationship.go rename to e2e/ratchet/partner/relationship.go index c545841761492ba43b854620b0b6724b67ee7c90..571f255d1d5d47dae69430f97d7e0f1f67b21a26 100644 --- a/storage/e2e/relationship.go +++ b/e2e/ratchet/partner/relationship.go @@ -5,16 +5,18 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package partner import ( "encoding/json" "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces/params" + "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "sync" ) @@ -26,29 +28,49 @@ const relationshipKey = "relationship" const relationshipFingerprintKey = "relationshipFingerprint" type relationship struct { - manager *Manager - t RelationshipType + t session.RelationshipType kv *versioned.KV - sessions []*Session - sessionByID map[SessionID]*Session + sessions []*session.Session + sessionByID map[session.SessionID]*session.Session fingerprint []byte mux sync.RWMutex sendMux sync.Mutex + + grp *cyclic.Group + myID *id.ID + partnerID *id.ID + + cyHandler session.CypherHandler + rng *fastRNG.StreamGenerator + + serviceHandler ServiceHandler } -func NewRelationship(manager *Manager, t RelationshipType, - initialParams params.E2ESessionParams) *relationship { +type ServiceHandler interface { + AddService(identifier []byte, tag string, source []byte) + DeleteKey(identifier []byte, tag string) +} - kv := manager.kv.Prefix(t.prefix()) +// fixme - this is weird becasue it creates the relationsip and the session. +// Should be refactored to create an empty relationship, with a second call +// adding the session +func NewRelationship(kv *versioned.KV, t session.RelationshipType, + myID, partnerID *id.ID, myOriginPrivateKey, + partnerOriginPublicKey *cyclic.Int, originMySIDHPrivKey *sidh.PrivateKey, + originPartnerSIDHPubKey *sidh.PublicKey, initialParams session.Params, + cyHandler session.CypherHandler, grp *cyclic.Group, + rng *fastRNG.StreamGenerator) *relationship { + + kv = kv.Prefix(t.Prefix()) //build the fingerprint - fingerprint := makeRelationshipFingerprint(t, manager.ctx.grp, - manager.originMyPrivKey, manager.originPartnerPubKey, manager.ctx.myID, - manager.partner) + fingerprint := makeRelationshipFingerprint(t, grp, + myOriginPrivateKey, partnerOriginPublicKey, myID, + partnerID) if err := storeRelationshipFingerprint(fingerprint, kv); err != nil { jww.FATAL.Panicf("Failed to store relationship fingerpint "+ @@ -56,22 +78,24 @@ func NewRelationship(manager *Manager, t RelationshipType, } r := &relationship{ - manager: manager, t: t, - sessions: make([]*Session, 0), - sessionByID: make(map[SessionID]*Session), + sessions: make([]*session.Session, 0), + sessionByID: make(map[session.SessionID]*session.Session), fingerprint: fingerprint, kv: kv, + grp: grp, + cyHandler: cyHandler, + rng: rng, } // set to confirmed because the first session is always confirmed as a // result of the negotiation before creation - s := newSession(r, r.t, manager.originMyPrivKey, - manager.originPartnerPubKey, nil, manager.originMySIDHPrivKey, - manager.originPartnerSIDHPubKey, SessionID{}, - r.fingerprint, Confirmed, initialParams) + s := session.NewSession(r.kv, r.t, partnerID, myOriginPrivateKey, + partnerOriginPublicKey, nil, originMySIDHPrivKey, + originPartnerSIDHPubKey, session.SessionID{}, + r.fingerprint, session.Confirmed, initialParams, cyHandler, grp, rng) - if err := s.save(); err != nil { + if err := s.Save(); err != nil { jww.FATAL.Panicf("Failed to Send session after setting to "+ "confirmed: %+v", err) } @@ -86,12 +110,43 @@ func NewRelationship(manager *Manager, t RelationshipType, return r } +func LoadRelationship(kv *versioned.KV, t session.RelationshipType, myID, + partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group, + rng *fastRNG.StreamGenerator) (*relationship, error) { + + kv = kv.Prefix(t.Prefix()) + + r := &relationship{ + t: t, + sessionByID: make(map[session.SessionID]*session.Session), + kv: kv, + myID: myID, + partnerID: partnerID, + cyHandler: cyHandler, + grp: grp, + rng: rng, + } + + obj, err := kv.Get(relationshipKey, currentRelationshipVersion) + if err != nil { + return nil, err + } + + err = r.unmarshal(obj.Data) + + if err != nil { + return nil, err + } + + return r, nil +} + // DeleteRelationship removes all relationship and // relationship adjacent information from storage func DeleteRelationship(manager *Manager) error { // Delete the send information - sendKv := manager.kv.Prefix(Send.prefix()) + sendKv := manager.kv.Prefix(session.Send.Prefix()) manager.send.Delete() if err := deleteRelationshipFingerprint(sendKv); err != nil { return err @@ -101,7 +156,7 @@ func DeleteRelationship(manager *Manager) error { } // Delete the receive information - receiveKv := manager.kv.Prefix(Receive.prefix()) + receiveKv := manager.kv.Prefix(session.Receive.Prefix()) manager.receive.Delete() if err := deleteRelationshipFingerprint(receiveKv); err != nil { return err @@ -113,31 +168,6 @@ func DeleteRelationship(manager *Manager) error { return nil } -func LoadRelationship(manager *Manager, t RelationshipType) (*relationship, error) { - - kv := manager.kv.Prefix(t.prefix()) - - r := &relationship{ - t: t, - manager: manager, - sessionByID: make(map[SessionID]*Session), - kv: kv, - } - - obj, err := kv.Get(relationshipKey, currentRelationshipVersion) - if err != nil { - return nil, err - } - - err = r.unmarshal(obj.Data) - - if err != nil { - return nil, err - } - - return r, nil -} - func (r *relationship) save() error { now := netTime.Now() @@ -158,7 +188,7 @@ func (r *relationship) save() error { //ekv functions func (r *relationship) marshal() ([]byte, error) { - sessions := make([]SessionID, len(r.sessions)) + sessions := make([]session.SessionID, len(r.sessions)) index := 0 for sid := range r.sessionByID { @@ -170,11 +200,9 @@ func (r *relationship) marshal() ([]byte, error) { } func (r *relationship) unmarshal(b []byte) error { - var sessions []SessionID + var sessions []session.SessionID - err := json.Unmarshal(b, &sessions) - - if err != nil { + if err := json.Unmarshal(b, &sessions); err != nil { return err } @@ -183,13 +211,13 @@ func (r *relationship) unmarshal(b []byte) error { //load all the sessions for _, sid := range sessions { - sessionKV := r.kv.Prefix(makeSessionPrefix(sid)) - session, err := loadSession(r, sessionKV, r.fingerprint) + s, err := session.LoadSession(r.kv, sid, r.fingerprint, + r.cyHandler, r.grp, r.rng) if err != nil { jww.FATAL.Panicf("Failed to load session %s for %s: %+v", - makeSessionPrefix(sid), r.manager.partner, err) + session.MakeSessionPrefix(sid), r.partnerID, err) } - r.addSession(session) + r.addSession(s) } return nil @@ -202,19 +230,18 @@ func (r *relationship) Delete() { delete(r.sessionByID, s.GetID()) s.Delete() } - } func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey, - trigger SessionID, negotiationStatus Negotiation, - e2eParams params.E2ESessionParams) *Session { + trigger session.SessionID, negotiationStatus session.Negotiation, + e2eParams session.Params) *session.Session { r.mux.Lock() defer r.mux.Unlock() - s := newSession(r, r.t, myPrivKey, partnerPubKey, baseKey, + s := session.NewSession(r.kv, r.t, r.partnerID, myPrivKey, partnerPubKey, baseKey, mySIDHPrivKey, partnerSIDHPubKey, trigger, - r.fingerprint, negotiationStatus, e2eParams) + r.fingerprint, negotiationStatus, e2eParams, r.cyHandler, r.grp, r.rng) r.addSession(s) if err := r.save(); err != nil { @@ -225,13 +252,13 @@ func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int, return s } -func (r *relationship) addSession(s *Session) { - r.sessions = append([]*Session{s}, r.sessions...) +func (r *relationship) addSession(s *session.Session) { + r.sessions = append([]*session.Session{s}, r.sessions...) r.sessionByID[s.GetID()] = s return } -func (r *relationship) GetNewest() *Session { +func (r *relationship) GetNewest() *session.Session { r.mux.RLock() defer r.mux.RUnlock() if len(r.sessions) == 0 { @@ -241,7 +268,7 @@ func (r *relationship) GetNewest() *Session { } // returns the key which is most likely to be successful for sending -func (r *relationship) getKeyForSending() (*Key, error) { +func (r *relationship) getKeyForSending() (*session.Cypher, error) { r.sendMux.Lock() defer r.sendMux.Unlock() s := r.getSessionForSending() @@ -253,12 +280,12 @@ func (r *relationship) getKeyForSending() (*Key, error) { } // returns the session which is most likely to be successful for sending -func (r *relationship) getSessionForSending() *Session { +func (r *relationship) getSessionForSending() *session.Session { sessions := r.sessions - var confirmedRekey []*Session - var unconfirmedActive []*Session - var unconfirmedRekey []*Session + var confirmedRekey []*session.Session + var unconfirmedActive []*session.Session + var unconfirmedRekey []*session.Session jww.TRACE.Printf("[REKEY] Sessions Available: %d", len(sessions)) @@ -267,14 +294,14 @@ func (r *relationship) getSessionForSending() *Session { confirmed := s.IsConfirmed() jww.TRACE.Printf("[REKEY] Session Status/Confirmed: %v, %v", status, confirmed) - if status == Active && confirmed { + if status == session.Active && confirmed { //always return the first confirmed active, happy path return s - } else if status == RekeyNeeded && confirmed { + } else if status == session.RekeyNeeded && confirmed { confirmedRekey = append(confirmedRekey, s) - } else if status == Active && !confirmed { + } else if status == session.Active && !confirmed { unconfirmedActive = append(unconfirmedActive, s) - } else if status == RekeyNeeded && !confirmed { + } else if status == session.RekeyNeeded && !confirmed { unconfirmedRekey = append(unconfirmedRekey, s) } } @@ -303,12 +330,12 @@ func (r *relationship) getSessionForSending() *Session { // returns a list of session that need rekeys. Nil instances mean a new rekey // from scratch -func (r *relationship) TriggerNegotiation() []*Session { +func (r *relationship) TriggerNegotiation() []*session.Session { //dont need to take the lock due to the use of a copy of the buffer sessions := r.getInternalBufferShallowCopy() - var instructions []*Session + var instructions []*session.Session for _, ses := range sessions { - if ses.triggerNegotiation() { + if ses.TriggerNegotiation() { instructions = append(instructions, ses) } } @@ -316,7 +343,7 @@ func (r *relationship) TriggerNegotiation() []*Session { } // returns a key which should be used for rekeying -func (r *relationship) getKeyForRekey() (*Key, error) { +func (r *relationship) getKeyForRekey() (*session.Cypher, error) { r.sendMux.Lock() defer r.sendMux.Unlock() s := r.getNewestRekeyableSession() @@ -328,14 +355,14 @@ func (r *relationship) getKeyForRekey() (*Key, error) { } // returns the newest session which can be used to start a key negotiation -func (r *relationship) getNewestRekeyableSession() *Session { +func (r *relationship) getNewestRekeyableSession() *session.Session { //dont need to take the lock due to the use of a copy of the buffer sessions := r.getInternalBufferShallowCopy() if len(sessions) == 0 { return nil } - var unconfirmed *Session + var unconfirmed *session.Session for _, s := range r.sessions { jww.TRACE.Printf("[REKEY] Looking at session %s", s) @@ -344,7 +371,7 @@ func (r *relationship) getNewestRekeyableSession() *Session { // 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() != RekeyEmpty { + if s.Status() != session.RekeyEmpty { if s.IsConfirmed() { jww.TRACE.Printf("[REKEY] Selected rekey: %s", s) @@ -359,7 +386,7 @@ func (r *relationship) getNewestRekeyableSession() *Session { return unconfirmed } -func (r *relationship) GetByID(id SessionID) *Session { +func (r *relationship) GetByID(id session.SessionID) *session.Session { r.mux.RLock() defer r.mux.RUnlock() return r.sessionByID[id] @@ -368,7 +395,7 @@ func (r *relationship) GetByID(id SessionID) *Session { // sets the passed session ID as confirmed. Call "GetSessionRotation" after // to get any sessions that are to be deleted and then "DeleteSession" to // remove them -func (r *relationship) Confirm(id SessionID) error { +func (r *relationship) Confirm(id session.SessionID) error { r.mux.Lock() defer r.mux.Unlock() @@ -377,7 +404,7 @@ func (r *relationship) Confirm(id SessionID) error { return errors.Errorf("Could not confirm session %s, does not exist", id) } - s.SetNegotiationStatus(Confirmed) + s.SetNegotiationStatus(session.Confirmed) r.clean() @@ -387,7 +414,7 @@ func (r *relationship) Confirm(id SessionID) error { // adding or removing a session is always done via replacing the entire // slice, this allow us to copy the slice under the read lock and do the // rest of the work while not taking the lock -func (r *relationship) getInternalBufferShallowCopy() []*Session { +func (r *relationship) getInternalBufferShallowCopy() []*session.Session { r.mux.RLock() defer r.mux.RUnlock() return r.sessions @@ -397,7 +424,7 @@ func (r *relationship) clean() { numConfirmed := uint(0) - var newSessions []*Session + var newSessions []*session.Session editsMade := false for _, s := range r.sessions { diff --git a/storage/e2e/relationshipFingerprint.go b/e2e/ratchet/partner/relationshipFingerprint.go similarity index 90% rename from storage/e2e/relationshipFingerprint.go rename to e2e/ratchet/partner/relationshipFingerprint.go index 29b80896dfc078b8ab1a7cefa348a7860498aec2..0cceefc61cb8aa6e2e0b6e461689fff8e3b704a4 100644 --- a/storage/e2e/relationshipFingerprint.go +++ b/e2e/ratchet/partner/relationshipFingerprint.go @@ -5,10 +5,11 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package partner import ( jww "github.com/spf13/jwalterweatherman" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/e2e" @@ -16,16 +17,16 @@ import ( "gitlab.com/xx_network/primitives/netTime" ) -func makeRelationshipFingerprint(t RelationshipType, grp *cyclic.Group, +func makeRelationshipFingerprint(t session2.RelationshipType, grp *cyclic.Group, myPrivKey, partnerPubKey *cyclic.Int, me, partner *id.ID) []byte { myPubKey := grp.ExpG(myPrivKey, grp.NewIntFromUInt(1)) switch t { - case Send: + case session2.Send: return e2e.MakeRelationshipFingerprint(myPubKey, partnerPubKey, me, partner) - case Receive: + case session2.Receive: return e2e.MakeRelationshipFingerprint(myPubKey, partnerPubKey, partner, me) default: diff --git a/storage/e2e/relationship_test.go b/e2e/ratchet/partner/relationship_test.go similarity index 77% rename from storage/e2e/relationship_test.go rename to e2e/ratchet/partner/relationship_test.go index bd21292259eae2cce4b1e82401bd4d002032a236..662951ac7374b443aa1a62e4170409353b0171e3 100644 --- a/storage/e2e/relationship_test.go +++ b/e2e/ratchet/partner/relationship_test.go @@ -5,11 +5,14 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package partner import ( "bytes" "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/e2e/ratchet" + session7 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" + session6 "gitlab.com/elixxir/client/e2e/ratchet/session" "gitlab.com/elixxir/client/interfaces/params" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" @@ -23,7 +26,7 @@ import ( // Subtest: unmarshal/marshal with one session in the buff func TestRelationship_MarshalUnmarshal(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) // Serialization should include session slice only serialized, err := sb.marshal() @@ -35,8 +38,8 @@ func TestRelationship_MarshalUnmarshal(t *testing.T) { manager: mgr, t: 0, kv: sb.kv, - sessions: make([]*Session, 0), - sessionByID: make(map[SessionID]*Session), + sessions: make([]*session7.Session, 0), + sessionByID: make(map[session7.SessionID]*session7.Session), } err = sb2.unmarshal(serialized) @@ -53,14 +56,14 @@ func TestRelationship_MarshalUnmarshal(t *testing.T) { // Shows that Relationship returns an equivalent session buff to the one that was saved func TestLoadRelationship(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) err := sb.save() if err != nil { t.Fatal(err) } - sb2, err := LoadRelationship(mgr, Send) + sb2, err := LoadRelationship(mgr, session7.Send) if err != nil { t.Fatal(err) } @@ -75,13 +78,13 @@ func TestDeleteRelationship(t *testing.T) { mgr := makeTestRelationshipManager(t) // Generate send relationship - mgr.send = NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + mgr.send = NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) if err := mgr.send.save(); err != nil { t.Fatal(err) } // Generate receive relationship - mgr.receive = NewRelationship(mgr, Receive, params.GetDefaultE2ESessionParams()) + mgr.receive = NewRelationship(mgr, session7.Receive, params.GetDefaultE2ESessionParams()) if err := mgr.receive.save(); err != nil { t.Fatal(err) } @@ -91,12 +94,12 @@ func TestDeleteRelationship(t *testing.T) { t.Fatalf("DeleteRelationship error: Could not delete manager: %v", err) } - _, err = LoadRelationship(mgr, Send) + _, err = LoadRelationship(mgr, session7.Send) if err == nil { t.Fatalf("DeleteRelationship error: Should not have loaded deleted relationship: %v", err) } - _, err = LoadRelationship(mgr, Receive) + _, err = LoadRelationship(mgr, session7.Receive) if err == nil { t.Fatalf("DeleteRelationship error: Should not have loaded deleted relationship: %v", err) } @@ -112,7 +115,7 @@ func TestRelationship_deleteRelationshipFingerprint(t *testing.T) { }() mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) err := sb.save() if err != nil { @@ -131,7 +134,7 @@ func TestRelationship_deleteRelationshipFingerprint(t *testing.T) { // Shows that Relationship returns a valid session buff func TestNewRelationshipBuff(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) if mgr != sb.manager { t.Error("managers should be identical") } @@ -148,21 +151,21 @@ func TestNewRelationshipBuff(t *testing.T) { // Shows that AddSession adds one session to the relationship func TestRelationship_AddSession(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) if len(sb.sessions) != 1 { t.Error("starting session slice length should be 1") } if len(sb.sessionByID) != 1 { t.Error("starting session map length should be 1") } - session, _ := makeTestSession() + session, _ := session6.makeTestSession() // Note: AddSession doesn't change the session relationship or set anything else up // to match the session to the session buffer. To work properly, the session // should have been created using the same relationship (which is not the case in // this test.) sb.AddSession(session.myPrivKey, session.partnerPubKey, nil, session.mySIDHPrivKey, session.partnerSIDHPubKey, - session.partnerSource, Sending, session.e2eParams) + session.partnerSource, session7.Sending, session.e2eParams) if len(sb.sessions) != 2 { t.Error("ending session slice length should be 2") } @@ -177,7 +180,7 @@ func TestRelationship_AddSession(t *testing.T) { // GetNewest should get the session that was most recently added to the buff func TestRelationship_GetNewest(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) // The newest session should be nil upon session buffer creation nilSession := sb.GetNewest() if nilSession == nil { @@ -185,18 +188,18 @@ func TestRelationship_GetNewest(t *testing.T) { "with one session") } - session, _ := makeTestSession() + session, _ := session6.makeTestSession() sb.AddSession(session.myPrivKey, session.partnerPubKey, nil, session.mySIDHPrivKey, session.partnerSIDHPubKey, - session.partnerSource, Sending, session.e2eParams) + session.partnerSource, session7.Sending, session.e2eParams) if session.GetID() != sb.GetNewest().GetID() { t.Error("session added should have same ID") } - session2, _ := makeTestSession() + session2, _ := session6.makeTestSession() sb.AddSession(session2.myPrivKey, session2.partnerPubKey, nil, session2.mySIDHPrivKey, session2.partnerSIDHPubKey, - session2.partnerSource, Sending, session.e2eParams) + session2.partnerSource, session7.Sending, session.e2eParams) if session2.GetID() != sb.GetNewest().GetID() { t.Error("session added should have same ID") } @@ -206,13 +209,13 @@ func TestRelationship_GetNewest(t *testing.T) { // Shows that Confirm confirms the specified session in the buff func TestRelationship_Confirm(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) - session, _ := makeTestSession() + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) + session, _ := session6.makeTestSession() sb.AddSession(session.myPrivKey, session.partnerPubKey, nil, session.mySIDHPrivKey, session.partnerSIDHPubKey, - session.partnerSource, Sending, session.e2eParams) - sb.sessions[1].negotiationStatus = Sent + session.partnerSource, session7.Sending, session.e2eParams) + sb.sessions[1].negotiationStatus = session7.Sent if sb.sessions[1].IsConfirmed() { t.Error("session should not be confirmed before confirmation") @@ -231,8 +234,8 @@ func TestRelationship_Confirm(t *testing.T) { // Shows that the session buff returns an error when the session doesn't exist func TestRelationship_Confirm_Err(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) - session, _ := makeTestSession() + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) + session, _ := session6.makeTestSession() err := sb.Confirm(session.GetID()) if err == nil { @@ -243,11 +246,11 @@ func TestRelationship_Confirm_Err(t *testing.T) { // Shows that a session can get got by ID from the buff func TestRelationship_GetByID(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) - session, _ := makeTestSession() + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) + session, _ := session6.makeTestSession() session = sb.AddSession(session.myPrivKey, session.partnerPubKey, nil, session.mySIDHPrivKey, session.partnerSIDHPubKey, - session.partnerSource, Sending, session.e2eParams) + session.partnerSource, session7.Sending, session.e2eParams) session2 := sb.GetByID(session.GetID()) if !reflect.DeepEqual(session, session2) { t.Error("gotten session should be the same") @@ -258,8 +261,8 @@ func TestRelationship_GetByID(t *testing.T) { // returning sessions that are confirmed and past rekeyThreshold func TestRelationship_GetNewestRekeyableSession(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) - sb.sessions[0].negotiationStatus = Unconfirmed + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) + sb.sessions[0].negotiationStatus = session7.Unconfirmed // no available rekeyable sessions: nil session2 := sb.getNewestRekeyableSession() if session2 != sb.sessions[0] { @@ -267,11 +270,11 @@ func TestRelationship_GetNewestRekeyableSession(t *testing.T) { } // add a rekeyable session: that session - session, _ := makeTestSession() + session, _ := session6.makeTestSession() sb.AddSession(session.myPrivKey, session.partnerPubKey, session.baseKey, session.mySIDHPrivKey, session.partnerSIDHPubKey, - session.partnerSource, Sending, session.e2eParams) - sb.sessions[0].negotiationStatus = Confirmed + session.partnerSource, session7.Sending, session.e2eParams) + sb.sessions[0].negotiationStatus = session7.Confirmed session3 := sb.getNewestRekeyableSession() if session3 == nil { @@ -282,15 +285,15 @@ func TestRelationship_GetNewestRekeyableSession(t *testing.T) { // add another rekeyable session: that session // show the newest session is selected - additionalSession, _ := makeTestSession() + additionalSession, _ := session6.makeTestSession() sb.AddSession(additionalSession.myPrivKey, additionalSession.partnerPubKey, nil, additionalSession.mySIDHPrivKey, additionalSession.partnerSIDHPubKey, additionalSession.partnerSource, - Sending, additionalSession.e2eParams) + session7.Sending, additionalSession.e2eParams) - sb.sessions[0].negotiationStatus = Confirmed + sb.sessions[0].negotiationStatus = session7.Confirmed session4 := sb.getNewestRekeyableSession() if session4 == nil { @@ -301,7 +304,7 @@ func TestRelationship_GetNewestRekeyableSession(t *testing.T) { // make the very newest session unrekeyable: the previous session // sb.sessions[1].negotiationStatus = Confirmed - sb.sessions[0].negotiationStatus = Unconfirmed + sb.sessions[0].negotiationStatus = session7.Unconfirmed session5 := sb.getNewestRekeyableSession() if session5 == nil { @@ -314,10 +317,10 @@ func TestRelationship_GetNewestRekeyableSession(t *testing.T) { // Shows that GetSessionForSending follows the hierarchy of sessions correctly func TestRelationship_GetSessionForSending(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) - sb.sessions = make([]*Session, 0) - sb.sessionByID = make(map[SessionID]*Session) + sb.sessions = make([]*session7.Session, 0) + sb.sessionByID = make(map[session7.SessionID]*session7.Session) none := sb.getSessionForSending() if none != nil { @@ -325,15 +328,15 @@ func TestRelationship_GetSessionForSending(t *testing.T) { } // First case: unconfirmed rekey - unconfirmedRekey, _ := makeTestSession() + unconfirmedRekey, _ := session6.makeTestSession() sb.AddSession(unconfirmedRekey.myPrivKey, unconfirmedRekey.partnerPubKey, unconfirmedRekey.partnerPubKey, // FIXME? Shoudln't this be nil? unconfirmedRekey.mySIDHPrivKey, unconfirmedRekey.partnerSIDHPubKey, unconfirmedRekey.partnerSource, - Sending, unconfirmedRekey.e2eParams) - sb.sessions[0].negotiationStatus = Unconfirmed + session7.Sending, unconfirmedRekey.e2eParams) + sb.sessions[0].negotiationStatus = session7.Unconfirmed sb.sessions[0].keyState.SetNumKeysTEST(2000, t) sb.sessions[0].rekeyThreshold = 1000 sb.sessions[0].keyState.SetNumAvailableTEST(600, t) @@ -341,14 +344,14 @@ func TestRelationship_GetSessionForSending(t *testing.T) { if sending.GetID() != sb.sessions[0].GetID() { t.Error("got an unexpected session") } - if sending.Status() != RekeyNeeded || sending.IsConfirmed() { + if sending.Status() != session7.RekeyNeeded || sending.IsConfirmed() { t.Errorf("returned session is expected to be 'RekeyNedded' "+ "'Unconfirmed', it is: %s, confirmed: %v", sending.Status(), sending.IsConfirmed()) } // Second case: unconfirmed active - unconfirmedActive, _ := makeTestSession() + unconfirmedActive, _ := session6.makeTestSession() sb.AddSession(unconfirmedActive.myPrivKey, unconfirmedActive.partnerPubKey, @@ -356,8 +359,8 @@ func TestRelationship_GetSessionForSending(t *testing.T) { unconfirmedActive.mySIDHPrivKey, unconfirmedActive.partnerSIDHPubKey, unconfirmedActive.partnerSource, - Sending, unconfirmedActive.e2eParams) - sb.sessions[0].negotiationStatus = Unconfirmed + session7.Sending, unconfirmedActive.e2eParams) + sb.sessions[0].negotiationStatus = session7.Unconfirmed sb.sessions[0].keyState.SetNumKeysTEST(2000, t) sb.sessions[0].rekeyThreshold = 1000 sb.sessions[0].keyState.SetNumAvailableTEST(2000, t) @@ -366,22 +369,22 @@ func TestRelationship_GetSessionForSending(t *testing.T) { t.Error("got an unexpected session") } - if sending.Status() != Active || sending.IsConfirmed() { + if sending.Status() != session7.Active || sending.IsConfirmed() { t.Errorf("returned session is expected to be 'Active' "+ "'Unconfirmed', it is: %s, confirmed: %v", sending.Status(), sending.IsConfirmed()) } // Third case: confirmed rekey - confirmedRekey, _ := makeTestSession() + confirmedRekey, _ := session6.makeTestSession() sb.AddSession(confirmedRekey.myPrivKey, confirmedRekey.partnerPubKey, confirmedRekey.partnerPubKey, confirmedRekey.mySIDHPrivKey, confirmedRekey.partnerSIDHPubKey, confirmedRekey.partnerSource, - Sending, confirmedRekey.e2eParams) - sb.sessions[0].negotiationStatus = Confirmed + session7.Sending, confirmedRekey.e2eParams) + sb.sessions[0].negotiationStatus = session7.Confirmed sb.sessions[0].keyState.SetNumKeysTEST(2000, t) sb.sessions[0].rekeyThreshold = 1000 sb.sessions[0].keyState.SetNumAvailableTEST(600, t) @@ -389,22 +392,22 @@ func TestRelationship_GetSessionForSending(t *testing.T) { if sending.GetID() != sb.sessions[0].GetID() { t.Error("got an unexpected session") } - if sending.Status() != RekeyNeeded || !sending.IsConfirmed() { + if sending.Status() != session7.RekeyNeeded || !sending.IsConfirmed() { t.Errorf("returned session is expected to be 'RekeyNeeded' "+ "'Confirmed', it is: %s, confirmed: %v", sending.Status(), sending.IsConfirmed()) } // Fourth case: confirmed active - confirmedActive, _ := makeTestSession() + confirmedActive, _ := session6.makeTestSession() sb.AddSession(confirmedActive.myPrivKey, confirmedActive.partnerPubKey, confirmedActive.partnerPubKey, confirmedActive.mySIDHPrivKey, confirmedActive.partnerSIDHPubKey, confirmedActive.partnerSource, - Sending, confirmedActive.e2eParams) + session7.Sending, confirmedActive.e2eParams) - sb.sessions[0].negotiationStatus = Confirmed + sb.sessions[0].negotiationStatus = session7.Confirmed sb.sessions[0].keyState.SetNumKeysTEST(2000, t) sb.sessions[0].keyState.SetNumAvailableTEST(2000, t) sb.sessions[0].rekeyThreshold = 1000 @@ -412,7 +415,7 @@ func TestRelationship_GetSessionForSending(t *testing.T) { if sending.GetID() != sb.sessions[0].GetID() { t.Errorf("got an unexpected session of state: %s", sending.Status()) } - if sending.Status() != Active || !sending.IsConfirmed() { + if sending.Status() != session7.Active || !sending.IsConfirmed() { t.Errorf("returned session is expected to be 'Active' "+ "'Confirmed', it is: %s, confirmed: %v", sending.Status(), sending.IsConfirmed()) @@ -422,10 +425,10 @@ func TestRelationship_GetSessionForSending(t *testing.T) { // Shows that GetKeyForRekey returns a key if there's an appropriate session for rekeying func TestSessionBuff_GetKeyForRekey(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) - sb.sessions = make([]*Session, 0) - sb.sessionByID = make(map[SessionID]*Session) + sb.sessions = make([]*session7.Session, 0) + sb.sessionByID = make(map[session7.SessionID]*session7.Session) // no available rekeyable sessions: error key, err := sb.getKeyForRekey() @@ -436,13 +439,13 @@ func TestSessionBuff_GetKeyForRekey(t *testing.T) { t.Error("shouldn't have returned a key with no sessions available") } - session, _ := makeTestSession() + session, _ := session6.makeTestSession() sb.AddSession(session.myPrivKey, session.partnerPubKey, session.partnerPubKey, session.mySIDHPrivKey, session.partnerSIDHPubKey, session.partnerSource, - Sending, session.e2eParams) - sb.sessions[0].negotiationStatus = Confirmed + session7.Sending, session.e2eParams) + sb.sessions[0].negotiationStatus = session7.Confirmed key, err = sb.getKeyForRekey() if err != nil { t.Error(err) @@ -455,10 +458,10 @@ func TestSessionBuff_GetKeyForRekey(t *testing.T) { // Shows that GetKeyForSending returns a key if there's an appropriate session for sending func TestSessionBuff_GetKeyForSending(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) - sb.sessions = make([]*Session, 0) - sb.sessionByID = make(map[SessionID]*Session) + sb.sessions = make([]*session7.Session, 0) + sb.sessionByID = make(map[session7.SessionID]*session7.Session) // no available rekeyable sessions: error key, err := sb.getKeyForSending() @@ -469,12 +472,12 @@ func TestSessionBuff_GetKeyForSending(t *testing.T) { t.Error("shouldn't have returned a key with no sessions available") } - session, _ := makeTestSession() + session, _ := session6.makeTestSession() sb.AddSession(session.myPrivKey, session.partnerPubKey, session.partnerPubKey, session.mySIDHPrivKey, session.partnerSIDHPubKey, session.partnerSource, - Sending, session.e2eParams) + session7.Sending, session.e2eParams) key, err = sb.getKeyForSending() if err != nil { t.Error(err) @@ -487,31 +490,31 @@ func TestSessionBuff_GetKeyForSending(t *testing.T) { // Shows that TriggerNegotiation sets up for negotiation correctly func TestSessionBuff_TriggerNegotiation(t *testing.T) { mgr := makeTestRelationshipManager(t) - sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams()) - sb.sessions = make([]*Session, 0) - sb.sessionByID = make(map[SessionID]*Session) + sb := NewRelationship(mgr, session7.Send, params.GetDefaultE2ESessionParams()) + sb.sessions = make([]*session7.Session, 0) + sb.sessionByID = make(map[session7.SessionID]*session7.Session) - session, _ := makeTestSession() + session, _ := session6.makeTestSession() session = sb.AddSession(session.myPrivKey, session.partnerPubKey, session.partnerPubKey, session.mySIDHPrivKey, session.partnerSIDHPubKey, session.partnerSource, - Sending, session.e2eParams) - session.negotiationStatus = Confirmed + session7.Sending, session.e2eParams) + session.negotiationStatus = session7.Confirmed // The added session isn't ready for rekey, so it's not returned here negotiations := sb.TriggerNegotiation() if len(negotiations) != 0 { t.Errorf("should have had zero negotiations: %+v", negotiations) } - session2, _ := makeTestSession() + session2, _ := session6.makeTestSession() // Make only a few keys available to trigger the rekeyThreshold session2 = sb.AddSession(session2.myPrivKey, session2.partnerPubKey, session2.partnerPubKey, session.mySIDHPrivKey, session.partnerSIDHPubKey, session2.partnerSource, - Sending, session2.e2eParams) + session7.Sending, session2.e2eParams) session2.keyState.SetNumAvailableTEST(4, t) - session2.negotiationStatus = Confirmed + session2.negotiationStatus = session7.Confirmed negotiations = sb.TriggerNegotiation() if len(negotiations) != 1 { t.Fatal("should have had one negotiation") @@ -520,24 +523,24 @@ func TestSessionBuff_TriggerNegotiation(t *testing.T) { t.Error("negotiated sessions should include the rekeyable " + "session") } - if session2.negotiationStatus != NewSessionTriggered { + if session2.negotiationStatus != session7.NewSessionTriggered { t.Errorf("Trigger negotiations should have set status to "+ "triggered: %s", session2.negotiationStatus) } // Unconfirmed sessions should also be included in the list // as the client should attempt to confirm them - session3, _ := makeTestSession() + session3, _ := session6.makeTestSession() session3 = sb.AddSession(session3.myPrivKey, session3.partnerPubKey, session3.partnerPubKey, session3.mySIDHPrivKey, session3.partnerSIDHPubKey, session3.partnerSource, - Sending, session3.e2eParams) - session3.negotiationStatus = Unconfirmed + session7.Sending, session3.e2eParams) + session3.negotiationStatus = session7.Unconfirmed // Set session 2 status back to Confirmed to show that more than one session can be returned - session2.negotiationStatus = Confirmed + session2.negotiationStatus = session7.Confirmed // Trigger negotiations negotiations = sb.TriggerNegotiation() @@ -548,7 +551,7 @@ func TestSessionBuff_TriggerNegotiation(t *testing.T) { for i := range negotiations { if negotiations[i].GetID() == session3.GetID() { found = true - if negotiations[i].negotiationStatus != Sending { + if negotiations[i].negotiationStatus != session7.Sending { t.Error("triggering negotiation should change session3 to sending") } } @@ -578,10 +581,10 @@ func makeTestRelationshipManager(t *testing.T) *Manager { mySIDHPubKey := util.NewSIDHPublicKey(sidh.KeyVariantSidhB) mySIDHPrivKey.Generate(rng) mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey) - fps := newFingerprints() - g := getGroup() + fps := ratchet.newFingerprints() + g := session6.getGroup() return &Manager{ - ctx: &context{ + ctx: &ratchet.context{ fa: &fps, grp: g, myID: &id.ID{}, @@ -596,7 +599,7 @@ func makeTestRelationshipManager(t *testing.T) *Manager { } // Revises a session to fit a sessionbuff and saves it to the sessionbuff's kv store -func adaptToBuff(session *Session, buff *relationship, t *testing.T) { +func adaptToBuff(session *session7.Session, buff *relationship, t *testing.T) { session.relationship = buff session.keyState.SetKvTEST(buff.manager.kv, t) err := session.keyState.SaveTEST(t) diff --git a/storage/e2e/key.go b/e2e/ratchet/partner/session/cypher.go similarity index 90% rename from storage/e2e/key.go rename to e2e/ratchet/partner/session/cypher.go index bd203c88e9c16d21224feda8181c77adaa8be0de..34ee21885ddd66e9e621c9dae027854837d2ea83 100644 --- a/storage/e2e/key.go +++ b/e2e/ratchet/partner/session/cypher.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( "github.com/cloudflare/circl/dh/sidh" @@ -50,7 +50,7 @@ func GenerateE2ESessionBaseKey(myDHPrivKey, theirDHPubKey *cyclic.Int, return baseKey } -type Key struct { +type Cypher struct { // Links session *Session @@ -61,21 +61,21 @@ type Key struct { keyNum uint32 } -func newKey(session *Session, keynum uint32) *Key { - return &Key{ +func newKey(session *Session, keynum uint32) *Cypher { + return &Cypher{ session: session, keyNum: keynum, } } // return pointers to higher level management structures -func (k *Key) GetSession() *Session { return k.session } +func (k *Cypher) GetSession() *Session { return k.session } // returns the key fingerprint if it has it, otherwise generates it // this function does not memoize the fingerprint if it doesnt have it because // in most cases it will not be used for a long time and as a result should not // be stored in ram. -func (k *Key) Fingerprint() format.Fingerprint { +func (k *Cypher) Fingerprint() format.Fingerprint { if k.fp != nil { return *k.fp } @@ -86,7 +86,7 @@ func (k *Key) Fingerprint() format.Fingerprint { // the E2E key to encrypt msg to its intended recipient // It also properly populates the associated data, including the MAC, fingerprint, // and encrypted timestamp -func (k *Key) Encrypt(msg format.Message) format.Message { +func (k *Cypher) Encrypt(msg format.Message) format.Message { fp := k.Fingerprint() key := k.generateKey() @@ -109,7 +109,7 @@ func (k *Key) Encrypt(msg format.Message) format.Message { // Decrypt uses the E2E key to decrypt the message // It returns an error in case of HMAC verification failure // or in case of a decryption error (related to padding) -func (k *Key) Decrypt(msg format.Message) (format.Message, error) { +func (k *Cypher) Decrypt(msg format.Message) (format.Message, error) { fp := k.Fingerprint() key := k.generateKey() @@ -128,13 +128,13 @@ func (k *Key) Decrypt(msg format.Message) (format.Message, error) { } // Sets the key as used -func (k *Key) denoteUse() { +func (k *Cypher) denoteUse() { k.session.useKey(k.keyNum) } // generateKey derives the current e2e key from the baseKey and the index // keyNum and returns it -func (k *Key) generateKey() e2eCrypto.Key { +func (k *Cypher) generateKey() e2eCrypto.Key { return e2eCrypto.DeriveKey(k.session.baseKey, k.keyNum, k.session.relationshipFingerprint) } diff --git a/e2e/ratchet/partner/session/cypherHandler.go b/e2e/ratchet/partner/session/cypherHandler.go new file mode 100644 index 0000000000000000000000000000000000000000..535d5ac63dd39bcfff24db572633874a87d2b02e --- /dev/null +++ b/e2e/ratchet/partner/session/cypherHandler.go @@ -0,0 +1,6 @@ +package session + +type CypherHandler interface { + AddKey(k *Cypher) + DeleteKey(k *Cypher) +} diff --git a/storage/e2e/key_test.go b/e2e/ratchet/partner/session/cypher_test.go similarity index 96% rename from storage/e2e/key_test.go rename to e2e/ratchet/partner/session/cypher_test.go index acf235b0ed7ddba596faaf27d6109a1273c29d6c..26d3b104aa6427ef1ab500f3225eefd3d447748f 100644 --- a/storage/e2e/key_test.go +++ b/e2e/ratchet/partner/session/cypher_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( "bytes" @@ -68,7 +68,7 @@ func TestGenerateE2ESessionBaseKey(t *testing.T) { // Happy path of newKey(). func Test_newKey(t *testing.T) { - expectedKey := &Key{ + expectedKey := &Cypher{ session: getSession(t), keyNum: rand.Uint32(), } @@ -134,7 +134,7 @@ func TestKey_EncryptDecrypt(t *testing.T) { prng := rand.New(rand.NewSource(42)) for i := 0; i < numTests; i++ { - // generate the baseKey and session + // finalizeKeyNegotation the baseKey and session privateKey := dh.GeneratePrivateKey(dh.DefaultPrivateKeyLength, grp, rng) publicKey := dh.GeneratePublicKey(privateKey, grp) baseKey := dh.GenerateSessionKey(privateKey, publicKey, grp) @@ -229,7 +229,7 @@ func getSession(t *testing.T) *Session { grp := getGroup() rng := csprng.NewSystemRNG() - // generate the baseKey and session + // finalizeKeyNegotation the baseKey and session privateKey := dh.GeneratePrivateKey(dh.DefaultPrivateKeyLength, grp, rng) publicKey := dh.GeneratePublicKey(privateKey, grp) @@ -246,21 +246,12 @@ func getSession(t *testing.T) *Session { baseKey := GenerateE2ESessionBaseKey(privateKey, publicKey, grp, privA, pubB) - fps := newFingerprints() - ctx := &context{ - fa: &fps, - grp: grp, - } - keyState, err := utility.NewStateVector(versioned.NewKV(make(ekv.Memstore)), "keyState", rand.Uint32()) if err != nil { panic(err) } return &Session{ - relationship: &relationship{ - manager: &Manager{ctx: ctx}, - }, baseKey: baseKey, keyState: keyState, } diff --git a/storage/e2e/negotiation.go b/e2e/ratchet/partner/session/negotiation.go similarity index 98% rename from storage/e2e/negotiation.go rename to e2e/ratchet/partner/session/negotiation.go index 783f6a04a16d537ca230a8a01287d7198185fe19..103d3feda5535b277968be2eb0f5a7b5796c995f 100644 --- a/storage/e2e/negotiation.go +++ b/e2e/ratchet/partner/session/negotiation.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import "fmt" diff --git a/e2e/ratchet/partner/session/params.go b/e2e/ratchet/partner/session/params.go new file mode 100644 index 0000000000000000000000000000000000000000..756bff1fa0a1129fd9c1874e22a9759a0ffbc4bd --- /dev/null +++ b/e2e/ratchet/partner/session/params.go @@ -0,0 +1,41 @@ +package session + +import "fmt" + +type Params struct { + // using the DH as a seed, both sides finalizeKeyNegotation a number + // of keys to use before they must rekey because + // there are no keys to use. + MinKeys uint16 + MaxKeys uint16 + // the percent of keys before a rekey is attempted. must be <0 + RekeyThreshold float64 + // extra keys generated and reserved for rekey attempts. This + // many keys are not allowed to be used for sending messages + // in order to ensure there are extras for rekeying. + NumRekeys uint16 +} + +// DEFAULT KEY GENERATION PARAMETERS +// Hardcoded limits for keys +// sets the number of keys very high, but with a low rekey threshold. In this case, if the other party is online, you will read +const ( + minKeys uint16 = 1000 + maxKeys uint16 = 2000 + rekeyThrshold float64 = 0.05 + numReKeys uint16 = 16 +) + +func GetDefaultE2ESessionParams() Params { + return Params{ + MinKeys: minKeys, + MaxKeys: maxKeys, + RekeyThreshold: rekeyThrshold, + NumRekeys: numReKeys, + } +} + +func (p Params) String() string { + return fmt.Sprintf("SessionParams{ MinKeys: %d, MaxKeys: %d, NumRekeys: %d }", + p.MinKeys, p.MaxKeys, p.NumRekeys) +} diff --git a/storage/e2e/relationshipType.go b/e2e/ratchet/partner/session/relationshipType.go similarity index 88% rename from storage/e2e/relationshipType.go rename to e2e/ratchet/partner/session/relationshipType.go index 5fb5980f1f1affde2165328aa719fb16ff40b1d4..cb2220ad40f01a6508184ac520dd980d7f0c4cf8 100644 --- a/storage/e2e/relationshipType.go +++ b/e2e/ratchet/partner/session/relationshipType.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( "fmt" @@ -30,14 +30,14 @@ func (rt RelationshipType) String() string { } } -func (rt RelationshipType) prefix() string { +func (rt RelationshipType) Prefix() string { switch rt { case Send: return "Send" case Receive: return "Receive" default: - jww.FATAL.Panicf("No prefix for relationship type: %s", rt) + jww.FATAL.Panicf("No Prefix for relationship type: %s", rt) } return "" } diff --git a/storage/e2e/session.go b/e2e/ratchet/partner/session/session.go similarity index 87% rename from storage/e2e/session.go rename to e2e/ratchet/partner/session/session.go index 8238b090d17db4bccf63cc1689b45ff18d9651a8..8f0605741225beb0cca6294c38cf3d501c94c1c4 100644 --- a/storage/e2e/session.go +++ b/e2e/ratchet/partner/session/session.go @@ -5,26 +5,26 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( + "encoding/binary" "encoding/json" "fmt" "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" dh "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/hash" "gitlab.com/xx_network/crypto/randomness" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "math" "math/big" - "math/rand" "sync" "testing" ) @@ -34,12 +34,12 @@ const sessionPrefix = "session{ID:%s}" const sessionKey = "session" type Session struct { - //pointer to relationship - relationship *relationship //prefixed kv kv *versioned.KV //params - e2eParams params.E2ESessionParams + e2eParams Params + + sID SessionID partner *id.ID @@ -76,13 +76,18 @@ type Session struct { //mutex mux sync.RWMutex + + //interfaces + cyHandler CypherHandler + grp *cyclic.Group + rng *fastRNG.StreamGenerator } // As this is serialized by json, any field that should be serialized // must be exported // Utility struct to write part of session data to disk type SessionDisk struct { - E2EParams params.E2ESessionParams + E2EParams Params //session type Type uint8 @@ -117,12 +122,14 @@ type SessionDisk struct { } /*CONSTRUCTORS*/ -//Generator which creates all keys and structures -func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey, - baseKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, + +//NewSession - Generator which creates all keys and structures +func NewSession(kv *versioned.KV, t RelationshipType, partner *id.ID, myPrivKey, + partnerPubKey, baseKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey, trigger SessionID, relationshipFingerprint []byte, negotiationStatus Negotiation, - e2eParams params.E2ESessionParams) *Session { + e2eParams Params, cyHandler CypherHandler, grp *cyclic.Group, + rng *fastRNG.StreamGenerator) *Session { if e2eParams.MinKeys < 10 { jww.FATAL.Panicf("Cannot create a session with a minimum "+ @@ -131,7 +138,6 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey session := &Session{ e2eParams: e2eParams, - relationship: ship, t: t, myPrivKey: myPrivKey, partnerPubKey: partnerPubKey, @@ -141,19 +147,23 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey relationshipFingerprint: relationshipFingerprint, negotiationStatus: negotiationStatus, partnerSource: trigger, - partner: ship.manager.partner.DeepCopy(), + partner: partner, + cyHandler: cyHandler, + grp: grp, + rng: rng, } - session.kv = session.generate(ship.kv) + session.finalizeKeyNegotiation() + session.kv = kv.Prefix(MakeSessionPrefix(session.sID)) + session.buildChildKeys() - grp := session.relationship.manager.ctx.grp myPubKey := dh.GeneratePublicKey(session.myPrivKey, grp) jww.INFO.Printf("New Session with Partner %s:\n\tType: %s"+ "\n\tBaseKey: %s\n\tRelationship Fingerprint: %v\n\tNumKeys: %d"+ "\n\tMy Public Key: %s\n\tPartner Public Key: %s"+ "\n\tMy Public SIDH: %s\n\tPartner Public SIDH: %s", - ship.manager.partner, + partner, t, session.baseKey.TextVerbose(16, 0), session.relationshipFingerprint, @@ -163,22 +173,26 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey utility.StringSIDHPrivKey(session.mySIDHPrivKey), utility.StringSIDHPubKey(session.partnerSIDHPubKey)) - err := session.save() + err := session.Save() if err != nil { jww.FATAL.Printf("Failed to make new session for Partner %s: %s", - ship.manager.partner, err) + partner, err) } return session } // Load session and state vector from kv and populate runtime fields -func loadSession(ship *relationship, kv *versioned.KV, - relationshipFingerprint []byte) (*Session, error) { +func LoadSession(kv *versioned.KV, sessionID SessionID, + relationshipFingerprint []byte, cyHandler CypherHandler, + grp *cyclic.Group, rng *fastRNG.StreamGenerator) (*Session, error) { session := Session{ - relationship: ship, - kv: kv, + kv: kv.Prefix(MakeSessionPrefix(sessionID)), + sID: sessionID, + cyHandler: cyHandler, + grp: grp, + rng: rng, } obj, err := kv.Get(sessionKey, currentSessionVersion) @@ -197,19 +211,16 @@ func loadSession(ship *relationship, kv *versioned.KV, if session.t == Receive { // register key fingerprints - ship.manager.ctx.fa.add(session.getUnusedKeys()) + for _, cy := range session.getUnusedKeys() { + cyHandler.AddKey(cy) + } } session.relationshipFingerprint = relationshipFingerprint - if !session.partner.Cmp(ship.manager.partner) { - return nil, errors.Errorf("Stored partner (%s) did not match "+ - "relationship partner (%s)", session.partner, ship.manager.partner) - } - return &session, nil } -func (s *Session) save() error { +func (s *Session) Save() error { now := netTime.Now() @@ -235,7 +246,9 @@ func (s *Session) Delete() { s.mux.Lock() defer s.mux.Unlock() - s.relationship.manager.ctx.fa.remove(s.getUnusedKeys()) + for _, cy := range s.getUnusedKeys() { + s.cyHandler.DeleteKey(cy) + } stateVectorErr := s.keyState.Delete() sessionErr := s.kv.Delete(sessionKey, currentSessionVersion) @@ -281,16 +294,6 @@ func (s *Session) GetSource() SessionID { return s.partnerSource } -//underlying definition of session id -func getSessionIDFromBaseKey(baseKey *cyclic.Int) SessionID { - // no lock is needed because this cannot be edited - sid := SessionID{} - h, _ := hash.NewCMixHash() - h.Write(baseKey.Bytes()) - copy(sid[:], h.Sum(nil)) - return sid -} - //underlying definition of session id // FOR TESTING PURPOSES ONLY func GetSessionIDFromBaseKeyForTesting(baseKey *cyclic.Int, i interface{}) SessionID { @@ -305,13 +308,13 @@ func GetSessionIDFromBaseKeyForTesting(baseKey *cyclic.Int, i interface{}) Sessi //Blake2B hash of base key used for storage func (s *Session) GetID() SessionID { - return getSessionIDFromBaseKey(s.baseKey) + return s.sID } // returns the ID of the partner for this session func (s *Session) GetPartner() *id.ID { - if s.relationship != nil { - return s.relationship.manager.partner.DeepCopy() + if s.partner != nil { + return s.partner } else { return nil } @@ -364,7 +367,7 @@ func (s *Session) unmarshal(b []byte) error { return err } - grp := s.relationship.manager.ctx.grp + grp := s.grp s.e2eParams = sd.E2EParams s.t = RelationshipType(sd.Type) @@ -403,7 +406,7 @@ func (s *Session) unmarshal(b []byte) error { //key usage // Pops the first unused key, skipping any which are denoted as used. // will return if the remaining keys are designated as rekeys -func (s *Session) PopKey() (*Key, error) { +func (s *Session) PopKey() (*Cypher, error) { if s.keyState.GetNumAvailable() <= uint32(s.e2eParams.NumRekeys) { return nil, errors.New("no more keys left, remaining reserved " + "for rekey") @@ -416,7 +419,7 @@ func (s *Session) PopKey() (*Key, error) { return newKey(s, keyNum), nil } -func (s *Session) PopReKey() (*Key, error) { +func (s *Session) PopReKey() (*Cypher, error) { keyNum, err := s.keyState.Next() if err != nil { return nil, err @@ -459,7 +462,7 @@ func (s *Session) Status() Status { // will be redone if it was in the process of sending // Moving from Unconfirmed to Sending and from Confirmed to NewSessionTriggered -// is handled by Session.triggerNegotiation() which is called by the +// is handled by Session.TriggerNegotiation() which is called by the // Manager as part of Manager.TriggerNegotiations() and will be rejected // from this function @@ -501,7 +504,7 @@ func (s *Session) TrySetNegotiationStatus(status Negotiation) error { //save the status if appropriate if save { - if err := s.save(); err != nil { + if err := s.Save(); err != nil { jww.FATAL.Panicf("Failed to save Session %s when moving from %s to %s", s, oldStatus, status) } } @@ -521,7 +524,7 @@ func (s *Session) TrySetNegotiationStatus(status Negotiation) error { // In order to ensure the session creation is not triggered again after the // reload, it is the responsibility of the caller to call // Session.SetConfirmationStatus(NewSessionCreated) . -func (s *Session) triggerNegotiation() bool { +func (s *Session) TriggerNegotiation() bool { // Due to the fact that a read lock cannot be transitioned to a // write lock, the state checks need to happen a second time because it // is possible for another thread to take the read lock and update the @@ -551,7 +554,7 @@ func (s *Session) triggerNegotiation() bool { s.mux.Unlock() return false } - } else if s.negotiationStatus == Unconfirmed && rand.Uint64()%s.rekeyThreshold == 0 { + } else if s.negotiationStatus == Unconfirmed && decideIfResendRekey(s.rng, 1/10) { // retrigger this sessions negotiation s.mux.RUnlock() s.mux.Lock() @@ -604,14 +607,14 @@ func (s *Session) useKey(keynum uint32) { s.keyState.Use(keynum) } -// generates keys from the base data stored in the session object. +// finalizeKeyNegotiation generates keys from the base data stored in the session object. // myPrivKey will be generated if not present -func (s *Session) generate(kv *versioned.KV) *versioned.KV { - grp := s.relationship.manager.ctx.grp +func (s *Session) finalizeKeyNegotiation() { + grp := s.grp - //generate private key if it is not present + //Generates private key if it is not present if s.myPrivKey == nil { - stream := s.relationship.manager.ctx.rng.GetStream() + stream := s.rng.GetStream() s.myPrivKey = dh.GeneratePrivateKey(len(grp.GetPBytes()), grp, stream) // get the variant opposite my partners variant @@ -629,12 +632,14 @@ func (s *Session) generate(kv *versioned.KV) *versioned.KV { s.partnerSIDHPubKey) } - kv = kv.Prefix(makeSessionPrefix(s.GetID())) + s.sID = getSessionIDFromBaseKey(s.baseKey) +} +func (s *Session) buildChildKeys() { p := s.e2eParams h, _ := hash.NewCMixHash() - //generate rekeyThreshold and keying info + //generates rekeyThreshold and keying info numKeys := uint32(randomness.RandInInterval(big.NewInt( int64(p.MaxKeys-p.MinKeys)), s.baseKey.Bytes(), h).Int64() + int64(p.MinKeys)) @@ -652,25 +657,24 @@ func (s *Session) generate(kv *versioned.KV) *versioned.KV { // To generate the state vector key correctly, // basekey must be computed as the session ID is the hash of basekey var err error - s.keyState, err = utility.NewStateVector(kv, "", numKeys) + s.keyState, err = utility.NewStateVector(s.kv, "", numKeys) if err != nil { jww.FATAL.Printf("Failed key generation: %s", err) } //register keys for reception if this is a reception session if s.t == Receive { - //register keys - s.relationship.manager.ctx.fa.add(s.getUnusedKeys()) + for _, cy := range s.getUnusedKeys() { + s.cyHandler.AddKey(cy) + } } - - return kv } //returns key objects for all unused keys -func (s *Session) getUnusedKeys() []*Key { +func (s *Session) getUnusedKeys() []*Cypher { keyNums := s.keyState.GetUnusedKeyNums() - keys := make([]*Key, len(keyNums)) + keys := make([]*Cypher, len(keyNums)) for i, keyNum := range keyNums { keys[i] = newKey(s, keyNum) } @@ -679,6 +683,16 @@ func (s *Session) getUnusedKeys() []*Key { } //builds the -func makeSessionPrefix(sid SessionID) string { +func MakeSessionPrefix(sid SessionID) string { return fmt.Sprintf(sessionPrefix, sid) } + +func decideIfResendRekey(genRng *fastRNG.StreamGenerator, ratio float64) bool { + stream := genRng.GetStream() + b := make([]byte, 8) + stream.Read(b) + stream.Close() + randNum := binary.BigEndian.Uint64(b) + max := uint64(float64(math.MaxUint64) * ratio) + return randNum < max +} diff --git a/storage/e2e/sessionID.go b/e2e/ratchet/partner/session/sessionID.go similarity index 72% rename from storage/e2e/sessionID.go rename to e2e/ratchet/partner/session/sessionID.go index 00b8ebca5c4709dc12d06da89c247eafbb09894d..4dddea303df01963b2a6b2d2a4bacbee5a44b08a 100644 --- a/storage/e2e/sessionID.go +++ b/e2e/ratchet/partner/session/sessionID.go @@ -5,11 +5,13 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( "encoding/base64" "github.com/pkg/errors" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/hash" ) const sessionIDLen = 32 @@ -31,3 +33,13 @@ func (sid *SessionID) Unmarshal(b []byte) error { copy(sid[:], b) return nil } + +//underlying definition of session id +func getSessionIDFromBaseKey(baseKey *cyclic.Int) SessionID { + // no lock is needed because this cannot be edited + sid := SessionID{} + h, _ := hash.NewCMixHash() + h.Write(baseKey.Bytes()) + copy(sid[:], h.Sum(nil)) + return sid +} diff --git a/storage/e2e/session_test.go b/e2e/ratchet/partner/session/session_test.go similarity index 92% rename from storage/e2e/session_test.go rename to e2e/ratchet/partner/session/session_test.go index 2719df3c7d28ee09726c0bb9eec31682e96b865c..141cc8ad2b85c82c87a95f891169c988fc479efa 100644 --- a/storage/e2e/session_test.go +++ b/e2e/ratchet/partner/session/session_test.go @@ -5,11 +5,13 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import ( "errors" "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/e2e/ratchet" + "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage/utility" util "gitlab.com/elixxir/client/storage/utility" @@ -38,8 +40,8 @@ func TestSession_generate_noPrivateKeyReceive(t *testing.T) { partnerSIDHPrivKey.GeneratePublicKey(partnerSIDHPubKey) // create context objects for general use - fps := newFingerprints() - ctx := &context{ + fps := ratchet.newFingerprints() + ctx := &ratchet.context{ fa: &fps, grp: grp, rng: fastRNG.NewStreamGenerator(1, 0, csprng.NewSystemRNG), @@ -50,14 +52,14 @@ func TestSession_generate_noPrivateKeyReceive(t *testing.T) { partnerPubKey: partnerPubKey, partnerSIDHPubKey: partnerSIDHPubKey, e2eParams: params.GetDefaultE2ESessionParams(), - relationship: &relationship{ - manager: &Manager{ctx: ctx}, + relationship: &ratchet.relationship{ + manager: &partner.Manager{ctx: ctx}, }, t: Receive, } - // run the generate command - s.generate(versioned.NewKV(make(ekv.Memstore))) + // run the finalizeKeyNegotation command + s.finalizeKeyNegotation(versioned.NewKV(make(ekv.Memstore))) // check that it generated a private key if s.myPrivKey == nil { @@ -110,8 +112,8 @@ func TestSession_generate_PrivateKeySend(t *testing.T) { mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey) // create context objects for general use - fps := newFingerprints() - ctx := &context{ + fps := ratchet.newFingerprints() + ctx := &ratchet.context{ fa: &fps, grp: grp, } @@ -123,14 +125,14 @@ func TestSession_generate_PrivateKeySend(t *testing.T) { mySIDHPrivKey: mySIDHPrivKey, partnerSIDHPubKey: partnerSIDHPubKey, e2eParams: params.GetDefaultE2ESessionParams(), - relationship: &relationship{ - manager: &Manager{ctx: ctx}, + relationship: &ratchet.relationship{ + manager: &partner.Manager{ctx: ctx}, }, t: Send, } - // run the generate command - s.generate(versioned.NewKV(make(ekv.Memstore))) + // run the finalizeKeyNegotation command + s.finalizeKeyNegotation(versioned.NewKV(make(ekv.Memstore))) // check that it generated a private key if s.myPrivKey.Cmp(myPrivKey) != 0 { @@ -164,13 +166,13 @@ func TestSession_generate_PrivateKeySend(t *testing.T) { } } -// Shows that newSession can result in all the fields being populated +// Shows that NewSession can result in all the fields being populated func TestNewSession(t *testing.T) { // Make a test session to easily populate all the fields sessionA, _ := makeTestSession() // Make a new session with the variables we got from makeTestSession - sessionB := newSession(sessionA.relationship, sessionA.t, + sessionB := NewSession(sessionA.relationship, sessionA.t, sessionA.myPrivKey, sessionA.partnerPubKey, sessionA.baseKey, sessionA.mySIDHPrivKey, sessionA.partnerSIDHPubKey, sessionA.GetID(), []byte(""), sessionA.negotiationStatus, @@ -182,26 +184,26 @@ func TestNewSession(t *testing.T) { } // For everything else, just make sure it's populated if sessionB.keyState == nil { - t.Error("newSession should populate keyState") + t.Error("NewSession should populate keyState") } if sessionB.relationship == nil { - t.Error("newSession should populate relationship") + t.Error("NewSession should populate relationship") } if sessionB.rekeyThreshold == 0 { - t.Error("newSession should populate rekeyThreshold") + t.Error("NewSession should populate rekeyThreshold") } } -// Shows that loadSession can result in all the fields being populated +// Shows that LoadSession can result in all the fields being populated func TestSession_Load(t *testing.T) { // Make a test session to easily populate all the fields sessionA, _ := makeTestSession() - err := sessionA.save() + err := sessionA.Save() if err != nil { t.Fatal(err) } // Load another, hopefully identical session from the storage - sessionB, err := loadSession(sessionA.relationship, sessionA.kv, []byte("")) + sessionB, err := LoadSession(sessionA.relationship, sessionA.kv, []byte("")) if err != nil { t.Fatal(err) } @@ -210,7 +212,7 @@ func TestSession_Load(t *testing.T) { t.Error(err) } // Key state should also be loaded and equivalent to the other session - // during loadSession() + // during LoadSession() if !reflect.DeepEqual(sessionA.keyState, sessionB.keyState) { t.Errorf("Two key states do not match.\nsessionA: %+v\nsessionB: %+v", sessionA.keyState, sessionB.keyState) @@ -233,8 +235,8 @@ func TestSession_Serialization(t *testing.T) { } sDeserialized := &Session{ - relationship: &relationship{ - manager: &Manager{ctx: ctx}, + relationship: &ratchet.relationship{ + manager: &partner.Manager{ctx: ctx}, }, kv: s.kv, } @@ -297,7 +299,7 @@ func TestSession_PopKey(t *testing.T) { // delete should remove unused keys from this session func TestSession_Delete(t *testing.T) { s, _ := makeTestSession() - err := s.save() + err := s.Save() if err != nil { t.Fatal(err) } @@ -537,7 +539,7 @@ func TestSession_TriggerNegotiation(t *testing.T) { s.rekeyThreshold = 49 s.negotiationStatus = Confirmed - if !s.triggerNegotiation() { + if !s.TriggerNegotiation() { t.Error("partnerSource negotiation unexpectedly failed") } if s.negotiationStatus != NewSessionTriggered { @@ -548,7 +550,7 @@ func TestSession_TriggerNegotiation(t *testing.T) { s.rekeyThreshold = 50 s.negotiationStatus = Confirmed - if !s.triggerNegotiation() { + if !s.TriggerNegotiation() { t.Error("partnerSource negotiation unexpectedly failed") } if s.negotiationStatus != NewSessionTriggered { @@ -559,7 +561,7 @@ func TestSession_TriggerNegotiation(t *testing.T) { s.rekeyThreshold = 51 s.negotiationStatus = Confirmed - if s.triggerNegotiation() { + if s.TriggerNegotiation() { t.Error("trigger negotiation unexpectedly failed") } if s.negotiationStatus != Confirmed { @@ -568,7 +570,7 @@ func TestSession_TriggerNegotiation(t *testing.T) { // Test other case: partnerSource sending confirmation message on unconfirmed session s.negotiationStatus = Unconfirmed - if !s.triggerNegotiation() { + if !s.TriggerNegotiation() { t.Error("partnerSource negotiation unexpectedly failed") } if s.negotiationStatus != Sending { @@ -596,7 +598,7 @@ func TestSession_GetTrigger(t *testing.T) { } // Make a default test session with some things populated -func makeTestSession() (*Session, *context) { +func makeTestSession() (*Session, *ratchet.context) { grp := getGroup() rng := csprng.NewSystemRNG() partnerPrivKey := dh.GeneratePrivateKey(dh.DefaultPrivateKeyLength, @@ -617,8 +619,8 @@ func makeTestSession() (*Session, *context) { mySIDHPrivKey, partnerSIDHPubKey) // create context objects for general use - fps := newFingerprints() - ctx := &context{ + fps := ratchet.newFingerprints() + ctx := &ratchet.context{ fa: &fps, grp: grp, myID: &id.ID{}, @@ -633,8 +635,8 @@ func makeTestSession() (*Session, *context) { mySIDHPrivKey: mySIDHPrivKey, partnerSIDHPubKey: partnerSIDHPubKey, e2eParams: params.GetDefaultE2ESessionParams(), - relationship: &relationship{ - manager: &Manager{ + relationship: &ratchet.relationship{ + manager: &partner.Manager{ ctx: ctx, kv: kv, partner: &id.ID{}, diff --git a/storage/e2e/status.go b/e2e/ratchet/partner/session/status.go similarity index 98% rename from storage/e2e/status.go rename to e2e/ratchet/partner/session/status.go index 63633724d0ad1b3faa2488198fdd4280041b028c..6494e31deafa043fa3bcf433fce5fea80cf772b4 100644 --- a/storage/e2e/status.go +++ b/e2e/ratchet/partner/session/status.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session import "fmt" diff --git a/storage/e2e/status_test.go b/e2e/ratchet/partner/session/status_test.go similarity index 98% rename from storage/e2e/status_test.go rename to e2e/ratchet/partner/session/status_test.go index a81894bae53b808ddc632a7881d5945b5b0c2d24..738db5260e63c0396613a3543475e38a4edc8392 100644 --- a/storage/e2e/status_test.go +++ b/e2e/ratchet/partner/session/status_test.go @@ -5,7 +5,7 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package session // Testing file for the status.go functions diff --git a/storage/e2e/store.go b/e2e/ratchet/store.go similarity index 91% rename from storage/e2e/store.go rename to e2e/ratchet/store.go index 1c9c361106b23062a08c7710afda82889d031d4a..ca16426ed134ab8c67bec6e44bea9058604ce6d2 100644 --- a/storage/e2e/store.go +++ b/e2e/ratchet/store.go @@ -5,13 +5,15 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package ratchet import ( "encoding/json" "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/e2e/ratchet/partner" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces/params" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" @@ -39,7 +41,7 @@ const ( var NoPartnerErrorStr = "No relationship with partner found" type Store struct { - managers map[id.ID]*Manager + managers map[id.ID]*partner.Manager mux sync.RWMutex dhPrivateKey *cyclic.Int @@ -67,7 +69,7 @@ func NewStore(grp *cyclic.Group, kv *versioned.KV, privKey *cyclic.Int, fingerprints := newFingerprints() s := &Store{ - managers: make(map[id.ID]*Manager), + managers: make(map[id.ID]*partner.Manager), dhPrivateKey: privKey, dhPublicKey: pubKey, @@ -117,7 +119,7 @@ func LoadStore(kv *versioned.KV, myID *id.ID, rng *fastRNG.StreamGenerator) (*St } s := &Store{ - managers: make(map[id.ID]*Manager), + managers: make(map[id.ID]*partner.Manager), fingerprints: &fingerprints, @@ -183,7 +185,7 @@ func (s *Store) AddPartner(partnerID *id.ID, partnerPubKey, return errors.New("Cannot overwrite existing partner") } - m := newManager(s.context, s.kv, partnerID, myPrivKey, partnerPubKey, + m := partner.newManager(s.context, s.kv, partnerID, myPrivKey, partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, sendParams, receiveParams) @@ -203,7 +205,7 @@ func (s *Store) DeletePartner(partnerId *id.ID) error { return errors.New(NoPartnerErrorStr) } - if err := clearManager(m, s.kv); err != nil { + if err := partner.clearManager(m, s.kv); err != nil { return errors.WithMessagef(err, "Could not remove partner %s from store", partnerId) } @@ -211,7 +213,7 @@ func (s *Store) DeletePartner(partnerId *id.ID) error { return s.save() } -func (s *Store) GetPartner(partnerID *id.ID) (*Manager, error) { +func (s *Store) GetPartner(partnerID *id.ID) (*partner.Manager, error) { s.mux.RLock() defer s.mux.RUnlock() @@ -262,7 +264,7 @@ func (s *Store) GetPartners() []*id.ID { } // PopKey pops a key for use based upon its fingerprint. -func (s *Store) PopKey(f format.Fingerprint) (*Key, bool) { +func (s *Store) PopKey(f format.Fingerprint) (*session2.Cypher, bool) { return s.fingerprints.Pop(f) } @@ -315,7 +317,7 @@ func (s *Store) unmarshal(b []byte) error { partnerID := (&contacts[i]).DeepCopy() // Load the relationship. The relationship handles adding the fingerprints via the // context object - manager, err := loadManager(s.context, s.kv, partnerID) + manager, err := partner.loadManager(s.context, s.kv, partnerID) if err != nil { jww.FATAL.Panicf("Failed to load relationship for partner %s: %s", partnerID, err.Error()) @@ -368,20 +370,20 @@ func (s *Store) SetE2ESessionParams(newParams params.E2ESessionParams) { } type fingerprints struct { - toKey map[format.Fingerprint]*Key + toKey map[format.Fingerprint]*session2.Cypher mux sync.RWMutex } // newFingerprints creates a new fingerprints with an empty map. func newFingerprints() fingerprints { return fingerprints{ - toKey: make(map[format.Fingerprint]*Key), + toKey: make(map[format.Fingerprint]*session2.Cypher), } } // fingerprints adheres to the fingerprintAccess interface. -func (f *fingerprints) add(keys []*Key) { +func (f *fingerprints) add(keys []*session2.Cypher) { f.mux.Lock() defer f.mux.Unlock() @@ -392,7 +394,7 @@ func (f *fingerprints) add(keys []*Key) { } } -func (f *fingerprints) remove(keys []*Key) { +func (f *fingerprints) remove(keys []*session2.Cypher) { f.mux.Lock() defer f.mux.Unlock() @@ -409,7 +411,7 @@ func (f *fingerprints) Check(fingerprint format.Fingerprint) bool { return ok } -func (f *fingerprints) Pop(fingerprint format.Fingerprint) (*Key, bool) { +func (f *fingerprints) Pop(fingerprint format.Fingerprint) (*session2.Cypher, bool) { f.mux.Lock() defer f.mux.Unlock() key, ok := f.toKey[fingerprint] diff --git a/storage/e2e/store_test.go b/e2e/ratchet/store_test.go similarity index 92% rename from storage/e2e/store_test.go rename to e2e/ratchet/store_test.go index 7a209321d8aba398ba33da1442fb85d25eb3e205..feacc60c94494df0d02af10d81153a2d147b7903 100644 --- a/storage/e2e/store_test.go +++ b/e2e/ratchet/store_test.go @@ -5,11 +5,14 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package e2e +package ratchet import ( "bytes" "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/e2e/ratchet/partner" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" + "gitlab.com/elixxir/client/e2e/ratchet/session" "gitlab.com/elixxir/client/interfaces/params" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" @@ -37,7 +40,7 @@ func TestNewStore(t *testing.T) { rng := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) e2eP := params.GetDefaultE2ESessionParams() expectedStore := &Store{ - managers: make(map[id.ID]*Manager), + managers: make(map[id.ID]*partner.Manager), dhPrivateKey: privKey, dhPublicKey: diffieHellman.GeneratePublicKey(privKey, grp), grp: grp, @@ -107,7 +110,7 @@ func TestStore_AddPartner(t *testing.T) { // initiation of the connection. _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - expectedManager := newManager(s.context, s.kv, partnerID, + expectedManager := partner.newManager(s.context, s.kv, partnerID, s.dhPrivateKey, pubKey, privSIDHKey, pubSIDHKey, p, p) @@ -170,7 +173,7 @@ func TestStore_GetPartner(t *testing.T) { p := params.GetDefaultE2ESessionParams() _, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA) privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB) - expectedManager := newManager(s.context, s.kv, partnerID, + expectedManager := partner.newManager(s.context, s.kv, partnerID, s.dhPrivateKey, pubKey, privSIDHKey, pubSIDHKey, p, p) _ = s.AddPartner(partnerID, pubKey, s.dhPrivateKey, pubSIDHKey, privSIDHKey, p, p) @@ -245,7 +248,7 @@ func TestStore_GetPartnerContact_Error(t *testing.T) { // Tests happy path of Store.PopKey. func TestStore_PopKey(t *testing.T) { s, _, _ := makeTestStore() - se, _ := makeTestSession() + se, _ := session.makeTestSession() // Pop Key that does not exist fp := format.Fingerprint{0xF, 0x6, 0x2} @@ -260,7 +263,7 @@ func TestStore_PopKey(t *testing.T) { } // Add a Key - keys := []*Key{newKey(se, 0), newKey(se, 1), newKey(se, 2)} + keys := []*session2.Cypher{session.newKey(se, 0), session.newKey(se, 1), session.newKey(se, 2)} s.add(keys) fp = keys[0].Fingerprint() @@ -279,7 +282,7 @@ func TestStore_PopKey(t *testing.T) { // Tests happy path of Store.CheckKey. func TestStore_CheckKey(t *testing.T) { s, _, _ := makeTestStore() - se, _ := makeTestSession() + se, _ := session.makeTestSession() // Check for a Key that does not exist fp := format.Fingerprint{0xF, 0x6, 0x2} @@ -289,7 +292,7 @@ func TestStore_CheckKey(t *testing.T) { } // Add Keys - keys := []*Key{newKey(se, 0), newKey(se, 1), newKey(se, 2)} + keys := []*session2.Cypher{session.newKey(se, 0), session.newKey(se, 1), session.newKey(se, 2)} s.add(keys) fp = keys[0].Fingerprint() @@ -335,7 +338,7 @@ func TestStore_GetGroup(t *testing.T) { // Tests happy path of newFingerprints. func Test_newFingerprints(t *testing.T) { - expectedFp := fingerprints{toKey: make(map[format.Fingerprint]*Key)} + expectedFp := fingerprints{toKey: make(map[format.Fingerprint]*session2.Cypher)} fp := newFingerprints() if !reflect.DeepEqual(&expectedFp, &fp) { @@ -346,8 +349,8 @@ func Test_newFingerprints(t *testing.T) { // Tests happy path of fingerprints.add. func TestFingerprints_add(t *testing.T) { - se, _ := makeTestSession() - keys := []*Key{newKey(se, 0), newKey(se, 1), newKey(se, 2)} + se, _ := session.makeTestSession() + keys := []*session2.Cypher{session.newKey(se, 0), session.newKey(se, 1), session.newKey(se, 2)} fps := newFingerprints() fps.add(keys) @@ -368,8 +371,8 @@ func TestFingerprints_add(t *testing.T) { // Tests happy path of fingerprints.remove. func TestFingerprints_remove(t *testing.T) { - se, _ := makeTestSession() - keys := []*Key{newKey(se, 0), newKey(se, 1), newKey(se, 2)} + se, _ := session.makeTestSession() + keys := []*session2.Cypher{session.newKey(se, 0), session.newKey(se, 1), session.newKey(se, 2)} fps := newFingerprints() fps.add(keys) fps.remove(keys) diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go index 4914bfb4fa04dd5273ea5bfb775ae1e3450b33ba..b5104d1018151632d4d1ae41767378333990d1bd 100644 --- a/interfaces/networkManager.go +++ b/interfaces/networkManager.go @@ -221,17 +221,5 @@ type Preimage [32]byte type ClientErrorReport func(source, message, trace string) -//type Ratchet interface { -// SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) -// SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error) -// AddPartner(partnerID *id.ID, partnerPubKey, -// myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, -// mySIDHPrivKey *sidh.PrivateKey, -// sendParams, receiveParams params.E2ESessionParams) -// GetPartner(partnerID *id.ID) (*manager, error) -// DeletePartner(partnerId *id.ID) -// GetAllPartnerIDs() []*id.ID -//} - //for use in key exchange which needs to be callable inside of network ///type SendE2E func(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error) diff --git a/keyExchange/confirm.go b/keyExchange/confirm.go index 9e7996ded27d3b79fbed8f3119ecfec0acae8774..3ff7e3183b279de0cebef1071a662f094e29de96 100644 --- a/keyExchange/confirm.go +++ b/keyExchange/confirm.go @@ -11,10 +11,10 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/e2e" ) func startConfirm(sess *storage.Session, c chan message.Receive, @@ -69,7 +69,7 @@ func handleConfirm(sess *storage.Session, confirmation message.Receive) { // This is expected sometimes because some errors cases can cause multiple // sends. For example if the sending device runs out of battery after it // sends but before it records the send it will resend on reload - if err := confirmedSession.TrySetNegotiationStatus(e2e.Confirmed); err != nil { + if err := confirmedSession.TrySetNegotiationStatus(session2.Confirmed); err != nil { jww.WARN.Printf("[REKEY] Failed to set the negotiation status for the "+ "confirmation of session %s from partner %s. This is expected in "+ "some edge cases but could be a sign of an issue if it persists: %s", @@ -80,17 +80,17 @@ func handleConfirm(sess *storage.Session, confirmation message.Receive) { "%s from partner %s.", confirmedSession, partner.GetPartnerID()) } -func unmarshalConfirm(payload []byte) (e2e.SessionID, error) { +func unmarshalConfirm(payload []byte) (session2.SessionID, error) { msg := &RekeyConfirm{} if err := proto.Unmarshal(payload, msg); err != nil { - return e2e.SessionID{}, errors.Errorf("Failed to "+ + return session2.SessionID{}, errors.Errorf("Failed to "+ "unmarshal payload: %s", err) } - confirmedSessionID := e2e.SessionID{} + confirmedSessionID := session2.SessionID{} if err := confirmedSessionID.Unmarshal(msg.SessionID); err != nil { - return e2e.SessionID{}, errors.Errorf("Failed to unmarshal"+ + return session2.SessionID{}, errors.Errorf("Failed to unmarshal"+ " sessionID: %s", err) } diff --git a/keyExchange/confirm_test.go b/keyExchange/confirm_test.go index 3dd8312ec791dfce8f70b195f1e80a865d4759c3..87c453093c6c0cdb0fb3d6d0d378441fbdf753bf 100644 --- a/keyExchange/confirm_test.go +++ b/keyExchange/confirm_test.go @@ -10,9 +10,9 @@ package keyExchange import ( "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" @@ -94,7 +94,7 @@ func TestHandleConfirm(t *testing.T) { // Check that the session is in the proper status newSession := receivedManager.GetSendSession(sessionID) - if newSession.NegotiationStatus() != e2e.Confirmed { + if newSession.NegotiationStatus() != session2.Confirmed { t.Errorf("Session not in confirmed status!"+ "\n\tExpected: Confirmed"+ "\n\tReceived: %s", confirmedSession.NegotiationStatus()) diff --git a/keyExchange/exchange_test.go b/keyExchange/exchange_test.go index 7136ea3dc36a23256af933b1f2030567393b13cb..04d6c4ec205d5396fab1e29dd5b64540425fa547 100644 --- a/keyExchange/exchange_test.go +++ b/keyExchange/exchange_test.go @@ -11,11 +11,11 @@ import ( "fmt" "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/switchboard" dh "gitlab.com/elixxir/crypto/diffieHellman" @@ -124,14 +124,14 @@ func TestFullExchange(t *testing.T) { confirmedSession := receivedManager.GetSendSession(oldSessionID) // Generate the new session ID based off of Bob's new keys - baseKey := e2e.GenerateE2ESessionBaseKey(alicePrivKey, newBobPubKey, + baseKey := session2.GenerateE2ESessionBaseKey(alicePrivKey, newBobPubKey, genericGroup, aliceSIDHPrivKey, newBobSIDHPubKey) - newSessionID := e2e.GetSessionIDFromBaseKeyForTesting(baseKey, t) + newSessionID := session2.GetSessionIDFromBaseKeyForTesting(baseKey, t) // Check that the Alice's session for Bob is in the proper status newSession := receivedManager.GetReceiveSession(newSessionID) fmt.Printf("newSession: %v\n", newSession) - if newSession == nil || newSession.NegotiationStatus() != e2e.Confirmed { + if newSession == nil || newSession.NegotiationStatus() != session2.Confirmed { t.Errorf("Session not in confirmed status!"+ "\n\tExpected: Confirmed"+ "\n\tReceived: %s", confirmedSession.NegotiationStatus()) diff --git a/keyExchange/rekey.go b/keyExchange/rekey.go index bf5d77803692f09e4327ca4193a9b0e0cd7f585e..e76f54652cf58f9f1e9b0c0b5975c9d1eceb7a7d 100644 --- a/keyExchange/rekey.go +++ b/keyExchange/rekey.go @@ -12,6 +12,8 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/e2e/ratchet/partner" + session3 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" @@ -19,7 +21,6 @@ import ( network2 "gitlab.com/elixxir/client/network" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/comms/network" ds "gitlab.com/elixxir/comms/network/dataStructures" @@ -30,7 +31,7 @@ import ( func CheckKeyExchanges(instance *network.Instance, sendE2E interfaces.SendE2E, events event.Manager, sess *storage.Session, - manager *e2e.Manager, sendTimeout time.Duration, + manager *partner.Manager, sendTimeout time.Duration, stop *stoppable.Single) { sessions := manager.TriggerNegotiations() for _, session := range sessions { @@ -45,23 +46,23 @@ func CheckKeyExchanges(instance *network.Instance, sendE2E interfaces.SendE2E, // session while the latter on an extant session func trigger(instance *network.Instance, sendE2E interfaces.SendE2E, events event.Manager, sess *storage.Session, - manager *e2e.Manager, session *e2e.Session, + manager *partner.Manager, session *session3.Session, sendTimeout time.Duration, stop *stoppable.Single) { - var negotiatingSession *e2e.Session + var negotiatingSession *session3.Session jww.INFO.Printf("[REKEY] Negotiation triggered for session %s with "+ "status: %s", session, session.NegotiationStatus()) switch session.NegotiationStatus() { // If the passed session is triggering a negotiation on a new session to // replace itself, then create the session - case e2e.NewSessionTriggered: + case session3.NewSessionTriggered: //create the session, pass a nil private key to generate a new one negotiatingSession = manager.NewSendSession(nil, nil, sess.E2e().GetE2ESessionParams()) //move the state of the triggering session forward - session.SetNegotiationStatus(e2e.NewSessionCreated) + session.SetNegotiationStatus(session3.NewSessionCreated) // If the session is set to send a negotiation - case e2e.Sending: + case session3.Sending: negotiatingSession = session default: jww.FATAL.Panicf("[REKEY] Session %s provided invalid e2e "+ @@ -83,7 +84,7 @@ func trigger(instance *network.Instance, sendE2E interfaces.SendE2E, } func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E, - sess *storage.Session, session *e2e.Session, sendTimeout time.Duration, + sess *storage.Session, session *session3.Session, sendTimeout time.Duration, rekeyPreimage []byte, stop *stoppable.Single) error { e2eStore := sess.E2e() @@ -152,7 +153,7 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E, // transmit, the partner cannot read the result. Log the error and set // the session as unconfirmed so it will re-trigger the negotiation if !success { - session.SetNegotiationStatus(e2e.Unconfirmed) + session.SetNegotiationStatus(session3.Unconfirmed) return errors.Errorf("[REKEY] Key Negotiation rekey for %s failed to "+ "transmit %v/%v paritions: %v round failures, %v timeouts, msgID: %s", session, numRoundFail+numTimeOut, len(rounds), numRoundFail, @@ -163,9 +164,9 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E, // in the session and the log jww.INFO.Printf("[REKEY] Key Negotiation rekey transmission for %s, msgID %s successful", session, msgID) - err = session.TrySetNegotiationStatus(e2e.Sent) + err = session.TrySetNegotiationStatus(session3.Sent) if err != nil { - if session.NegotiationStatus() == e2e.NewSessionTriggered { + if session.NegotiationStatus() == session3.NewSessionTriggered { msg := fmt.Sprintf("All channels exhausted for %s, "+ "rekey impossible.", session) return errors.WithMessage(err, msg) diff --git a/keyExchange/trigger.go b/keyExchange/trigger.go index 984fc3306400da69c38f2005b4e1695e153c6563..85e68e48b2493e1131c5d1d09043a34f56b8770e 100644 --- a/keyExchange/trigger.go +++ b/keyExchange/trigger.go @@ -13,13 +13,13 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/network" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" ds "gitlab.com/elixxir/comms/network/dataStructures" "gitlab.com/elixxir/crypto/cyclic" @@ -168,26 +168,26 @@ func handleTrigger(sess *storage.Session, net interfaces.NetworkManager, return nil } -func unmarshalSource(grp *cyclic.Group, payload []byte) (e2e.SessionID, +func unmarshalSource(grp *cyclic.Group, payload []byte) (session2.SessionID, *cyclic.Int, *sidh.PublicKey, error) { msg := &RekeyTrigger{} if err := proto.Unmarshal(payload, msg); err != nil { - return e2e.SessionID{}, nil, nil, errors.Errorf( + return session2.SessionID{}, nil, nil, errors.Errorf( "Failed to unmarshal payload: %s", err) } - oldSessionID := e2e.SessionID{} + oldSessionID := session2.SessionID{} if err := oldSessionID.Unmarshal(msg.SessionID); err != nil { - return e2e.SessionID{}, nil, nil, errors.Errorf( + return session2.SessionID{}, nil, nil, errors.Errorf( "Failed to unmarshal sessionID: %s", err) } // checking it is inside the group is necessary because otherwise the // creation of the cyclic int will crash below if !grp.BytesInside(msg.PublicKey) { - return e2e.SessionID{}, nil, nil, errors.Errorf( + return session2.SessionID{}, nil, nil, errors.Errorf( "Public key not in e2e group; PublicKey %v", msg.PublicKey) } diff --git a/keyExchange/trigger_test.go b/keyExchange/trigger_test.go index 610428b2ce0ed3c84a2ececca56827b60c9b476e..6391fbab07cf54391c346f41162c42b556964583 100644 --- a/keyExchange/trigger_test.go +++ b/keyExchange/trigger_test.go @@ -9,10 +9,10 @@ package keyExchange import ( "github.com/cloudflare/circl/dh/sidh" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/stoppable" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" dh "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/xx_network/crypto/csprng" @@ -109,9 +109,9 @@ func TestHandleTrigger(t *testing.T) { } // Generate the new session ID based off of Bob's new keys - baseKey := e2e.GenerateE2ESessionBaseKey(alicePrivKey, newBobPubKey, + baseKey := session2.GenerateE2ESessionBaseKey(alicePrivKey, newBobPubKey, genericGroup, aliceSIDHPrivKey, newBobSIDHPubKey) - newSessionID := e2e.GetSessionIDFromBaseKeyForTesting(baseKey, t) + newSessionID := session2.GetSessionIDFromBaseKeyForTesting(baseKey, t) // Check that this new session ID is now in the manager newSession := receivedManager.GetReceiveSession(newSessionID) @@ -124,7 +124,7 @@ func TestHandleTrigger(t *testing.T) { unknownPubliceKey := dh.GeneratePublicKey(unknownPrivateKey, genericGroup) // Generate a new session ID based off of these unrecognized keys - badSessionID := e2e.GetSessionIDFromBaseKeyForTesting(unknownPubliceKey, t) + badSessionID := session2.GetSessionIDFromBaseKeyForTesting(unknownPubliceKey, t) // Check that this session with unrecognized keys is not valid badSession := receivedManager.GetReceiveSession(badSessionID) diff --git a/keyExchange/utils_test.go b/keyExchange/utils_test.go index ef27ae79eb04cd7917cb62f557c093351a674a01..ed32032b4320569573019a3b74a6af65c218c652 100644 --- a/keyExchange/utils_test.go +++ b/keyExchange/utils_test.go @@ -11,6 +11,7 @@ import ( "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" jww "github.com/spf13/jwalterweatherman" + session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" @@ -18,7 +19,6 @@ import ( "gitlab.com/elixxir/client/network/gateway" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/e2e" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/comms/network" @@ -40,14 +40,14 @@ import ( // Generate partner ID for two people, used for smoke tests func GeneratePartnerID(aliceKey, bobKey *cyclic.Int, group *cyclic.Group, alicePrivKey *sidh.PrivateKey, - bobPubKey *sidh.PublicKey) e2e.SessionID { - baseKey := e2e.GenerateE2ESessionBaseKey(aliceKey, bobKey, group, + bobPubKey *sidh.PublicKey) session2.SessionID { + baseKey := session2.GenerateE2ESessionBaseKey(aliceKey, bobKey, group, alicePrivKey, bobPubKey) h, _ := hash.NewCMixHash() h.Write(baseKey.Bytes()) - sid := e2e.SessionID{} + sid := session2.SessionID{} copy(sid[:], h.Sum(nil)) diff --git a/network/interface.go b/network/interface.go index 4a11335e4742a069dccf88730b1571c4e2acc231..1d23002387d6c993c2d65bb153031132d99cd0cb 100644 --- a/network/interface.go +++ b/network/interface.go @@ -97,15 +97,21 @@ type Manager interface { // AddFingerprint - Adds a fingerprint which will be handled by a // specific processor for messages received by the given identity + // If a nil identity is passed, it will automatically use the default + // identity in the session AddFingerprint(identity *id.ID, fingerprint format.Fingerprint, mp message.Processor) error // DeleteFingerprint deletes a single fingerprint associated with the given // identity if it exists + // If a nil identity is passed, it will automatically use the default + // identity in the session DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint) // DeleteClientFingerprints deletes al fingerprint associated with the given // identity if it exists + // A sepecific identity must be supplied, a nil identity will result in a + // panic DeleteClientFingerprints(identity *id.ID) /* Service - predefined hash based tags appended to all cMix messages diff --git a/network/manager.go b/network/manager.go index d7ccd6372a8d9c433c81c351ed656df89d4966e8..555b60105aa76c109faed58c1dd073c52bea61f9 100644 --- a/network/manager.go +++ b/network/manager.go @@ -149,7 +149,8 @@ func NewManager(params Params, comms *client.Comms, session storage.Session, m.Retriever = historical.NewRetriever(params.Historical, comms, m.Sender, events) //Set up Message Handler - m.Handler = message.NewHandler(params.Message, m.session.GetKV(), m.events) + m.Handler = message.NewHandler(params.Message, m.session.GetKV(), m.events, + m.session.GetReceptionID()) //set up round handler m.Pickup = rounds.NewPickup(params.Rounds, m.Handler.GetMessageReceptionChannel(), diff --git a/network/message/fingerprints.go b/network/message/fingerprints.go index d79f865615ead3490c5eb373f5fc72a9bd3bea64..7a734f2f43a285b86e56694623afa37a9343af79 100644 --- a/network/message/fingerprints.go +++ b/network/message/fingerprints.go @@ -18,14 +18,16 @@ import ( // FingerprintsManager is a thread-safe map, mapping format.Fingerprint's to a // Handler object. type FingerprintsManager struct { - fpMap map[id.ID]map[format.Fingerprint]Processor + fpMap map[id.ID]map[format.Fingerprint]Processor + standardID *id.ID sync.Mutex } // newFingerprints is a constructor function for the fingerprints tracker. -func newFingerprints() *FingerprintsManager { +func newFingerprints(standardID *id.ID) *FingerprintsManager { return &FingerprintsManager{ - fpMap: make(map[id.ID]map[format.Fingerprint]Processor), + fpMap: make(map[id.ID]map[format.Fingerprint]Processor), + standardID: standardID, } } @@ -56,11 +58,17 @@ func (f *FingerprintsManager) pop(clientID *id.ID, // AddFingerprint maps the given fingerprint key to the handler value. If there // is already an entry for this fingerprint, the method returns with no write // operation. +// If a nil identity is passed, it will automatically use the default +// identity in the session func (f *FingerprintsManager) AddFingerprint(clientID *id.ID, fingerprint format.Fingerprint, mp Processor) error { f.Lock() defer f.Unlock() + if clientID == nil { + clientID = f.standardID + } + cid := *clientID if _, exists := f.fpMap[cid]; !exists { @@ -83,6 +91,10 @@ func (f *FingerprintsManager) DeleteFingerprint(clientID *id.ID, f.Lock() defer f.Unlock() + if clientID == nil { + clientID = f.standardID + } + cid := *clientID if _, exists := f.fpMap[cid]; exists { diff --git a/network/message/fingerprints_test.go b/network/message/fingerprints_test.go index 66784d284c7e9456699eaa659144b5a6a3e78d14..873ef57a2f9c206f641b28f28f052b302f6fe410 100644 --- a/network/message/fingerprints_test.go +++ b/network/message/fingerprints_test.go @@ -24,7 +24,7 @@ func Test_newFingerprints(t *testing.T) { fpMap: make(map[id.ID]map[format.Fingerprint]Processor), } - received := newFingerprints() + received := newFingerprints(&id.ID{}) if !reflect.DeepEqual(expected, received) { t.Fatalf("New FingerprintsManager did not match expected."+ "\nexpected: %+v\nreceived: %+v", expected, received) @@ -34,7 +34,7 @@ func Test_newFingerprints(t *testing.T) { // Unit test. func TestFingerprintsManager_pop(t *testing.T) { // Construct fingerprint map - fpTracker := newFingerprints() + fpTracker := newFingerprints(&id.ID{}) // Construct fingerprint and handler values cid := id.NewIdFromString("clientID", id.User, t) @@ -66,7 +66,7 @@ func TestFingerprintsManager_pop(t *testing.T) { // Unit test. func TestFingerprintsManager_AddFingerprint(t *testing.T) { // Construct fingerprint map - fpTracker := newFingerprints() + fpTracker := newFingerprints(&id.ID{}) // Construct fingerprint and handler values cid := id.NewIdFromString("clientID", id.User, t) @@ -97,7 +97,7 @@ func TestFingerprintsManager_AddFingerprint(t *testing.T) { func TestFingerprintsManager_DeleteFingerprint(t *testing.T) { // Construct fingerprint map - fpTracker := newFingerprints() + fpTracker := newFingerprints(&id.ID{}) // Construct fingerprint and handler values cid := id.NewIdFromString("clientID", id.User, t) @@ -123,7 +123,7 @@ func TestFingerprintsManager_DeleteFingerprint(t *testing.T) { // Unit test. func TestFingerprintsManager_DeleteClientFingerprints(t *testing.T) { // Construct fingerprints map - fpTracker := newFingerprints() + fpTracker := newFingerprints(&id.ID{}) // Construct slices of fingerprints and processors numTests := 100 diff --git a/network/message/handler.go b/network/message/handler.go index 75728fc6a22b5b73e15f723af47051e2ef0f1bd0..687f68544c3413f452e9deda1b77d18515995f72 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -74,13 +74,13 @@ func (p *handler) handleMessage(ecrMsg format.Message, bundle Bundle) bool { return true } - triggers, exists := p.get( + services, exists := p.get( identity.Source, ecrMsg.GetSIH(), ecrMsg.GetContents()) if exists { - for _, t := range triggers { + for _, t := range services { go t.Process(ecrMsg, identity, round) } - if len(triggers) == 0 { + if len(services) == 0 { jww.ERROR.Printf("empty service list for %s", ecrMsg.GetSIH()) } return true diff --git a/network/message/pickup.go b/network/message/pickup.go index 4119e720465d4a9891a89b98cf3e13b7e6bb615a..acba1c0382c1190c8f7524dbdba40852dfa7e415 100644 --- a/network/message/pickup.go +++ b/network/message/pickup.go @@ -53,7 +53,8 @@ type handler struct { ServicesManager } -func NewHandler(param Params, kv *versioned.KV, events event.Manager) Handler { +func NewHandler(param Params, kv *versioned.KV, events event.Manager, + standardID *id.ID) Handler { garbled, err := NewOrLoadMeteredCmixMessageBuffer(kv, inProcessKey) if err != nil { @@ -69,7 +70,7 @@ func NewHandler(param Params, kv *versioned.KV, events event.Manager) Handler { events: events, } - m.FingerprintsManager = *newFingerprints() + m.FingerprintsManager = *newFingerprints(standardID) m.ServicesManager = *NewServices() return &m } diff --git a/network/nodes/mixCypher.go b/network/nodes/mixCypher.go index c94b8007394c388c0423cada55cf7fdb7e0fbc2e..730212defe1ac6f8a2104ba0a1bea1185ddc2c0d 100644 --- a/network/nodes/mixCypher.go +++ b/network/nodes/mixCypher.go @@ -19,7 +19,7 @@ import ( type MixCypher interface { Encrypt(msg format.Message, salt []byte, roundID id.Round) (format.Message, [][]byte) - MakeClientGatewayKey(salt, digest []byte) []byte + MakeClientGatewayAuthMAC(salt, digest []byte) []byte } type mixCypher struct { @@ -56,7 +56,7 @@ func (mc *mixCypher) Encrypt(msg format.Message, return ecrMsg, KMAC } -func (mc *mixCypher) MakeClientGatewayKey(salt, digest []byte) []byte { +func (mc *mixCypher) MakeClientGatewayAuthMAC(salt, digest []byte) []byte { clientGatewayKey := cmix.GenerateClientGatewayKey(mc.keys[0].k) h, _ := hash.NewCMixHash() h.Write(clientGatewayKey) diff --git a/network/sendCmixUtils.go b/network/sendCmixUtils.go index 18c629e7fde1ab59cb146319f3e566e68655ddb1..0d0f89094b005d60529b81b5caf8254b0590cad1 100644 --- a/network/sendCmixUtils.go +++ b/network/sendCmixUtils.go @@ -160,7 +160,7 @@ func buildSlotMessage(msg format.Message, recipient *id.ID, target *id.ID, } // Add the mac proving ownership - slot.MAC = mixCrypt.MakeClientGatewayKey(salt, + slot.MAC = mixCrypt.MakeClientGatewayAuthMAC(salt, network.GenerateSlotDigest(slot)) return slot, encMsg, ephID, nil