diff --git a/api/client.go b/api/client.go index 257373d4c243e35ad4d7229a151cfbee8131d35d..3f4623c5af5179a02fc8ce368306c2f54974d0b4 100644 --- a/api/client.go +++ b/api/client.go @@ -25,7 +25,6 @@ import ( "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/comms/client" - cryptoBackup "gitlab.com/elixxir/crypto/backup" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/primitives/version" @@ -74,18 +73,18 @@ func NewClient(ndfJSON, storageDir string, password []byte, rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) - def, err := parseNDF(ndfJSON) + def, err := ParseNDF(ndfJSON) if err != nil { return err } - cmixGrp, e2eGrp := decodeGroups(def) + cmixGrp, e2eGrp := DecodeGroups(def) start := netTime.Now() protoUser := createNewUser(rngStreamGen) jww.DEBUG.Printf("PortableUserInfo generation took: %s", netTime.Now().Sub(start)) - _, err = checkVersionAndSetupStorage(def, storageDir, password, + _, err = CheckVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, registrationCode) if err != nil { return err @@ -107,16 +106,16 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, csprng.NewSystemRNG) rngStream := rngStreamGen.GetStream() - def, err := parseNDF(ndfJSON) + def, err := ParseNDF(ndfJSON) if err != nil { return err } - cmixGrp, e2eGrp := decodeGroups(def) + cmixGrp, e2eGrp := DecodeGroups(def) protoUser := createNewVanityUser(rngStream, cmixGrp, e2eGrp, userIdPrefix) - _, err = checkVersionAndSetupStorage(def, storageDir, password, + _, err = CheckVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, registrationCode) if err != nil { return err @@ -125,53 +124,6 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, return nil } -// NewClientFromBackup constructs a new Client from an encrypted -// backup. The backup is decrypted using the backupPassphrase. On -// success a successful client creation, the function will return a -// JSON encoded list of the E2E partners contained in the backup and a -// json-encoded string containing parameters stored in the backup -func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, - backupPassphrase []byte, backupFileContents []byte) ([]*id.ID, - string, error) { - - backUp := &cryptoBackup.Backup{} - err := backUp.Decrypt(string(backupPassphrase), backupFileContents) - if err != nil { - return nil, "", errors.WithMessage(err, - "Failed to unmarshal decrypted client contents.") - } - - usr := user.NewUserFromBackup(backUp) - - def, err := parseNDF(ndfJSON) - if err != nil { - return nil, "", err - } - - cmixGrp, e2eGrp := decodeGroups(def) - - // Note we do not need registration here - storageSess, err := checkVersionAndSetupStorage(def, storageDir, - []byte(sessionPassword), usr, cmixGrp, e2eGrp, - backUp.RegistrationCode) - - storageSess.SetReceptionRegistrationValidationSignature( - backUp.ReceptionIdentity.RegistrarSignature) - storageSess.SetTransmissionRegistrationValidationSignature( - backUp.TransmissionIdentity.RegistrarSignature) - storageSess.SetRegistrationTimestamp(backUp.RegistrationTimestamp) - - //move the registration state to indicate registered with - // registration on proto client - err = storageSess.ForwardRegistrationStatus( - storage.PermissioningComplete) - if err != nil { - return nil, "", err - } - - return backUp.Contacts.Identities, backUp.JSONParams, nil -} - // OpenClient session, but don't connect to the network or log in func OpenClient(storageDir string, password []byte, parameters Params) (*Client, error) { @@ -224,12 +176,12 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password, protoClientJSON []byte) error { jww.INFO.Printf("NewProtoClient_Unsafe") - def, err := parseNDF(ndfJSON) + def, err := ParseNDF(ndfJSON) if err != nil { return err } - cmixGrp, e2eGrp := decodeGroups(def) + cmixGrp, e2eGrp := DecodeGroups(def) protoUser := &user.Proto{} err = json.Unmarshal(protoClientJSON, protoUser) @@ -239,7 +191,7 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password, usr := user.NewUserFromProto(protoUser) - storageSess, err := checkVersionAndSetupStorage(def, storageDir, + storageSess, err := CheckVersionAndSetupStorage(def, storageDir, password, usr, cmixGrp, e2eGrp, protoUser.RegCode) if err != nil { return err @@ -325,7 +277,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, params Params) (*Client, error) { jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()") - def, err := parseNDF(newBaseNdf) + def, err := ParseNDF(newBaseNdf) if err != nil { return nil, err } @@ -370,7 +322,7 @@ func LoginWithProtoClient(storageDir string, password []byte, params Params) (*Client, error) { jww.INFO.Printf("LoginWithProtoClient()") - def, err := parseNDF(newBaseNdf) + def, err := ParseNDF(newBaseNdf) if err != nil { return nil, err } @@ -689,9 +641,9 @@ func (c *Client) GetPreferredBins(countryCode string) ([]string, error) { } // ----- Utility Functions ----- -// parseNDF parses the initial ndf string for the client. do not check the +// ParseNDF parses the initial ndf string for the client. do not check the // signature, it is deprecated. -func parseNDF(ndfString string) (*ndf.NetworkDefinition, error) { +func ParseNDF(ndfString string) (*ndf.NetworkDefinition, error) { if ndfString == "" { return nil, errors.New("ndf file empty") } @@ -704,8 +656,8 @@ func parseNDF(ndfString string) (*ndf.NetworkDefinition, error) { return netDef, nil } -// decodeGroups returns the e2e and cmix groups from the ndf -func decodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { +// DecodeGroups returns the e2e and cmix groups from the ndf +func DecodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { largeIntBits := 16 //Generate the cmix group @@ -720,10 +672,10 @@ func decodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { return cmixGrp, e2eGrp } -// checkVersionAndSetupStorage is common code shared by NewClient, +// CheckVersionAndSetupStorage is common code shared by NewClient, // NewPrecannedClient and NewVanityClient it checks client version and // creates a new storage for user data -func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, +func CheckVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, password []byte, protoUser user.Info, cmixGrp, e2eGrp *cyclic.Group, registrationCode string) ( storage.Session, error) { diff --git a/api/messenger/messenger.go b/api/messenger/messenger.go index 901d458c602a25722257497865f4b6ecc0d29f1f..2677e6fbaf23270e7eb6fc6009266da1638eaade 100644 --- a/api/messenger/messenger.go +++ b/api/messenger/messenger.go @@ -69,11 +69,20 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) { //generate the key var privkey *cyclic.Int if client.GetStorage().IsPrecanned() { - precannedID := binary.BigEndian.Uint64(client.GetStorage().GetReceptionID()[:]) - privkey = generatePrecanDHKeypair(uint(precannedID), client.GetStorage().GetE2EGroup()) + jww.WARN.Printf("Using Precanned DH key") + precannedID := binary.BigEndian.Uint64( + client.GetStorage().GetReceptionID()[:]) + privkey = generatePrecanDHKeypair( + uint(precannedID), + client.GetStorage().GetE2EGroup()) + } else if usr.E2eDhPrivateKey != nil { + jww.INFO.Printf("Using pre-existing DH key") + privkey = usr.E2eDhPrivateKey } else { + jww.INFO.Printf("Generating new DH key") rngStream := client.GetRng().GetStream() - privkey = diffieHellman.GeneratePrivateKey(len(e2eGrp.GetPBytes()), + privkey = diffieHellman.GeneratePrivateKey( + len(e2eGrp.GetPBytes()), e2eGrp, rngStream) rngStream.Close() } diff --git a/api/precan.go b/api/precan.go index eaa471e9ee963a41d493c2a0452c762bb072fa1e..150d90fa9a806db81277fe9677a9a6ecc13e64dc 100644 --- a/api/precan.go +++ b/api/precan.go @@ -9,6 +9,7 @@ package api import ( "encoding/binary" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/user" @@ -59,15 +60,15 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, csprng.NewSystemRNG) rngStream := rngStreamGen.GetStream() - def, err := parseNDF(defJSON) + def, err := ParseNDF(defJSON) if err != nil { return err } - cmixGrp, e2eGrp := decodeGroups(def) + cmixGrp, e2eGrp := DecodeGroups(def) protoUser := CreatePrecannedUser(precannedID, rngStream) - store, err := checkVersionAndSetupStorage(def, storageDir, password, + store, err := CheckVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, "") if err != nil { return err @@ -81,4 +82,4 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, } return nil -} \ No newline at end of file +} diff --git a/cmd/root.go b/cmd/root.go index 1237e52678dcac1e7051a0b88bbe51f08478a8f2..7d8733e1dca001782df6579acd22d2a4dc355093 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -560,8 +560,11 @@ func createClient() *api.Client { } // Construct client from backup data - backupIdList, _, err := api.NewClientFromBackup(string(ndfJSON), storeDir, + backupIdList, _, err := messenger.NewClientFromBackup(string(ndfJSON), storeDir, pass, backupPass, backupFile) + if err != nil { + jww.FATAL.Panicf("%+v", err) + } backupIdListPath := viper.GetString("backupIdList") if backupIdListPath != "" { diff --git a/ud/manager.go b/ud/manager.go index 9d60515e5995059eb4926e6ef33384a69e6a0347..3cd1b679a3586248c14f8608eb31cddb2e1f43e7 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -2,6 +2,9 @@ package ud import ( "fmt" + "sync" + "time" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" @@ -13,8 +16,6 @@ import ( "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" - "sync" - "time" ) const ( @@ -116,7 +117,7 @@ func NewManager(services CMix, e2e E2E, } // Set storage to registered - if err = m.setRegistered(); err != nil && m.events != nil { + if err = setRegistered(kv); err != nil && m.events != nil { m.events.Report(1, "UserDiscovery", "Registration", fmt.Sprintf("User Registered with UD: %+v", username)) @@ -163,6 +164,13 @@ func NewManagerFromBackup(services CMix, "from backup") } + // Set as registered. Since it's from a backup, + // the client is already registered + if err = setRegistered(kv); err != nil { + return nil, errors.WithMessage(err, "failed to set client as "+ + "registered with user discovery.") + } + // Create the user discovery host object _, err = m.getOrAddUdHost() if err != nil { @@ -170,14 +178,33 @@ func NewManagerFromBackup(services CMix, "not be constructed.") } + return m, nil +} + +// InitStoreFromBackup initializes the UD storage from the backup subsystem +func InitStoreFromBackup(kv *versioned.KV, + username, email, phone fact.Fact) error { + // Initialize our store + udStore, err := store.NewOrLoadStore(kv) + if err != nil { + return err + } + + // Put any passed in missing facts into store + err = udStore.BackUpMissingFacts(email, phone) + if err != nil { + return errors.WithMessage(err, "Failed to restore UD store "+ + "from backup") + } + // Set as registered. Since it's from a backup, // the client is already registered - if err = m.setRegistered(); err != nil { - return nil, errors.WithMessage(err, "failed to set client as "+ + if err = setRegistered(kv); err != nil { + return errors.WithMessage(err, "failed to set client as "+ "registered with user discovery.") } - return m, nil + return nil } // LoadManager loads the state of the Manager diff --git a/ud/registered.go b/ud/registered.go index 47104cc2f56315fcbe11dbf925f7d415f2dbf132..71eab2a4e71ede3019c866c261dd818e325ebdaa 100644 --- a/ud/registered.go +++ b/ud/registered.go @@ -2,6 +2,7 @@ package ud import ( "encoding/binary" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/netTime" @@ -21,8 +22,8 @@ func (m *Manager) isRegistered() bool { return true } -// isRegistered returns if the client is registered with user discovery -func (m *Manager) setRegistered() error { +// setRegistered sets the user to registered +func setRegistered(kv *versioned.KV) error { data := make([]byte, 4) binary.BigEndian.PutUint32(data, 1) obj := &versioned.Object{ @@ -31,7 +32,7 @@ func (m *Manager) setRegistered() error { Data: data, } - if err := m.kv.Set(isRegisteredKey, isRegisteredVersion, obj); err != nil { + if err := kv.Set(isRegisteredKey, isRegisteredVersion, obj); err != nil { jww.FATAL.Panicf("Failed to store that the client is "+ "registered: %+v", err) }