diff --git a/bindings/ud.go b/bindings/ud.go index df4d3c5bf2fa1ed27bad1ee66b7c9146862c4da9..a8dbb9e39cd692c4bec358ca2fbb50b8faacef80 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -96,7 +96,7 @@ func NewUserDiscoveryFromBackup(client *Client, jww.WARN.Printf("Loading manager without a registered phone number") } - m, err := ud.NewManagerFromBackup(&client.api, single, emailFact, phoneFact) + m, err := ud.NewManagerFromBackup(&client.api, single, phoneFact) if err != nil { return nil, errors.WithMessage(err, "Failed to create User Discovery Manager") } else { diff --git a/ud/addFact.go b/ud/addFact.go index d67fe0961a609a3707e731bfe388618ac07ea0b7..5139b0490060c2baaa1e0b0854733d727ba7b17b 100644 --- a/ud/addFact.go +++ b/ud/addFact.go @@ -21,7 +21,7 @@ import ( // called along with the code to finalize the fact. func (m *Manager) SendRegisterFact(f fact.Fact) (string, error) { jww.INFO.Printf("ud.SendRegisterFact(%s)", f.Stringify()) - return m.addFact(f, m.myID, m.comms) + return m.addFact(f, m.e2e.GetReceptionID(), m.comms) } func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, aFC addFactComms) (string, error) { @@ -42,7 +42,8 @@ func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, aFC addFactComms) (stri fHash := factID.Fingerprint(f) // Sign our inFact for putting into the request - fSig, err := rsa.Sign(rand.Reader, m.privKey, hash.CMixHash, fHash, nil) + privKey := m.user.PortableUserInfo().ReceptionRSA + fSig, err := rsa.Sign(rand.Reader, privKey, hash.CMixHash, fHash, nil) if err != nil { return "", err } diff --git a/ud/interfaces.go b/ud/interfaces.go new file mode 100644 index 0000000000000000000000000000000000000000..02d01f2159580699273b2e1e2d608700e2391ad5 --- /dev/null +++ b/ud/interfaces.go @@ -0,0 +1,26 @@ +package ud + +import ( + "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/interfaces/user" + "gitlab.com/elixxir/client/single" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/crypto/contact" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" +) + +type Userinfo interface { + PortableUserInfo() user.Info + GetUsername() (string, error) + GetReceptionRegistrationValidationSignature() []byte +} + +type SingleInterface interface { + TransmitRequest(recipient contact.Contact, tag string, payload []byte, + callback single.Response, param single.RequestParams, net cmix.Client, rng csprng.Source, + e2eGrp *cyclic.Group) (id.Round, receptionID.EphemeralIdentity, error) + StartProcesses() (stoppable.Stoppable, error) +} diff --git a/ud/lookup.go b/ud/lookup.go index 5ff0899f9f77efc19ae3cabe4b510759e452ab4c..5f64ab3de53e4469e78308f155ce208a2aa7c8d6 100644 --- a/ud/lookup.go +++ b/ud/lookup.go @@ -104,6 +104,8 @@ func lookup(services cmix.Client, callback single.Response, // will be passed into the callback. func (m *Manager) lookupResponseProcess(uid *id.ID, cb single.Response, payload []byte, err error) { + grp := m.e2e.GetGroup() + if err != nil { go cb.Callback(contact.Contact{}, errors.WithMessage(err, "Failed to lookup.")) return @@ -124,7 +126,7 @@ func (m *Manager) lookupResponseProcess(uid *id.ID, cb single.Response, c := contact.Contact{ ID: uid, - DhPubKey: m.grp.NewIntFromBytes(lookupResponse.PubKey), + DhPubKey: grp.NewIntFromBytes(lookupResponse.PubKey), } if lookupResponse.Username != "" { diff --git a/ud/manager.go b/ud/manager.go index 821718a58b2fdd29e3427e7c655f88e8288cf364..b5d8d4d7d5babd0ed183a0a84b8585463698114d 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -6,43 +6,21 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" "gitlab.com/elixxir/client/cmix" - "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/event" - "gitlab.com/elixxir/client/interfaces/user" - "gitlab.com/elixxir/client/single" - "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/versioned" + store "gitlab.com/elixxir/client/ud/store/ud" "gitlab.com/elixxir/comms/client" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/comms/connect" - "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "math" "time" ) -type SingleInterface interface { - TransmitRequest(recipient contact.Contact, tag string, payload []byte, - callback single.Response, param single.RequestParams, net cmix.Client, rng csprng.Source, - e2eGrp *cyclic.Group) (id.Round, receptionID.EphemeralIdentity, error) - StartProcesses() (stoppable.Stoppable, error) -} - -type Userinfo interface { - PortableUserInfo() user.Info - GetUsername() (string, error) - GetReceptionRegistrationValidationSignature() []byte -} - -const ( -// todo: populate with err messages -) - // todo: newuserDiscRegistratration, loadUserDiscRegistration // neworLoad? // fixme: search/lookup off ud object @@ -68,13 +46,6 @@ type Manager struct { kv *versioned.KV - // Loaded from external access - privKey *rsa.PrivateKey - grp *cyclic.Group - - // internal structures - myID *id.ID - // alternate User discovery service to circumvent production alternativeUd *alternateUd } @@ -90,9 +61,9 @@ type alternateUd struct { // NewManager builds a new user discovery manager. It requires that an updated // NDF is available and will error if one is not. // todo: docstring, organize the order of arguments in a meaningful way -func NewManager(services cmix.Client, e2e e2e.Handler, events event.Manager, - comms Comms, userStore Userinfo, rng *fastRNG.StreamGenerator, - privKey *rsa.PrivateKey, username string, +func NewManager(services cmix.Client, e2e e2e.Handler, + events event.Manager, comms Comms, userStore Userinfo, + rng *fastRNG.StreamGenerator, username string, kv *versioned.KV) (*Manager, error) { jww.INFO.Println("ud.NewManager()") @@ -114,9 +85,6 @@ func NewManager(services cmix.Client, e2e e2e.Handler, events event.Manager, comms: comms, rng: rng, store: udStore, - myID: e2e.GetReceptionID(), - grp: e2e.GetGroup(), - privKey: privKey, user: userStore, kv: kv, } @@ -129,13 +97,6 @@ func NewManager(services cmix.Client, e2e e2e.Handler, events event.Manager, "information, is there network access?: Cert not present.") } - // Pull user discovery ID from NDF - udID, err := id.Unmarshal(def.UDB.ID) - if err != nil { - return nil, errors.Errorf("failed to unmarshal UD ID "+ - "from NDF: %+v", err) - } - udHost, err := m.getOrAddUdHost() if err != nil { return nil, errors.WithMessage(err, "User Discovery host object could "+ @@ -162,36 +123,38 @@ func NewManager(services cmix.Client, e2e e2e.Handler, events event.Manager, // NewManagerFromBackup builds a new user discover manager from a backup. // It will construct a manager that is already registered and restore // already registered facts into store. -func NewManagerFromBackup(client *api.Client, single *single.Manager, - email, phone fact.Fact) (*Manager, error) { +func NewManagerFromBackup(services cmix.Client, e2e e2e.Handler, comms Comms, userStore Userinfo, rng *fastRNG.StreamGenerator, email, phone fact.Fact, kv *versioned.KV) (*Manager, error) { jww.INFO.Println("ud.NewManagerFromBackup()") if client.NetworkFollowerStatus() != api.Running { return nil, errors.New( - "cannot start UD Manager when network follower is not running.") + "cannot start UD Manager when " + + "network follower is not running.") } - registered := uint32(0) - m := &Manager{ - client: client, - comms: client.GetComms(), - rng: client.GetRng(), - sw: client.GetSwitchboard(), - storage: client.GetStorage(), - net: client.GetNetworkInterface(), - single: single, - registered: ®istered, + services: services, + e2e: e2e, + comms: comms, + user: userStore, + rng: rng, + kv: kv, } - err := m.client.GetStorage().GetUd(). - BackUpMissingFacts(email, phone) + udStore, err := store.NewOrLoadStore(kv) + if err != nil { + return nil, err + } + + m.store = udStore + + err = m.store.BackUpMissingFacts(email, phone) if err != nil { return nil, errors.WithMessage(err, "Failed to restore UD store "+ "from backup") } // check that user discovery is available in the NDF - def := m.net.GetInstance().GetPartialNdf().Get() + def := m.services.GetInstance().GetPartialNdf().Get() if def.UDB.Cert == "" { return nil, errors.New("NDF does not have User Discovery information, " + @@ -206,21 +169,14 @@ func NewManagerFromBackup(client *api.Client, single *single.Manager, hp.SendTimeout = 3 * time.Second hp.AuthEnabled = false - m.myID = m.storage.User().GetCryptographicIdentity().GetReceptionID() - - // Get the commonly used data from storage - m.privKey = m.storage.GetUser().ReceptionRSA - // Set as registered. Since it's from a backup, // the client is already registered + // todo: maybe we don't need this? if err = m.setRegistered(); err != nil { return nil, errors.WithMessage(err, "failed to set client as "+ "registered with user discovery.") } - // Store the pointer to the group locally for easy access - m.grp = m.storage.E2e().GetGroup() - return m, nil } @@ -235,7 +191,6 @@ func LoadManager(services cmix.Client, e2e e2e.Handler, events event.Manager, comms: comms, user: userStore, rng: rng, - privKey: privKey, kv: kv, } @@ -314,10 +269,11 @@ func (m *Manager) GetStringifiedFacts() []string { // GetContact returns the contact for UD as retrieved from the NDF. func (m *Manager) GetContact() (contact.Contact, error) { + grp := m.e2e.GetGroup() // Return alternative User discovery contact if set if m.alternativeUd != nil { // Unmarshal UD DH public key - alternativeDhPubKey := m.grp.NewInt(1) + alternativeDhPubKey := grp.NewInt(1) if err := alternativeDhPubKey. UnmarshalJSON(m.alternativeUd.dhPubKey); err != nil { return contact.Contact{}, @@ -343,7 +299,7 @@ func (m *Manager) GetContact() (contact.Contact, error) { } // Unmarshal UD DH public key - dhPubKey := m.grp.NewInt(1) + dhPubKey := grp.NewInt(1) if err = dhPubKey.UnmarshalJSON(netDef.UDB.DhPubKey); err != nil { return contact.Contact{}, errors.WithMessage(err, "Failed to unmarshal UD DH "+ diff --git a/ud/remove.go b/ud/remove.go index 973a997ad81aa440917cbeb9c94b240b916c82fc..29be3b90e4e8823d1df623fc678f2cc323b0c235 100644 --- a/ud/remove.go +++ b/ud/remove.go @@ -42,14 +42,15 @@ func (m *Manager) removeFact(f fact.Fact, fHash := factID.Fingerprint(f) // Sign our inFact for putting into the request - fSig, err := rsa.Sign(rand.Reader, m.privKey, hash.CMixHash, fHash, nil) + privKey := m.user.PortableUserInfo().ReceptionRSA + fSig, err := rsa.Sign(rand.Reader, privKey, hash.CMixHash, fHash, nil) if err != nil { return err } // Create our Fact Removal Request message data remFactMsg := mixmessages.FactRemovalRequest{ - UID: m.myID.Marshal(), + UID: m.e2e.GetReceptionID().Marshal(), RemovalData: &mmFact, FactSig: fSig, } @@ -77,8 +78,9 @@ func (m *Manager) RemoveUser(f fact.Fact) error { if err != nil { return err } + privKey := m.user.PortableUserInfo().ReceptionRSA - return removeUser(f, m.myID, m.privKey, m.comms, udHost) + return removeUser(f, m.e2e.GetReceptionID(), privKey, m.comms, udHost) } func removeUser(f fact.Fact, myId *id.ID, privateKey *rsa.PrivateKey, diff --git a/ud/search.go b/ud/search.go index 7cb6bc6d5209f5eca5fa031f7c532a1b39c6c76d..836278a66f33bde3a81069716c8be721996f770b 100644 --- a/ud/search.go +++ b/ud/search.go @@ -139,7 +139,7 @@ func hashFactList(list fact.FactList) ([]*HashFact, map[string]fact.Fact) { func (m *Manager) parseContacts(response []*Contact, hashMap map[string]fact.Fact) ([]contact.Contact, error) { contacts := make([]contact.Contact, len(response)) - + grp := m.e2e.GetGroup() // Convert each contact message into a new contact.Contact for i, c := range response { // Unmarshal user ID bytes @@ -154,7 +154,7 @@ func (m *Manager) parseContacts(response []*Contact, // Create new Contact contacts[i] = contact.Contact{ ID: uid, - DhPubKey: m.grp.NewIntFromBytes(c.PubKey), + DhPubKey: grp.NewIntFromBytes(c.PubKey), Facts: facts, }