diff --git a/backup/backupRestore.go b/backup/backupRestore.go index 91950ce8ad8912a50cadbf0d3aa60051e17a4c1a..94e1180ae0d5a993d4d13ca63854e6b690885e1c 100644 --- a/backup/backupRestore.go +++ b/backup/backupRestore.go @@ -8,6 +8,7 @@ package backup import ( "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/rekey" "gitlab.com/elixxir/client/storage" @@ -35,6 +36,9 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, "Failed to unmarshal decrypted client contents.") } + jww.INFO.Printf("Decrypted backup ID to Restore: %v", + backUp.ReceptionIdentity.ComputedID) + userInfo := user.NewUserFromBackup(backUp) def, err := xxdk.ParseNDF(ndfJSON) diff --git a/bindings/e2e.go b/bindings/e2e.go index 6edf2a9ff5d070bafcb32cee0a22c7e1a9977dc5..c2ddab490032145b15675d191c0a0fceaab9dda4 100644 --- a/bindings/e2e.go +++ b/bindings/e2e.go @@ -117,41 +117,6 @@ func LoginE2eEphemeral(cmixId int, callbacks AuthCallbacks, identity, return e2eTrackerSingleton.make(newE2e), nil } -// LoginE2eLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV -// Uses the pre-generated transmission ID used by xxdk.Cmix -// If callbacks is left nil, a default auth.Callbacks will be used -// This function is designed to maintain backwards compatibility with previous xx messenger designs -// and should not be used for other purposes -func LoginE2eLegacy(cmixId int, callbacks AuthCallbacks, e2eParamsJSON []byte) (*E2e, error) { - if len(e2eParamsJSON) == 0 { - jww.WARN.Printf("e2e params not specified, using defaults...") - e2eParamsJSON = GetDefaultE2EParams() - } - - cmix, err := cmixTrackerSingleton.get(cmixId) - if err != nil { - return nil, err - } - - var authCallbacks xxdk.AuthCallbacks - if callbacks == nil { - authCallbacks = xxdk.DefaultAuthCallbacks{} - } else { - authCallbacks = &authCallback{bindingsCbs: callbacks} - } - - params, err := parseE2EParams(e2eParamsJSON) - if err != nil { - return nil, err - } - - newE2e, err := xxdk.LoginLegacy(cmix.api, params, authCallbacks) - if err != nil { - return nil, err - } - return e2eTrackerSingleton.make(newE2e), nil -} - // GetContact returns a marshalled contact.Contact object for the E2e ReceptionIdentity func (e *E2e) GetContact() []byte { return e.api.GetReceptionIdentity().GetContact().Marshal() diff --git a/bindings/identity.go b/bindings/identity.go index b17e45d5eccbc5299e0b24374d87686312e53c5b..39665ca28bd5f90584f63ecf561733e7d886c106 100644 --- a/bindings/identity.go +++ b/bindings/identity.go @@ -42,6 +42,16 @@ func (c *Cmix) MakeIdentity() ([]byte, error) { return ident.Marshal() } +// MakeLegacyIdentity generates the legacy identity for receiving messages +func (c *Cmix) MakeLegacyIdentity() ([]byte, error) { + ident, err := xxdk.MakeLegacyReceptionIdentity(c.api) + if err != nil { + return nil, err + } + + return ident.Marshal() +} + // GetIDFromContact accepts a marshalled contact.Contact object & returns a marshalled id.ID object func GetIDFromContact(marshaled []byte) ([]byte, error) { cnt, err := contact.Unmarshal(marshaled) diff --git a/cmd/backup.go b/cmd/backup.go index 5a2091a49c97a891eff87a6b6b959b4eb8d600eb..faabf16661b45b783a6c11a6ff8f9438b02b1ac5 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -8,6 +8,10 @@ package cmd import ( "encoding/json" + "io/fs" + "io/ioutil" + "os" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" @@ -15,18 +19,16 @@ import ( "gitlab.com/elixxir/client/xxdk" backupCrypto "gitlab.com/elixxir/crypto/backup" "gitlab.com/xx_network/primitives/utils" - "io/fs" - "io/ioutil" - "os" ) // loadOrInitBackup will build a new xxdk.E2e from existing storage // or from a new storage that it will create if none already exists func loadOrInitBackup(backupPath string, backupPass string, password []byte, storeDir string, cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { + jww.INFO.Printf("Using Backup sender") // create a new client if none exist - var baseClient *xxdk.Cmix + var net *xxdk.Cmix var identity xxdk.ReceptionIdentity if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { // Initialize from scratch @@ -72,39 +74,37 @@ func loadOrInitBackup(backupPath string, backupPass string, password []byte, sto } } - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - // TODO: Get proper identity - identity, err = xxdk.MakeReceptionIdentity(baseClient) + identity, err = xxdk.MakeLegacyReceptionIdentity(net) if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } else { // Initialize from storage - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient) + identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } - jww.INFO.Printf("Using LoginLegacy for precan sender") - client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs) + messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - return client + return messenger } func loadBackup(backupPath, backupPass string) (backupCrypto.Backup, []byte) { diff --git a/cmd/callbacks.go b/cmd/callbacks.go index 4be99e0d0b6c7521d34cdd4cfa7e9ac90a763dbe..ec6bf4cd1760e009c9477b0d845d7a228c5f9e6f 100644 --- a/cmd/callbacks.go +++ b/cmd/callbacks.go @@ -40,7 +40,7 @@ func makeAuthCallbacks(autoConfirm bool, params xxdk.E2EParams) *authCallbacks { func (a *authCallbacks) Request(requestor contact.Contact, receptionID receptionID.EphemeralIdentity, - round rounds.Round, client *xxdk.E2e) { + round rounds.Round, messenger *xxdk.E2e) { msg := fmt.Sprintf("Authentication channel request from: %s\n", requestor.ID) jww.INFO.Printf(msg) @@ -49,9 +49,9 @@ func (a *authCallbacks) Request(requestor contact.Contact, jww.INFO.Printf("Channel Request: %s", requestor.ID) if viper.GetBool("verify-sends") { // Verify message sends were successful - acceptChannelVerified(client, requestor.ID, a.params) + acceptChannelVerified(messenger, requestor.ID, a.params) } else { - acceptChannel(client, requestor.ID) + acceptChannel(messenger, requestor.ID) } a.confCh <- requestor.ID @@ -60,15 +60,15 @@ func (a *authCallbacks) Request(requestor contact.Contact, } func (a *authCallbacks) Confirm(requestor contact.Contact, - receptionID receptionID.EphemeralIdentity, - round rounds.Round, client *xxdk.E2e) { + _ receptionID.EphemeralIdentity, + _ rounds.Round, _ *xxdk.E2e) { jww.INFO.Printf("Channel Confirmed: %s", requestor.ID) a.confCh <- requestor.ID } func (a *authCallbacks) Reset(requestor contact.Contact, - receptionID receptionID.EphemeralIdentity, - round rounds.Round, client *xxdk.E2e) { + _ receptionID.EphemeralIdentity, + _ rounds.Round, _ *xxdk.E2e) { msg := fmt.Sprintf("Authentication channel reset from: %s\n", requestor.ID) jww.INFO.Printf(msg) diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go index eb9b7f34e441b078db012e114b3abc45f00154a3..20e8968bf9e4e2ef69556ad7cd1459984c07bee9 100644 --- a/cmd/fileTransfer.go +++ b/cmd/fileTransfer.go @@ -132,7 +132,7 @@ type receivedFtResults struct { // initFileTransferManager creates a new file transfer manager with a new // reception callback. Returns the file transfer manager and the channel that // will be triggered when the callback is called. -func initFileTransferManager(client *xxdk.E2e, maxThroughput int) ( +func initFileTransferManager(messenger *xxdk.E2e, maxThroughput int) ( *ftE2e.Wrapper, chan receivedFtResults) { // Create interfaces.ReceiveCallback that returns the results on a channel @@ -152,24 +152,24 @@ func initFileTransferManager(client *xxdk.E2e, maxThroughput int) ( // Create new manager manager, err := ft.NewManager(p, - client.GetReceptionIdentity().ID, - client.GetCmix(), - client.GetStorage(), - client.GetRng()) + messenger.GetReceptionIdentity().ID, + messenger.GetCmix(), + messenger.GetStorage(), + messenger.GetRng()) if err != nil { jww.FATAL.Panicf( "[FT] Failed to create new file transfer manager: %+v", err) } // Start the file transfer sending and receiving threads - err = client.AddService(manager.StartProcesses) + err = messenger.AddService(manager.StartProcesses) if err != nil { jww.FATAL.Panicf("[FT] Failed to start file transfer threads: %+v", err) } e2eParams := ftE2e.DefaultParams() e2eFt, err := ftE2e.NewWrapper(receiveCB, e2eParams, manager, - client.GetReceptionIdentity().ID, client.GetE2E(), client.GetCmix()) + messenger.GetReceptionIdentity().ID, messenger.GetE2E(), messenger.GetCmix()) if err != nil { jww.FATAL.Panicf( "[FT] Failed to create new e2e file transfer wrapper: %+v", err) diff --git a/cmd/group.go b/cmd/group.go index 3045e71b328bc51dc71fd30364398e761c7170b3..8909d2214812729af586dd75e7a6f342e01d18f0 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -116,7 +116,7 @@ var groupCmd = &cobra.Command{ // initGroupManager creates a new group chat manager and starts the process // service. -func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat, +func initGroupManager(messenger *xxdk.E2e) (groupChat.GroupChat, chan groupChat.MessageReceive, chan groupStore.Group) { recChan := make(chan groupChat.MessageReceive, 10) @@ -126,10 +126,10 @@ func initGroupManager(client *xxdk.E2e) (groupChat.GroupChat, } jww.INFO.Print("[GC] Creating new group manager.") - manager, err := groupChat.NewManager(client.GetCmix(), - client.GetE2E(), client.GetStorage().GetReceptionID(), - client.GetRng(), client.GetStorage().GetE2EGroup(), - client.GetStorage().GetKV(), requestCb, &receiveProcessor{recChan}) + manager, err := groupChat.NewManager(messenger.GetCmix(), + messenger.GetE2E(), messenger.GetStorage().GetReceptionID(), + messenger.GetRng(), messenger.GetStorage().GetE2EGroup(), + messenger.GetStorage().GetKV(), requestCb, &receiveProcessor{recChan}) if err != nil { jww.FATAL.Panicf("[GC] Failed to initialize group chat manager: %+v", err) } diff --git a/cmd/init.go b/cmd/init.go index 9028bcff711a7c77738e42b39022b0ea122af0a8..a126e95e983a99de5693a525dc11b8a25405d8cb 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -9,14 +9,17 @@ package cmd import ( + "fmt" + + "io/fs" + "io/ioutil" + "os" + "github.com/pkg/errors" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" "gitlab.com/elixxir/client/xxdk" - "io/fs" - "io/ioutil" - "os" ) // initCmd creates a new user object with the given NDF @@ -37,23 +40,26 @@ var initCmd = &cobra.Command{ } err = xxdk.NewCmix(string(ndfJson), storeDir, storePassword, regCode) - baseClient, err := xxdk.OpenCmix(storeDir, storePassword) + net, err := xxdk.OpenCmix(storeDir, storePassword) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err := xxdk.MakeReceptionIdentity(baseClient) + identity, err := xxdk.MakeReceptionIdentity(net) if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } jww.INFO.Printf("User: %s", identity.ID) writeContact(identity.GetContact()) + + // NOTE: DO NOT REMOVE THIS LINE. YOU WILL BREAK INTEGRATION + fmt.Printf("%s\n", identity.ID) }, } @@ -65,13 +71,14 @@ func init() { rootCmd.AddCommand(initCmd) } -// loadOrInitClient will build a new xxdk.E2e from existing storage +// loadOrInitMessenger will build a new xxdk.E2e from existing storage // or from a new storage that it will create if none already exists -func loadOrInitClient(password []byte, storeDir, regCode string, +func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string, cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { + jww.INFO.Printf("Using normal sender") // create a new client if none exist - var baseClient *xxdk.Cmix + var net *xxdk.Cmix var identity xxdk.ReceptionIdentity if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { // Initialize from scratch @@ -81,50 +88,55 @@ func loadOrInitClient(password []byte, storeDir, regCode string, } err = xxdk.NewCmix(string(ndfJson), storeDir, password, regCode) - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.MakeReceptionIdentity(baseClient) + if forceLegacy { + jww.INFO.Printf("Forcing legacy sender") + identity, err = xxdk.MakeLegacyReceptionIdentity(net) + } else { + identity, err = xxdk.MakeReceptionIdentity(net) + } if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } else { // Initialize from storage - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient) + identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } - jww.INFO.Printf("Using Login for normal sender") - client, err := xxdk.Login(baseClient, authCbs, identity, e2eParams) + messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - return client + return messenger } // loadOrInitVanity will build a new xxdk.E2e from existing storage // or from a new storage that it will create if none already exists func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string, cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { + jww.INFO.Printf("Using Vanity sender") // create a new client if none exist - var baseClient *xxdk.Cmix + var net *xxdk.Cmix var identity xxdk.ReceptionIdentity if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { - // Initialize precan from scratch + // Initialize from scratch ndfJson, err := ioutil.ReadFile(viper.GetString("ndf")) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -132,37 +144,35 @@ func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string, err = xxdk.NewVanityClient(string(ndfJson), storeDir, password, regCode, userIdPrefix) - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - // TODO: Get proper identity - identity, err = xxdk.MakeReceptionIdentity(baseClient) + identity, err = xxdk.MakeLegacyReceptionIdentity(net) if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } else { - // Initialize precan from storage - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + // Initialize from storage + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient) + identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } - jww.INFO.Printf("Using LoginLegacy for vanity sender") - client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs) + messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - return client + return messenger } diff --git a/cmd/precan.go b/cmd/precan.go index 9b3a35f2fcace0fd4367e654e4f5689a37839d32..dded07723871e34ba54065ab628a346b055603a0 100644 --- a/cmd/precan.go +++ b/cmd/precan.go @@ -25,9 +25,10 @@ import ( // or from a new storage that it will create if none already exists func loadOrInitPrecan(precanId uint, password []byte, storeDir string, cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { + jww.INFO.Printf("Using Precanned sender") // create a new client if none exist - var baseClient *xxdk.Cmix + var net *xxdk.Cmix var identity xxdk.ReceptionIdentity if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { // Initialize from scratch @@ -36,35 +37,38 @@ func loadOrInitPrecan(precanId uint, password []byte, storeDir string, jww.FATAL.Panicf("%+v", err) } - // TODO: Separate identity from this call - identity, err = xxdk.NewPrecannedClient(precanId, string(ndfJson), storeDir, password) - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + err = xxdk.NewPrecannedClient(precanId, string(ndfJson), storeDir, password) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + identity, err = xxdk.MakeLegacyReceptionIdentity(net) + if err != nil { + return nil + } + + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } else { // Initialize from storage - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient) + identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } - jww.INFO.Printf("Using LoginLegacy for precan sender") - client, err := xxdk.LoginLegacy(baseClient, e2eParams, authCbs) + messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - return client + return messenger } func isPrecanID(id *id.ID) bool { @@ -85,10 +89,10 @@ func getPrecanID(recipientID *id.ID) uint { return uint(recipientID.Bytes()[7]) } -func addPrecanAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, +func addPrecanAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID, recipient contact.Contact) { jww.WARN.Printf("Precanned user id detected: %s", recipientID) - preUsr, err := client.MakePrecannedAuthenticatedChannel( + preUsr, err := messenger.MakePrecannedAuthenticatedChannel( getPrecanID(recipientID)) if err != nil { jww.FATAL.Panicf("%+v", err) diff --git a/cmd/proto.go b/cmd/proto.go index 3d2568e16d567dd4b97195cc5314e54be46a61f9..bdb5b0855d764a077b1ac47d329bcffc29b2ff8b 100644 --- a/cmd/proto.go +++ b/cmd/proto.go @@ -23,9 +23,10 @@ import ( // or from a new storage that it will create if none already exists func loadOrInitProto(protoUserPath string, password []byte, storeDir string, cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { + jww.INFO.Printf("Using Proto sender") // create a new client if none exist - var baseClient *xxdk.Cmix + var net *xxdk.Cmix var identity xxdk.ReceptionIdentity if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { // Initialize from scratch @@ -45,34 +46,36 @@ func loadOrInitProto(protoUserPath string, password []byte, storeDir string, jww.FATAL.Panicf("%v", err) } - // TODO: Separate identity from this call - identity, err = xxdk.NewProtoClient_Unsafe(string(ndfJson), storeDir, + err = xxdk.NewProtoClient_Unsafe(string(ndfJson), storeDir, password, protoUser) - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient) + identity, err = xxdk.MakeLegacyReceptionIdentity(net) + if err != nil { + return nil + } + + err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } else { // Initialize from storage - baseClient, err = xxdk.LoadCmix(storeDir, password, cmixParams) + net, err = xxdk.LoadCmix(storeDir, password, cmixParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, baseClient) + identity, err = xxdk.LoadReceptionIdentity(identityStorageKey, net) if err != nil { jww.FATAL.Panicf("%+v", err) } } - - jww.INFO.Printf("Using Login for proto sender") - client, err := xxdk.Login(baseClient, authCbs, identity, e2eParams) + messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) if err != nil { jww.FATAL.Panicf("%+v", err) } - return client + return messenger } diff --git a/cmd/root.go b/cmd/root.go index 59c83e81871ab52418cd8d5703830df926768d03..4b360c8d188b767768548bf2d2904a46a1f0d5db 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -585,6 +585,7 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { storePassword := parsePassword(viper.GetString("password")) storeDir := viper.GetString("session") regCode := viper.GetString("regcode") + forceLegacy := viper.GetBool("force-legacy") jww.DEBUG.Printf("sessionDir: %v", storeDir) // TODO: This probably shouldn't be initialized globally. @@ -592,22 +593,22 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { viper.GetBool("unsafe-channel-creation"), e2eParams) // Initialize the client of the proper type - var client *xxdk.E2e + var messenger *xxdk.E2e if precanId != 0 { - client = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams) + messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams) } else if protoUserPath != "" { - client = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams) + messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams) } else if userIdPrefix != "" { - client = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams) + messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams) } else if backupPath != "" { - client = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams) + messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams) } else { - client = loadOrInitClient(storePassword, storeDir, regCode, cmixParams, e2eParams) + messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams) } // Handle protoUser output if protoUser := viper.GetString("protoUserOut"); protoUser != "" { - jsonBytes, err := client.ConstructProtoUserFile() + jsonBytes, err := messenger.ConstructProtoUserFile() if err != nil { jww.FATAL.Panicf("cannot construct proto user file: %v", err) @@ -622,6 +623,9 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { // Handle backup output if backupOut := viper.GetString("backupOut"); backupOut != "" { + if !forceLegacy { + jww.FATAL.Panicf("Unable to make backup for non-legacy sender!") + } updateBackupCb := func(encryptedBackup []byte) { jww.INFO.Printf("Backup update received, size %d", len(encryptedBackup)) @@ -653,24 +657,24 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { } } _, err := backup.InitializeBackup(backupPass, updateBackupCb, - client.GetBackupContainer(), client.GetE2E(), client.GetStorage(), - nil, client.GetStorage().GetKV(), client.GetRng()) + messenger.GetBackupContainer(), messenger.GetE2E(), messenger.GetStorage(), + nil, messenger.GetStorage().GetKV(), messenger.GetRng()) if err != nil { jww.FATAL.Panicf("Failed to initialize backup with key %q: %+v", backupPass, err) } } - return client + return messenger } -func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round { - recipientContact, err := client.GetAuth().GetReceivedRequest( +func acceptChannel(messenger *xxdk.E2e, recipientID *id.ID) id.Round { + recipientContact, err := messenger.GetAuth().GetReceivedRequest( recipientID) if err != nil { jww.FATAL.Panicf("%+v", err) } - rid, err := client.GetAuth().Confirm( + rid, err := messenger.GetAuth().Confirm( recipientContact) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -679,14 +683,14 @@ func acceptChannel(client *xxdk.E2e, recipientID *id.ID) id.Round { return rid } -func deleteChannel(client *xxdk.E2e, partnerId *id.ID) { - err := client.DeleteContact(partnerId) +func deleteChannel(messenger *xxdk.E2e, partnerId *id.ID) { + err := messenger.DeleteContact(partnerId) if err != nil { jww.FATAL.Panicf("%+v", err) } } -func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, +func addAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID, recipient contact.Contact, e2eParams xxdk.E2EParams) { var allowed bool if viper.GetBool("unsafe-channel-creation") { @@ -709,17 +713,17 @@ func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, recipientContact := recipient if recipientContact.ID != nil && recipientContact.DhPubKey != nil { - me := client.GetReceptionIdentity().GetContact() + me := messenger.GetReceptionIdentity().GetContact() jww.INFO.Printf("Requesting auth channel from: %s", recipientID) // Verify that the auth request makes it to the recipient // by monitoring the round result if viper.GetBool("verify-sends") { - requestChannelVerified(client, recipientContact, me, e2eParams) + requestChannelVerified(messenger, recipientContact, me, e2eParams) } else { // Just call Request, agnostic of round result - _, err := client.GetAuth().Request(recipientContact, + _, err := messenger.GetAuth().Request(recipientContact, me.Facts) if err != nil { jww.FATAL.Panicf("%+v", err) @@ -732,7 +736,7 @@ func addAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, } } -func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, +func resetAuthenticatedChannel(messenger *xxdk.E2e, recipientID *id.ID, recipient contact.Contact, e2eParams xxdk.E2EParams) { var allowed bool if viper.GetBool("unsafe-channel-creation") { @@ -760,10 +764,10 @@ func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, // Verify that the auth request makes it to the recipient // by monitoring the round result if viper.GetBool("verify-sends") { - resetChannelVerified(client, recipientContact, + resetChannelVerified(messenger, recipientContact, e2eParams) } else { - _, err := client.GetAuth().Reset(recipientContact) + _, err := messenger.GetAuth().Reset(recipientContact) if err != nil { jww.FATAL.Panicf("%+v", err) } @@ -774,17 +778,17 @@ func resetAuthenticatedChannel(client *xxdk.E2e, recipientID *id.ID, } } -func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID, +func acceptChannelVerified(messenger *xxdk.E2e, recipientID *id.ID, params xxdk.E2EParams) { roundTimeout := params.Base.CMIXParams.SendTimeout done := make(chan struct{}, 1) retryChan := make(chan struct{}, 1) for { - rid := acceptChannel(client, recipientID) + rid := acceptChannel(messenger, recipientID) // Monitor rounds for results - err := client.GetCmix().GetRoundResults(roundTimeout, + err := messenger.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) if err != nil { jww.DEBUG.Printf("Could not verify "+ @@ -810,7 +814,7 @@ func acceptChannelVerified(client *xxdk.E2e, recipientID *id.ID, } } -func requestChannelVerified(client *xxdk.E2e, +func requestChannelVerified(messenger *xxdk.E2e, recipientContact, me contact.Contact, params xxdk.E2EParams) { roundTimeout := params.Base.CMIXParams.SendTimeout @@ -818,14 +822,14 @@ func requestChannelVerified(client *xxdk.E2e, retryChan := make(chan struct{}, 1) done := make(chan struct{}, 1) for { - rid, err := client.GetAuth().Request(recipientContact, + rid, err := messenger.GetAuth().Request(recipientContact, me.Facts) if err != nil { continue } // Monitor rounds for results - err = client.GetCmix().GetRoundResults(roundTimeout, + err = messenger.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) if err != nil { @@ -850,7 +854,7 @@ func requestChannelVerified(client *xxdk.E2e, } } -func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact, +func resetChannelVerified(messenger *xxdk.E2e, recipientContact contact.Contact, params xxdk.E2EParams) { roundTimeout := params.Base.CMIXParams.SendTimeout @@ -858,13 +862,13 @@ func resetChannelVerified(client *xxdk.E2e, recipientContact contact.Contact, done := make(chan struct{}, 1) for { - rid, err := client.GetAuth().Reset(recipientContact) + rid, err := messenger.GetAuth().Reset(recipientContact) if err != nil { jww.FATAL.Panicf("%+v", err) } // Monitor rounds for results - err = client.GetCmix().GetRoundResults(roundTimeout, + err = messenger.GetCmix().GetRoundResults(roundTimeout, makeVerifySendsCallback(retryChan, done), rid) if err != nil { @@ -1131,6 +1135,9 @@ func init() { "ID to send message to (if below 40, will be precanned. Use "+ "'0x' or 'b64:' for hex and base64 representations)") viper.BindPFlag("destid", rootCmd.Flags().Lookup("destid")) + rootCmd.PersistentFlags().Bool("force-legacy", false, + "Force client to operate using legacy identities.") + viper.BindPFlag("force-legacy", rootCmd.PersistentFlags().Lookup("force-legacy")) rootCmd.Flags().StringP("destfile", "", "", "Read this contact file for the destination id") diff --git a/cmd/single.go b/cmd/single.go index 406374c939efacb4af6e0e5b55f5cf91581da5c0..6a7e99575ff163f03c82bb2cc9799fa884e8775e 100644 --- a/cmd/single.go +++ b/cmd/single.go @@ -157,7 +157,7 @@ func (r *Response) Callback(payload []byte, receptionID receptionID.EphemeralIde } // sendSingleUse sends a single use message. -func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte, +func sendSingleUse(net *xxdk.Cmix, partner contact.Contact, payload []byte, maxMessages uint8, timeout time.Duration, tag string) { // Construct callback callback := &Response{ @@ -178,12 +178,12 @@ func sendSingleUse(m *xxdk.Cmix, partner contact.Contact, payload []byte, partner.ID, payload) params := single.GetDefaultRequestParams() params.MaxResponseMessages = maxMessages - rng := m.GetRng().GetStream() + rng := net.GetRng().GetStream() defer rng.Close() - e2eGrp := m.GetStorage().GetE2EGroup() + e2eGrp := net.GetStorage().GetE2EGroup() rnd, ephID, err := single.TransmitRequest(partner, tag, payload, callback, params, - m.GetCmix(), rng, e2eGrp) + net.GetCmix(), rng, e2eGrp) if err != nil { jww.FATAL.Panicf("Failed to transmit single-use message: %+v", err) } diff --git a/cmd/ud.go b/cmd/ud.go index cf1a0df7be220da8ded2bc23bba9b0c1c6c01fa3..b016651f39e6e576d36e2cbf189aba94c696c445 100644 --- a/cmd/ud.go +++ b/cmd/ud.go @@ -39,38 +39,16 @@ var udCmd = &cobra.Command{ // get user and save contact to file user := client.GetReceptionIdentity() - jww.INFO.Printf("User: %s", user.ID) + jww.INFO.Printf("[UD]User: %s", user.ID) writeContact(user.GetContact()) - // // Set up reception handler - // swBoard := client.GetSwitchboard() - // recvCh := make(chan message.Receive, 10000) - // listenerID := swBoard.RegisterChannel("DefaultCLIReceiver", - // switchboard.AnyUser(), message.XxMessage, recvCh) - // jww.INFO.Printf("Message ListenerID: %v", listenerID) - - // // Set up auth request handler, which simply prints the user ID of the - // // requester - // authMgr := client.GetAuthRegistrar() - // authMgr.AddGeneralRequestCallback(printChanRequest) - - // // If unsafe channels, add auto-acceptor - // if viper.GetBool("unsafe-channel-creation") { - // authMgr.AddGeneralRequestCallback(func( - // requester contact.Contact) { - // jww.INFO.Printf("Got Request: %s", requester.ID) - // _, err := client.ConfirmAuthenticatedChannel(requester) - // if err != nil { - // jww.FATAL.Panicf("%+v", err) - // } - // }) - // } - err := client.StartNetworkFollower(50 * time.Millisecond) if err != nil { jww.FATAL.Panicf("%+v", err) } + jww.TRACE.Printf("[UD] Waiting for connection...") + // Wait until connected or crash on timeout connected := make(chan bool, 10) client.GetCmix().AddHealthCallback( @@ -79,9 +57,12 @@ var udCmd = &cobra.Command{ }) waitUntilConnected(connected) + jww.TRACE.Printf("[UD] Connected!") + // Make user discovery manager rng := client.GetRng() userToRegister := viper.GetString("register") + jww.TRACE.Printf("[UD] Registering user %v...", userToRegister) userDiscoveryMgr, err := ud.NewManager(client, client.GetComms(), client.NetworkFollowerStatus, userToRegister, nil) if err != nil { @@ -95,6 +76,7 @@ var udCmd = &cobra.Command{ } } + jww.INFO.Printf("[UD] Registered user %v", userToRegister) var newFacts fact.FactList phone := viper.GetString("addphone") @@ -116,24 +98,29 @@ var udCmd = &cobra.Command{ } for i := 0; i < len(newFacts); i++ { + jww.INFO.Printf("[UD] Registering Fact: %v", + newFacts[i]) r, err := userDiscoveryMgr.SendRegisterFact(newFacts[i]) if err != nil { fmt.Printf("Failed to register fact: %s\n", newFacts[i]) - jww.FATAL.Panicf("Failed to send register fact: %+v", err) + jww.FATAL.Panicf("[UD] Failed to send register fact: %+v", err) } // TODO Store the code? - jww.INFO.Printf("Fact Add Response: %+v", r) + jww.INFO.Printf("[UD] Fact Add Response: %+v", r) } confirmID := viper.GetString("confirm") if confirmID != "" { + jww.INFO.Printf("[UD] Confirming fact: %v", confirmID) err = userDiscoveryMgr.ConfirmFact(confirmID, confirmID) if err != nil { fmt.Printf("Couldn't confirm fact: %s\n", err.Error()) jww.FATAL.Panicf("%+v", err) } + + jww.INFO.Printf("[UD] Confirmed %v", confirmID) } udContact, err := userDiscoveryMgr.GetContact() @@ -147,9 +134,7 @@ var udCmd = &cobra.Command{ lookupIDStr := viper.GetString("lookup") if lookupIDStr != "" { lookupID := parseRecipient(lookupIDStr) - //if !ok { - // jww.FATAL.Panicf("Could not parse recipient: %s", lookupIDStr) - //} + jww.INFO.Printf("[UD] Looking up %v", lookupID) cb := func(newContact contact.Contact, err error) { if err != nil { @@ -177,6 +162,7 @@ var udCmd = &cobra.Command{ err.Error()) jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err) } + jww.INFO.Printf("[UD] BATCHADD: Running") restored, _, _, err := xxmutils.RestoreContactsFromBackup( idListFile, client, userDiscoveryMgr, nil) if err != nil { @@ -187,7 +173,7 @@ var udCmd = &cobra.Command{ for !client.GetE2E().HasAuthenticatedChannel(uid) { time.Sleep(time.Second) } - jww.INFO.Printf("Authenticated channel established for %s", uid) + jww.INFO.Printf("[UD] Authenticated channel established for %s", uid) } } usernameSearchStr := viper.GetString("searchusername") @@ -232,7 +218,7 @@ var udCmd = &cobra.Command{ "Failed to remove user %s: %+v", userToRemove, err) } - fmt.Printf("Removed user from discovery: %s\n", + fmt.Printf("[UD] Removed user from discovery: %s\n", userToRemove) } @@ -255,6 +241,7 @@ var udCmd = &cobra.Command{ stream := rng.GetStream() defer stream.Close() + jww.INFO.Printf("[UD] Search: %v", facts) _, _, err = ud.Search(client.GetCmix(), client.GetEventReporter(), stream, client.GetE2E().GetGroup(), diff --git a/connect/authCallbacks.go b/connect/authCallbacks.go index 227c47500e166155655ce96d0bdc0b9bfbfa2a94..01eb5e90ff994f83d79e68a11a0285104307a6f4 100644 --- a/connect/authCallbacks.go +++ b/connect/authCallbacks.go @@ -117,12 +117,12 @@ func (a serverAuthCallback) Confirm(contact.Contact, // Request will be called when an auth Request message is processed. func (a serverAuthCallback) Request(requestor contact.Contact, - _ receptionID.EphemeralIdentity, _ rounds.Round, e2e *xxdk.E2e) { + _ receptionID.EphemeralIdentity, _ rounds.Round, messenger *xxdk.E2e) { if a.requestCallback == nil { jww.ERROR.Printf("Received a request when requests are" + "not enable, will not accept") } - _, err := e2e.GetAuth().Confirm(requestor) + _, err := messenger.GetAuth().Confirm(requestor) if err != nil { jww.ERROR.Printf("Unable to build connection with "+ "partner %s: %+v", requestor.ID, err) @@ -130,7 +130,7 @@ func (a serverAuthCallback) Request(requestor contact.Contact, a.requestCallback(nil) } // After confirmation, get the new partner - newPartner, err := e2e.GetE2E().GetPartner(requestor.ID) + newPartner, err := messenger.GetE2E().GetPartner(requestor.ID) if err != nil { jww.ERROR.Printf("Unable to build connection with "+ "partner %s: %+v", requestor.ID, err) @@ -142,7 +142,7 @@ func (a serverAuthCallback) Request(requestor contact.Contact, // Return the new Connection object c := BuildConnection( - newPartner, e2e.GetE2E(), e2e.GetAuth(), a.connectionParams) + newPartner, messenger.GetE2E(), messenger.GetAuth(), a.connectionParams) a.cl.Add(c) a.requestCallback(c) } diff --git a/connect/authenticated.go b/connect/authenticated.go index 4376a2ceec13c2588e2dd637ce742cff02a4b033..11f0d2de9d92cb2b42e34dab9618b61d48d77328 100644 --- a/connect/authenticated.go +++ b/connect/authenticated.go @@ -52,27 +52,27 @@ type AuthenticatedCallback func(connection AuthenticatedConnection) // ConnectWithAuthentication is called by the client, ie the one establishing // connection with the server. Once a connect.Connection has been established // with the server and then authenticate their identity to the server. -func ConnectWithAuthentication(recipient contact.Contact, e2eClient *xxdk.E2e, +func ConnectWithAuthentication(recipient contact.Contact, messenger *xxdk.E2e, p xxdk.E2EParams) (AuthenticatedConnection, error) { // Track the time since we started to attempt to establish a connection timeStart := netTime.Now() // Establish a connection with the server - conn, err := Connect(recipient, e2eClient, p) + conn, err := Connect(recipient, messenger, p) if err != nil { return nil, errors.Errorf("failed to establish connection "+ "with recipient %s: %+v", recipient.ID, err) } // Build the authenticated connection and return - identity := e2eClient.GetReceptionIdentity() + identity := messenger.GetReceptionIdentity() privKey, err := identity.GetRSAPrivatePem() if err != nil { return nil, err } return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, privKey, - e2eClient.GetRng(), e2eClient.GetCmix(), p) + messenger.GetRng(), messenger.GetCmix(), p) } // connectWithAuthentication builds and sends an IdentityAuthentication to diff --git a/connect/connect.go b/connect/connect.go index 5e77868c43fb00970483a59b00350a6b5c082999..ea755c0b181cbace7c64f2bb8878dcfd612b022e 100644 --- a/connect/connect.go +++ b/connect/connect.go @@ -26,12 +26,6 @@ import ( "gitlab.com/xx_network/primitives/id" ) -const ( - // connectionTimeout is the time.Duration for a connection - // to be established before the requester times out. - connectionTimeout = 15 * time.Second -) - var alreadyClosedErr = errors.New("connection is closed") // Connection is a wrapper for the E2E and auth packages. @@ -87,19 +81,19 @@ type Callback func(connection Connection) // and returns a Connection object for the newly-created partner.Manager // This function is to be used sender-side and will block until the // partner.Manager is confirmed. -func Connect(recipient contact.Contact, e2eClient *xxdk.E2e, +func Connect(recipient contact.Contact, messenger *xxdk.E2e, p xxdk.E2EParams) (Connection, error) { // Build callback for E2E negotiation signalChannel := make(chan Connection, 1) cb := func(connection Connection) { signalChannel <- connection } - callback := getClientAuthCallback(cb, nil, e2eClient.GetE2E(), - e2eClient.GetAuth(), p) - e2eClient.GetAuth().AddPartnerCallback(recipient.ID, callback) + callback := getClientAuthCallback(cb, nil, messenger.GetE2E(), + messenger.GetAuth(), p) + messenger.GetAuth().AddPartnerCallback(recipient.ID, callback) // Perform the auth request - _, err := e2eClient.GetAuth().Request(recipient, nil) + _, err := messenger.GetAuth().Request(recipient, nil) if err != nil { return nil, err } @@ -157,8 +151,8 @@ func StartServer(identity xxdk.ReceptionIdentity, cb Callback, net *xxdk.Cmix, // ConnectionServer contains type ConnectionServer struct { - E2e *xxdk.E2e - Cl *ConnectionList + Messenger *xxdk.E2e + Cl *ConnectionList } // handler provides an implementation for the Connection interface. diff --git a/dummy/manager.go b/dummy/manager.go index 28ddd25e69c7e40bd2ee8a31a4b84d16ac9a7f5a..4832f3ef505ea37114c2f4d202c82604ddd7eab0 100644 --- a/dummy/manager.go +++ b/dummy/manager.go @@ -57,25 +57,25 @@ type Manager struct { statusChan chan bool // Cmix interfaces - client *xxdk.Cmix - store *storage.Session - net interfaces.NetworkManager - rng *fastRNG.StreamGenerator + net *xxdk.Cmix + store *storage.Session + networkManager interfaces.NetworkManager + rng *fastRNG.StreamGenerator } // NewManager creates a new dummy Manager with the specified average send delta // and the range used for generating random durations. func NewManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - client *xxdk.Cmix, manager interfaces.NetworkManager) *Manager { - clientStorage := client.GetStorage() - return newManager(maxNumMessages, avgSendDelta, randomRange, client, - &clientStorage, manager, client.GetRng()) + net *xxdk.Cmix, manager interfaces.NetworkManager) *Manager { + clientStorage := net.GetStorage() + return newManager(maxNumMessages, avgSendDelta, randomRange, net, + &clientStorage, manager, net.GetRng()) } // newManager builds a new dummy Manager from fields explicitly passed in. This // function is a helper function for NewManager to make it easier to test. func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, - client *xxdk.Cmix, store *storage.Session, net interfaces.NetworkManager, + net *xxdk.Cmix, store *storage.Session, networkManager interfaces.NetworkManager, rng *fastRNG.StreamGenerator) *Manager { return &Manager{ maxNumMessages: maxNumMessages, @@ -83,9 +83,9 @@ func newManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, randomRange: randomRange, status: notStarted, statusChan: make(chan bool, statusChanLen), - client: client, - store: store, net: net, + store: store, + networkManager: networkManager, rng: rng, } } diff --git a/dummy/manager_test.go b/dummy/manager_test.go index 753b0fcb215855f960a5517305c430b0207e9776..6a49bcc6a597ebf476ee8bbfb8f45a79045a4488 100644 --- a/dummy/manager_test.go +++ b/dummy/manager_test.go @@ -59,7 +59,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { msgChan := make(chan bool) go func() { - for m.net.(*testNetworkManager).GetMsgListLen() == 0 { + for m.networkManager.(*testNetworkManager).GetMsgListLen() == 0 { time.Sleep(5 * time.Millisecond) } msgChan <- true @@ -71,7 +71,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.net.(*testNetworkManager).GetMsgListLen() + numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() } err = stop.Close() @@ -86,7 +86,7 @@ func TestManager_StartDummyTraffic(t *testing.T) { msgChan = make(chan bool) go func() { - for m.net.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } msgChan <- true @@ -118,10 +118,10 @@ func TestManager_SetStatus(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.net.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.net.(*testNetworkManager).GetMsgListLen() + numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() msgChan <- true } }() @@ -161,7 +161,7 @@ func TestManager_SetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.net.(*testNetworkManager).GetMsgListLen() + numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() } // Setting status to true multiple times does not interrupt sending @@ -177,10 +177,10 @@ func TestManager_SetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.net.(*testNetworkManager).GetMsgListLen()) + numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) } } @@ -254,10 +254,10 @@ func TestManager_GetStatus(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.net.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.net.(*testNetworkManager).GetMsgListLen() + numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() msgChan <- true } }() @@ -292,7 +292,7 @@ func TestManager_GetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.net.(*testNetworkManager).GetMsgListLen() + numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() } // Setting status to true multiple times does not interrupt sending @@ -311,10 +311,10 @@ func TestManager_GetStatus(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.net.(*testNetworkManager).GetMsgListLen()) + numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) } } diff --git a/dummy/send.go b/dummy/send.go index f6f532c81557a3c440a1296a8c60f2f114146f73..84271b67ea4310bf91af057a58ffe2256520460a 100644 --- a/dummy/send.go +++ b/dummy/send.go @@ -106,7 +106,7 @@ func (m *Manager) sendMessages(msgs map[id.ID]format.Message) error { // } // rng.Close() // p.DebugTag = "dummy" - _, _, err := m.net.SendCMIX(msg, &recipient, p) + _, _, err := m.networkManager.SendCMIX(msg, &recipient, p) if err != nil { jww.WARN.Printf("Failed to send dummy message %d/%d via "+ "Send: %+v", i, len(msgs), err) diff --git a/dummy/send_test.go b/dummy/send_test.go index 6a5a91feff0c152b70982e60e769aae53c37813e..9af8ee8796e4d76faa7d45188c60db271d772335 100644 --- a/dummy/send_test.go +++ b/dummy/send_test.go @@ -40,10 +40,10 @@ func TestManager_sendThread(t *testing.T) { go func() { var numReceived int for i := 0; i < 2; i++ { - for m.net.(*testNetworkManager).GetMsgListLen() == numReceived { + for m.networkManager.(*testNetworkManager).GetMsgListLen() == numReceived { time.Sleep(5 * time.Millisecond) } - numReceived = m.net.(*testNetworkManager).GetMsgListLen() + numReceived = m.networkManager.(*testNetworkManager).GetMsgListLen() msgChan <- true } }() @@ -54,7 +54,7 @@ func TestManager_sendThread(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - numReceived += m.net.(*testNetworkManager).GetMsgListLen() + numReceived += m.networkManager.(*testNetworkManager).GetMsgListLen() } select { @@ -62,10 +62,10 @@ func TestManager_sendThread(t *testing.T) { t.Errorf("Timed out after %s waiting for messages to be sent.", 3*m.avgSendDelta) case <-msgChan: - if m.net.(*testNetworkManager).GetMsgListLen() <= numReceived { + if m.networkManager.(*testNetworkManager).GetMsgListLen() <= numReceived { t.Errorf("Failed to receive second send."+ "\nmessages on last receive: %d\nmessages on this receive: %d", - numReceived, m.net.(*testNetworkManager).GetMsgListLen()) + numReceived, m.networkManager.(*testNetworkManager).GetMsgListLen()) } } @@ -115,7 +115,7 @@ func TestManager_sendMessages(t *testing.T) { } // get sent messages - receivedMsgs := m.net.(*testNetworkManager).GetMsgList() + receivedMsgs := m.networkManager.(*testNetworkManager).GetMsgList() // Test that all messages were received if len(receivedMsgs) != len(msgs) { diff --git a/dummy/utils_test.go b/dummy/utils_test.go index cbc441c22d732469ecc77f145c8de9796c6adee7..bc838731f5f42b345c4fbdfd849750b4551c0ef5 100644 --- a/dummy/utils_test.go +++ b/dummy/utils_test.go @@ -59,7 +59,7 @@ func newTestManager(maxNumMessages int, avgSendDelta, randomRange time.Duration, randomRange: randomRange, statusChan: make(chan bool, statusChanLen), store: &store, - net: newTestNetworkManager(sendErr, t), + networkManager: newTestNetworkManager(sendErr, t), rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG), } diff --git a/e2e/ratchet/partner/relationshipFingerprint.go b/e2e/ratchet/partner/relationshipFingerprint.go index e00f6aa69638830752b079332e63f0f6bb68755f..9380b9a5051e9d82f76d3043e880350600425d6b 100644 --- a/e2e/ratchet/partner/relationshipFingerprint.go +++ b/e2e/ratchet/partner/relationshipFingerprint.go @@ -12,6 +12,7 @@ import ( session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" @@ -20,7 +21,7 @@ import ( func makeRelationshipFingerprint(t session2.RelationshipType, grp *cyclic.Group, myPrivKey, partnerPubKey *cyclic.Int, me, partner *id.ID) []byte { - myPubKey := grp.ExpG(myPrivKey, grp.NewIntFromUInt(1)) + myPubKey := diffieHellman.GeneratePublicKey(myPrivKey, grp) switch t { case session2.Send: diff --git a/single/request.go b/single/request.go index 1a49628653915c373fb6d7b59e632a7375eebfbc..08e78c6effd39046fada90042fd04efd8472855a 100644 --- a/single/request.go +++ b/single/request.go @@ -11,6 +11,7 @@ import ( "gitlab.com/elixxir/client/single/message" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/e2e/auth" "gitlab.com/elixxir/crypto/e2e/singleUse" "gitlab.com/xx_network/crypto/csprng" @@ -271,7 +272,7 @@ func generateDhKeys(grp *cyclic.Group, dhPubKey *cyclic.Int, rng io.Reader) ( privKey := grp.NewIntFromBytes(privKeyBytes) // Generate public key and DH key - publicKey = grp.ExpG(privKey, grp.NewInt(1)) + publicKey = diffieHellman.GeneratePublicKey(privKey, grp) dhKey = grp.Exp(dhPubKey, privKey, grp.NewInt(1)) return dhKey, publicKey, nil diff --git a/storage/session.go b/storage/session.go index 89836d53ebf70a88a006e007e76c940927f7c9b1..1925d453bf8066b22921958c35519842340b5eb9 100644 --- a/storage/session.go +++ b/storage/session.go @@ -10,6 +10,8 @@ package storage import ( + "gitlab.com/elixxir/crypto/diffieHellman" + "math/rand" "sync" "testing" "time" @@ -30,13 +32,11 @@ import ( "gitlab.com/xx_network/primitives/ndf" ) -// Number of rounds to store in the CheckedRound buffer -const CheckRoundsMaxSize = 1000000 / 64 const currentSessionVersion = 0 const cmixGroupKey = "cmixGroup" const e2eGroupKey = "e2eGroup" -// Session object, backed by encrypted filestore +// Session object, backed by encrypted versioned.KVc type Session interface { GetClientVersion() version.Version Get(key string) (*versioned.Object, error) @@ -86,7 +86,7 @@ type session struct { clientVersion *clientVersion.Store } -// Initialize a new Session object +// initStore initializes a new Session object func initStore(baseDir, password string) (*session, error) { fs, err := ekv.NewFilestore(baseDir, password) var s *session @@ -102,7 +102,7 @@ func initStore(baseDir, password string) (*session, error) { return s, nil } -// Creates new UserData in the session +// New UserData in the session func New(baseDir, password string, u user.Info, currentVersion version.Version, cmixGrp, e2eGrp *cyclic.Group) (Session, error) { @@ -119,7 +119,7 @@ func New(baseDir, password string, u user.Info, } s.User, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt, - u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned) + u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned, u.E2eDhPrivateKey, u.E2eDhPublicKey) if err != nil { return nil, errors.WithMessage(err, "Failed to create user") } @@ -139,7 +139,7 @@ func New(baseDir, password string, u user.Info, return s, nil } -// Loads existing user data into the session +// Load existing user data into the session func Load(baseDir, password string, currentVersion version.Version) (Session, error) { s, err := initStore(baseDir, password) @@ -196,7 +196,7 @@ func (s *session) Set(key string, object *versioned.Object) error { return s.kv.Set(key, currentSessionVersion, object) } -// delete a value in the session +// Delete a value in the session func (s *session) Delete(key string) error { return s.kv.Delete(key, currentSessionVersion) } @@ -206,17 +206,17 @@ func (s *session) GetKV() *versioned.KV { return s.kv } -// GetCmixGrouo returns cMix Group +// GetCmixGroup returns cMix Group func (s *session) GetCmixGroup() *cyclic.Group { return s.cmixGroup } -// GetE2EGrouo returns cMix Group +// GetE2EGroup returns cMix Group func (s *session) GetE2EGroup() *cyclic.Group { return s.e2eGroup } -// Initializes a Session object wrapped around a MemStore object. +// InitTestingSession object wrapped around a MemStore object. // FOR TESTING ONLY func InitTestingSession(i interface{}) Session { switch i.(type) { @@ -230,7 +230,14 @@ func InitTestingSession(i interface{}) Session { kv := versioned.NewKV(ekv.MakeMemstore()) s := &session{kv: kv} uid := id.NewIdFromString("zezima", id.User, i) - u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := user.NewUser(kv, uid, uid, []byte("salt"), []byte("salt"), privKey, privKey, false, dhPrivKey, dhPubKey) if err != nil { jww.FATAL.Panicf("InitTestingSession failed to create dummy user: %+v", err) } diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go index fd4b73047008f6f0f78ad9a2f1b067372932aae6..8c245fc70ac257dc9eef14d9848be007c7831343 100644 --- a/storage/user/cryptographic.go +++ b/storage/user/cryptographic.go @@ -10,15 +10,19 @@ package user import ( "bytes" "encoding/gob" + "encoding/json" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" ) -const currentCryptographicIdentityVersion = 0 +const originalCryptographicIdentityVersion = 0 +const currentCryptographicIdentityVersion = 1 const cryptographicIdentityKey = "cryptographicIdentity" type CryptographicIdentity struct { @@ -29,6 +33,8 @@ type CryptographicIdentity struct { receptionSalt []byte receptionRsaKey *rsa.PrivateKey isPrecanned bool + e2eDhPrivateKey *cyclic.Int + e2eDhPublicKey *cyclic.Int } type ciDisk struct { @@ -41,10 +47,23 @@ type ciDisk struct { IsPrecanned bool } +type ciDiskV1 struct { + TransmissionID *id.ID + TransmissionSalt []byte + TransmissionRsaKey *rsa.PrivateKey + ReceptionID *id.ID + ReceptionSalt []byte + ReceptionRsaKey *rsa.PrivateKey + IsPrecanned bool + E2eDhPrivateKey []byte + E2eDhPublicKey []byte +} + func newCryptographicIdentity(transmissionID, receptionID *id.ID, transmissionSalt, receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, - isPrecanned bool, kv *versioned.KV) *CryptographicIdentity { + isPrecanned bool, e2eDhPrivateKey, e2eDhPublicKey *cyclic.Int, + kv *versioned.KV) *CryptographicIdentity { ci := &CryptographicIdentity{ transmissionID: transmissionID, @@ -54,6 +73,8 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID, receptionSalt: receptionSalt, receptionRsaKey: receptionRsa, isPrecanned: isPrecanned, + e2eDhPrivateKey: e2eDhPrivateKey, + e2eDhPublicKey: e2eDhPublicKey, } if err := ci.save(kv); err != nil { @@ -64,39 +85,115 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID, return ci } -func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) { - obj, err := kv.Get(cryptographicIdentityKey, - currentCryptographicIdentityVersion) +// loadOriginalCryptographicIdentity attempts to load the originalCryptographicIdentityVersion CryptographicIdentity +func loadOriginalCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) { + result := &CryptographicIdentity{} + obj, err := kv.Get(cryptographicIdentityKey, originalCryptographicIdentityVersion) if err != nil { - return nil, errors.WithMessage(err, "Failed to get user "+ - "cryptographic identity from EKV") + return nil, errors.WithMessagef(err, "Failed to get version %d user "+ + "cryptographic identity from EKV", originalCryptographicIdentityVersion) } - var resultBuffer bytes.Buffer - result := &CryptographicIdentity{} decodable := &ciDisk{} resultBuffer.Write(obj.Data) dec := gob.NewDecoder(&resultBuffer) err = dec.Decode(decodable) + if err != nil { + return nil, err + } - if decodable != nil { - result.isPrecanned = decodable.IsPrecanned - result.receptionRsaKey = decodable.ReceptionRsaKey - result.transmissionRsaKey = decodable.TransmissionRsaKey - result.transmissionSalt = decodable.TransmissionSalt - result.transmissionID = decodable.TransmissionID - result.receptionID = decodable.ReceptionID - result.receptionSalt = decodable.ReceptionSalt + result.isPrecanned = decodable.IsPrecanned + result.receptionRsaKey = decodable.ReceptionRsaKey + result.transmissionRsaKey = decodable.TransmissionRsaKey + result.transmissionSalt = decodable.TransmissionSalt + result.transmissionID = decodable.TransmissionID + result.receptionID = decodable.ReceptionID + result.receptionSalt = decodable.ReceptionSalt + return result, nil +} + +func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) { + result := &CryptographicIdentity{} + obj, err := kv.Get(cryptographicIdentityKey, + currentCryptographicIdentityVersion) + if err != nil { + result, err = loadOriginalCryptographicIdentity(kv) + if err != nil { + return nil, err + } + jww.WARN.Printf("Attempting to migrate cryptographic identity to new version...") + // Populate E2E keys from legacy storage + result.e2eDhPublicKey, result.e2eDhPrivateKey = loadLegacyDHKeys(kv) + // Migrate to the new version in storage + return result, result.save(kv) + } + + decodable := &ciDiskV1{} + err = json.Unmarshal(obj.Data, decodable) + if err != nil { + return nil, err } - return result, err + result.isPrecanned = decodable.IsPrecanned + result.receptionRsaKey = decodable.ReceptionRsaKey + result.transmissionRsaKey = decodable.TransmissionRsaKey + result.transmissionSalt = decodable.TransmissionSalt + result.transmissionID = decodable.TransmissionID + result.receptionID = decodable.ReceptionID + result.receptionSalt = decodable.ReceptionSalt + + result.e2eDhPrivateKey = &cyclic.Int{} + err = result.e2eDhPrivateKey.UnmarshalJSON(decodable.E2eDhPrivateKey) + if err != nil { + return nil, err + } + result.e2eDhPublicKey = &cyclic.Int{} + err = result.e2eDhPublicKey.UnmarshalJSON(decodable.E2eDhPublicKey) + if err != nil { + return nil, err + } + + return result, nil +} + +// loadLegacyDHKeys attempts to load DH Keys from legacy storage. It +// prints a warning to the log as users should be using ReceptionIdentity +// instead of PortableUserInfo +func loadLegacyDHKeys(kv *versioned.KV) (pub, priv *cyclic.Int) { + // Legacy package prefixes and keys, see e2e/ratchet/storage.go + packagePrefix := "e2eSession" + pubKeyKey := "DhPubKey" + privKeyKey := "DhPrivKey" + + kvPrefix := kv.Prefix(packagePrefix) + + privKey, err := utility.LoadCyclicKey(kvPrefix, privKeyKey) + if err != nil { + jww.ERROR.Printf("Failed to load e2e DH private key: %v", err) + return nil, nil + } + + pubKey, err := utility.LoadCyclicKey(kvPrefix, pubKeyKey) + if err != nil { + jww.ERROR.Printf("Failed to load e2e DH public key: %v", err) + return nil, nil + } + + return pubKey, privKey } func (ci *CryptographicIdentity) save(kv *versioned.KV) error { - var userDataBuffer bytes.Buffer + dhPriv, err := ci.e2eDhPrivateKey.MarshalJSON() + if err != nil { + return err + } + dhPub, err := ci.e2eDhPublicKey.MarshalJSON() + if err != nil { + return err + } - encodable := &ciDisk{ + encodable := &ciDiskV1{ TransmissionID: ci.transmissionID, TransmissionSalt: ci.transmissionSalt, TransmissionRsaKey: ci.transmissionRsaKey, @@ -104,10 +201,11 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { ReceptionSalt: ci.receptionSalt, ReceptionRsaKey: ci.receptionRsaKey, IsPrecanned: ci.isPrecanned, + E2eDhPrivateKey: dhPriv, + E2eDhPublicKey: dhPub, } - enc := gob.NewEncoder(&userDataBuffer) - err := enc.Encode(encodable) + enc, err := json.Marshal(&encodable) if err != nil { return err } @@ -115,7 +213,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { obj := &versioned.Object{ Version: currentCryptographicIdentityVersion, Timestamp: netTime.Now(), - Data: userDataBuffer.Bytes(), + Data: enc, } return kv.Set(cryptographicIdentityKey, @@ -149,3 +247,11 @@ func (ci *CryptographicIdentity) GetTransmissionRSA() *rsa.PrivateKey { func (ci *CryptographicIdentity) IsPrecanned() bool { return ci.isPrecanned } + +func (ci *CryptographicIdentity) GetE2eDhPublicKey() *cyclic.Int { + return ci.e2eDhPublicKey.DeepCopy() +} + +func (ci *CryptographicIdentity) GetE2eDhPrivateKey() *cyclic.Int { + return ci.e2eDhPrivateKey.DeepCopy() +} diff --git a/storage/user/cryptographic_test.go b/storage/user/cryptographic_test.go index 1096ccf683e288ae99577bc14989ab3fd71af599..0b9f92d9525600ad66c7746dbda12fa06fc6a318 100644 --- a/storage/user/cryptographic_test.go +++ b/storage/user/cryptographic_test.go @@ -11,7 +11,10 @@ import ( "bytes" "crypto/rand" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "testing" @@ -22,11 +25,19 @@ func TestNewCryptographicIdentity(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("zezima", id.User, t) salt := []byte("salt") - _ = newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) - _, err := kv.Get(cryptographicIdentityKey, 0) + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + _ = newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) + + _, err := kv.Get(cryptographicIdentityKey, currentCryptographicIdentityVersion) if err != nil { - t.Errorf("Did not store cryptographic identity") + t.Errorf("Did not store cryptographic identity: %+v", err) } } @@ -35,7 +46,15 @@ func TestLoadCryptographicIdentity(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("zezima", id.User, t) salt := []byte("salt") - ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) err := ci.save(kv) if err != nil { @@ -64,7 +83,15 @@ func TestCryptographicIdentity_GetReceptionRSA(t *testing.T) { t.Errorf("Failed to generate pk2") } salt := []byte("salt") - ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity( + uid, uid, salt, salt, pk1, pk2, false, dhPrivKey, dhPubKey, kv) if ci.GetReceptionRSA().D != pk2.D { t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk2, ci.GetReceptionRSA()) } @@ -83,7 +110,15 @@ func TestCryptographicIdentity_GetTransmissionRSA(t *testing.T) { t.Errorf("Failed to generate pk2") } salt := []byte("salt") - ci := newCryptographicIdentity(uid, uid, salt, salt, pk1, pk2, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity( + uid, uid, salt, salt, pk1, pk2, false, dhPrivKey, dhPubKey, kv) if ci.GetTransmissionRSA().D != pk1.D { t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk1, ci.GetTransmissionRSA()) } @@ -95,7 +130,15 @@ func TestCryptographicIdentity_GetTransmissionSalt(t *testing.T) { uid := id.NewIdFromString("zezima", id.User, t) ts := []byte("transmission salt") rs := []byte("reception salt") - ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) if bytes.Compare(ci.GetTransmissionSalt(), ts) != 0 { t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", ts, ci.GetTransmissionSalt()) } @@ -107,7 +150,15 @@ func TestCryptographicIdentity_GetReceptionSalt(t *testing.T) { uid := id.NewIdFromString("zezima", id.User, t) ts := []byte("transmission salt") rs := []byte("reception salt") - ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(uid, uid, ts, rs, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) if bytes.Compare(ci.GetReceptionSalt(), rs) != 0 { t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", rs, ci.GetReceptionSalt()) } @@ -119,7 +170,14 @@ func TestCryptographicIdentity_GetTransmissionID(t *testing.T) { rid := id.NewIdFromString("zezima", id.User, t) tid := id.NewIdFromString("jakexx360", id.User, t) salt := []byte("salt") - ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) if !ci.GetTransmissionID().Cmp(tid) { t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", tid, ci.GetTransmissionID()) } @@ -131,7 +189,14 @@ func TestCryptographicIdentity_GetReceptionID(t *testing.T) { rid := id.NewIdFromString("zezima", id.User, t) tid := id.NewIdFromString("jakexx360", id.User, t) salt := []byte("salt") - ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(tid, rid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) if !ci.GetReceptionID().Cmp(rid) { t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", rid, ci.GetReceptionID()) } @@ -142,7 +207,14 @@ func TestCryptographicIdentity_IsPrecanned(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("zezima", id.User, t) salt := []byte("salt") - ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, true, kv) + + prng := rand.Reader + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, true, dhPrivKey, dhPubKey, kv) if !ci.IsPrecanned() { t.Error("I really don't know how this could happen") } diff --git a/storage/user/info.go b/storage/user/info.go index 3da77bb13935d863e382e26ad55aa529f1b63b6b..fc272cb0fe134b767e399b4bb9fca2a8cd3411e4 100644 --- a/storage/user/info.go +++ b/storage/user/info.go @@ -94,10 +94,8 @@ func (u *User) PortableUserInfo() Info { ReceptionSalt: copySlice(ci.GetReceptionSalt()), ReceptionRSA: ci.GetReceptionRSA(), Precanned: ci.IsPrecanned(), - //fixme: set these in the e2e layer, the command line layer - //needs more logical separation so this can be removed - E2eDhPrivateKey: nil, - E2eDhPublicKey: nil, + E2eDhPrivateKey: ci.GetE2eDhPrivateKey(), + E2eDhPublicKey: ci.GetE2eDhPublicKey(), } } diff --git a/storage/user/registation_test.go b/storage/user/registation_test.go index cec369ea41ca74c63ea972e3455a4b577ebcd464..346e662758223a755e13c5e19186002ae6b9ec6f 100644 --- a/storage/user/registation_test.go +++ b/storage/user/registation_test.go @@ -11,10 +11,14 @@ import ( "bytes" "encoding/binary" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" + "math/rand" "testing" "time" ) @@ -24,7 +28,15 @@ func TestUser_GetRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -59,7 +71,15 @@ func TestUser_SetRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -102,7 +122,15 @@ func TestUser_loadRegistrationValidationSignature(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -145,7 +173,15 @@ func TestUser_GetRegistrationTimestamp(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -194,7 +230,15 @@ func TestUser_loadRegistrationTimestamp(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } diff --git a/storage/user/user.go b/storage/user/user.go index e79abf3300c039ab8f097672bc6e62ca8a47f286..5b84321a97cc169df474ab2ebd602bfb2769c0b1 100644 --- a/storage/user/user.go +++ b/storage/user/user.go @@ -10,6 +10,7 @@ package user import ( "github.com/pkg/errors" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "sync" @@ -33,9 +34,11 @@ type User struct { // builds a new user. func NewUser(kv *versioned.KV, transmissionID, receptionID *id.ID, transmissionSalt, - receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool) (*User, error) { + receptionSalt []byte, transmissionRsa, receptionRsa *rsa.PrivateKey, isPrecanned bool, + e2eDhPrivateKey, e2eDhPublicKey *cyclic.Int) (*User, error) { - ci := newCryptographicIdentity(transmissionID, receptionID, transmissionSalt, receptionSalt, transmissionRsa, receptionRsa, isPrecanned, kv) + ci := newCryptographicIdentity(transmissionID, receptionID, transmissionSalt, + receptionSalt, transmissionRsa, receptionRsa, isPrecanned, e2eDhPrivateKey, e2eDhPublicKey, kv) return &User{CryptographicIdentity: ci, kv: kv}, nil } diff --git a/storage/user/user_test.go b/storage/user/user_test.go index 01a93088c1e54c7d2b6d03a6d5a6a1cb0cfb8803..9198e48f607e3c25d79d74242f7607819a83efd1 100644 --- a/storage/user/user_test.go +++ b/storage/user/user_test.go @@ -9,9 +9,13 @@ package user import ( "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" + "math/rand" "testing" ) @@ -26,7 +30,15 @@ func TestLoadUser(t *testing.T) { uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false, kv) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + ci := newCryptographicIdentity(uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey, kv) err = ci.save(kv) if err != nil { t.Errorf("Failed to save ci to kv: %+v", err) @@ -43,7 +55,15 @@ func TestNewUser(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) uid := id.NewIdFromString("test", id.User, t) salt := []byte("salt") - u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, uid, uid, salt, salt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } diff --git a/storage/user/username_test.go b/storage/user/username_test.go index f4a851145b8296bdab49b07bb6996d51344dc2ae..a52b20ac003d692c38ba632299354bb8ce698faf 100644 --- a/storage/user/username_test.go +++ b/storage/user/username_test.go @@ -9,10 +9,14 @@ package user import ( "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/large" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" + "math/rand" "testing" ) @@ -23,7 +27,15 @@ func TestUser_SetUsername(t *testing.T) { rid := id.NewIdFromString("recv", id.User, t) tsalt := []byte("tsalt") rsalt := []byte("rsalt") - u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -57,7 +69,15 @@ func TestUser_GetUsername(t *testing.T) { rid := id.NewIdFromString("recv", id.User, t) tsalt := []byte("tsalt") rsalt := []byte("rsalt") - u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } @@ -85,7 +105,15 @@ func TestUser_loadUsername(t *testing.T) { rid := id.NewIdFromString("recv", id.User, t) tsalt := []byte("tsalt") rsalt := []byte("rsalt") - u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, &rsa.PrivateKey{}, false) + + prng := rand.New(rand.NewSource(42)) + grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2)) + dhPrivKey := diffieHellman.GeneratePrivateKey( + diffieHellman.DefaultPrivateKeyLength, grp, prng) + dhPubKey := diffieHellman.GeneratePublicKey(dhPrivKey, grp) + + u, err := NewUser(kv, tid, rid, tsalt, rsalt, &rsa.PrivateKey{}, + &rsa.PrivateKey{}, false, dhPrivKey, dhPubKey) if err != nil || u == nil { t.Errorf("Failed to create new user: %+v", err) } diff --git a/ud/register.go b/ud/register.go index 591a1cf1fd218c9afc9b84af5d53c4300505914e..07c7fcdb942b2f96726af26a5e1deeac92fc2278 100644 --- a/ud/register.go +++ b/ud/register.go @@ -3,6 +3,7 @@ package ud import ( "github.com/pkg/errors" pb "gitlab.com/elixxir/comms/mixmessages" + "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/crypto/factID" "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/primitives/fact" @@ -30,7 +31,7 @@ func (m *Manager) register(username string, rng csprng.Source, if err != nil { return err } - dhKeyPub := grp.ExpG(dhKeyPriv, grp.NewInt(1)) + dhKeyPub := diffieHellman.GeneratePublicKey(dhKeyPriv, grp) // Construct the user registration message msg := &pb.UDBUserRegistration{ diff --git a/xxdk/cmix.go b/xxdk/cmix.go index f2904335b283f5fd5327c7e69bc0bd34120d7502..64f08e03ab2ae6bffbc6e45c8418681a17fc3b17 100644 --- a/xxdk/cmix.go +++ b/xxdk/cmix.go @@ -78,12 +78,12 @@ func NewCmix(ndfJSON, storageDir string, password []byte, cmixGrp, e2eGrp := DecodeGroups(def) start := netTime.Now() - protoUser := createNewUser(rngStreamGen) + userInfo := createNewUser(rngStreamGen, e2eGrp) jww.DEBUG.Printf("PortableUserInfo generation took: %s", netTime.Now().Sub(start)) _, err = CheckVersionAndSetupStorage(def, storageDir, password, - protoUser, cmixGrp, e2eGrp, registrationCode) + userInfo, cmixGrp, e2eGrp, registrationCode) return err } @@ -106,8 +106,7 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, } cmixGrp, e2eGrp := DecodeGroups(def) - userInfo := createNewVanityUser(rngStream, cmixGrp, e2eGrp, - userIdPrefix) + userInfo := createNewVanityUser(rngStream, e2eGrp, userIdPrefix) _, err = CheckVersionAndSetupStorage(def, storageDir, password, userInfo, cmixGrp, e2eGrp, registrationCode) @@ -162,28 +161,21 @@ func OpenCmix(storageDir string, password []byte) (*Cmix, error) { // predefined cryptographic which defines a user. This is designed for some // specific deployment procedures and is generally unsafe. func NewProtoClient_Unsafe(ndfJSON, storageDir string, password []byte, - protoUser *user.Proto) (ReceptionIdentity, error) { + protoUser *user.Proto) error { jww.INFO.Printf("NewProtoClient_Unsafe") usr := user.NewUserFromProto(protoUser) def, err := ParseNDF(ndfJSON) if err != nil { - return ReceptionIdentity{}, err + return err } cmixGrp, e2eGrp := DecodeGroups(def) - storageSess, err := CheckVersionAndSetupStorage(def, storageDir, password, usr, cmixGrp, e2eGrp, protoUser.RegCode) if err != nil { - return ReceptionIdentity{}, err - } - - identity, err := buildReceptionIdentity(protoUser.ReceptionID, protoUser.ReceptionSalt, - protoUser.ReceptionRSA, e2eGrp, protoUser.E2eDhPrivateKey) - if err != nil { - return ReceptionIdentity{}, err + return err } storageSess.SetReceptionRegistrationValidationSignature( @@ -197,10 +189,10 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password []byte, err = storageSess.ForwardRegistrationStatus( storage.PermissioningComplete) if err != nil { - return ReceptionIdentity{}, err + return err } - return identity, nil + return nil } // LoadCmix initializes a Cmix object from existing storage and starts the network @@ -569,7 +561,7 @@ func DecodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { // NewPrecannedClient and NewVanityClient it checks client version and // creates a new storage for user data func CheckVersionAndSetupStorage(def *ndf.NetworkDefinition, - storageDir string, password []byte, protoUser user.Info, + storageDir string, password []byte, userInfo user.Info, cmixGrp, e2eGrp *cyclic.Group, registrationCode string) ( storage.Session, error) { // get current client version @@ -581,7 +573,7 @@ func CheckVersionAndSetupStorage(def *ndf.NetworkDefinition, // Create Storage passwordStr := string(password) - storageSess, err := storage.New(storageDir, passwordStr, protoUser, + storageSess, err := storage.New(storageDir, passwordStr, userInfo, currentVersion, cmixGrp, e2eGrp) if err != nil { return nil, err diff --git a/xxdk/e2e.go b/xxdk/e2e.go index 098657f9c4e2e0ad4c15e3ce797c4457d1888540..2fe5fdf87ed43b2b90be8dc7b1286cb19262e067 100644 --- a/xxdk/e2e.go +++ b/xxdk/e2e.go @@ -7,7 +7,6 @@ package xxdk import ( - "encoding/binary" "encoding/json" "time" @@ -21,8 +20,6 @@ import ( "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/diffieHellman" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/crypto/xx" "gitlab.com/xx_network/primitives/id" @@ -42,143 +39,80 @@ type E2e struct { // that allows for initializing an E2e object without an E2e-dependant auth.Callbacks type AuthCallbacks interface { Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity, - round rounds.Round, e2e *E2e) + round rounds.Round, messenger *E2e) Confirm(partner contact.Contact, receptionID receptionID.EphemeralIdentity, - round rounds.Round, e2e *E2e) + round rounds.Round, messenger *E2e) Reset(partner contact.Contact, receptionID receptionID.EphemeralIdentity, - round rounds.Round, e2e *E2e) + round rounds.Round, messenger *E2e) } // Login creates a new E2e backed by the xxdk.Cmix persistent versioned.KV // It bundles a Cmix object with a ReceptionIdentity object // and initializes the auth.State and e2e.Handler objects -func Login(client *Cmix, callbacks AuthCallbacks, +func Login(net *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, params E2EParams) (m *E2e, err error) { - return login(client, callbacks, identity, client.GetStorage().GetKV(), - params) + + // If the given identity matches the stored ReceptionID, + // then we are using a legacy ReceptionIdentity + defaultReceptionId := net.GetStorage().PortableUserInfo().ReceptionID + if identity.ID.Cmp(defaultReceptionId) { + return loginLegacy(net, callbacks, identity, params) + } + + // Otherwise, we are using a modern ReceptionIdentity + return login(net, callbacks, identity, net.GetStorage().GetKV(), params) } // LoginEphemeral creates a new E2e backed by a totally ephemeral versioned.KV -func LoginEphemeral(client *Cmix, callbacks AuthCallbacks, +func LoginEphemeral(net *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, params E2EParams) (m *E2e, err error) { - return login(client, callbacks, identity, + return login(net, callbacks, identity, versioned.NewKV(ekv.MakeMemstore()), params) } -// LoginLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV +// loginLegacy creates a new E2e backed by the xxdk.Cmix persistent versioned.KV // Uses the pre-generated transmission ID used by xxdk.Cmix. // This function is designed to maintain backwards compatibility with previous // xx messenger designs and should not be used for other purposes. -func LoginLegacy(client *Cmix, params E2EParams, callbacks AuthCallbacks) ( +func loginLegacy(net *Cmix, callbacks AuthCallbacks, + identity ReceptionIdentity, params E2EParams) ( m *E2e, err error) { m = &E2e{ - Cmix: client, + Cmix: net, backup: &Container{}, } - m.e2e, err = loadOrInitE2eLegacy(client) + m.e2e, err = loadOrInitE2eLegacy(identity, net) if err != nil { return nil, err } + net.GetCmix().AddIdentity(identity.ID, time.Time{}, true) - userInfo := client.GetStorage().PortableUserInfo() - client.GetCmix().AddIdentity(userInfo.ReceptionID, time.Time{}, true) - - err = client.AddService(m.e2e.StartProcesses) + err = net.AddService(m.e2e.StartProcesses) if err != nil { return nil, errors.WithMessage(err, "Failed to add "+ "the e2e processies") } - m.auth, err = auth.NewState(client.GetStorage().GetKV(), client.GetCmix(), - m.e2e, client.GetRng(), client.GetEventReporter(), params.Auth, + m.auth, err = auth.NewState(net.GetStorage().GetKV(), net.GetCmix(), + m.e2e, net.GetRng(), net.GetEventReporter(), params.Auth, params.Session, MakeAuthCallbacksAdapter(callbacks, m), m.backup.TriggerBackup) if err != nil { return nil, err } - m.e2eIdentity, err = buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt, - userInfo.ReceptionRSA, m.e2e.GetGroup(), m.e2e.GetHistoricalDHPrivkey()) - return m, err -} - -// LoginWithNewBaseNDF_UNSAFE initializes a client object from existing storage -// while replacing the base NDF. This is designed for some specific deployment -// procedures and is generally unsafe. -func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, - newBaseNdf string, e2eParams E2EParams, cmixParams CMIXParams) (*E2e, - error) { - jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()") - - def, err := ParseNDF(newBaseNdf) - if err != nil { - return nil, err - } - - c, err := LoadCmix(storageDir, password, cmixParams) - if err != nil { - return nil, err - } - - //store the updated base NDF - c.storage.SetNDF(def) - - if def.Registration.Address != "" { - err = c.initPermissioning(def) - if err != nil { - return nil, err - } - } else { - jww.WARN.Printf("Registration with permissioning skipped due " + - "to blank permissionign address. Cmix will not be " + - "able to register or track network.") - } - - return LoginLegacy(c, e2eParams, nil) -} - -// LoginWithProtoClient creates a client object with a protoclient -// JSON containing the cryptographic primitives. This is designed for -// some specific deployment procedures and is generally unsafe. -func LoginWithProtoClient(storageDir string, password []byte, - protoClientJSON []byte, newBaseNdf string, callbacks AuthCallbacks, - cmixParams CMIXParams, e2eParams E2EParams) (*E2e, error) { - jww.INFO.Printf("LoginWithProtoClient()") - - def, err := ParseNDF(newBaseNdf) - if err != nil { - return nil, err - } - - protoUser := &user.Proto{} - err = json.Unmarshal(protoClientJSON, protoUser) - if err != nil { - return nil, err - } - - receptionIdentity, err := NewProtoClient_Unsafe(newBaseNdf, storageDir, password, - protoUser) - if err != nil { - return nil, err - } - - c, err := LoadCmix(storageDir, password, cmixParams) - if err != nil { - return nil, err - } - - c.storage.SetNDF(def) - - err = c.initPermissioning(def) + rsaKey, err := identity.GetRSAPrivatePem() if err != nil { return nil, err } - return Login(c, callbacks, receptionIdentity, e2eParams) + m.e2eIdentity, err = buildReceptionIdentity(identity.ID, identity.Salt, + rsaKey, m.e2e.GetGroup(), m.e2e.GetHistoricalDHPrivkey()) + return m, err } // login creates a new xxdk.E2e backed by the given versioned.KV -func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, +func login(net *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, kv *versioned.KV, params E2EParams) (m *E2e, err error) { // Verify the passed-in ReceptionIdentity matches its properties @@ -196,7 +130,7 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, } m = &E2e{ - Cmix: client, + Cmix: net, backup: &Container{}, e2eIdentity: identity, } @@ -206,10 +140,10 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, } // load or init the new e2e storage - e2eGrp := client.GetStorage().GetE2EGroup() + e2eGrp := net.GetStorage().GetE2EGroup() m.e2e, err = e2e.Load(kv, - client.GetCmix(), identity.ID, e2eGrp, client.GetRng(), - client.GetEventReporter()) + net.GetCmix(), identity.ID, e2eGrp, net.GetRng(), + net.GetEventReporter()) if err != nil { //initialize the e2e storage err = e2e.Init(kv, identity.ID, dhPrivKey, e2eGrp, @@ -220,29 +154,29 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, //load the new e2e storage m.e2e, err = e2e.Load(kv, - client.GetCmix(), identity.ID, e2eGrp, client.GetRng(), - client.GetEventReporter()) + net.GetCmix(), identity.ID, e2eGrp, net.GetRng(), + net.GetEventReporter()) if err != nil { return nil, errors.WithMessage(err, "Failed to load a "+ "newly created e2e store") } } - err = client.AddService(m.e2e.StartProcesses) + err = net.AddService(m.e2e.StartProcesses) if err != nil { return nil, errors.WithMessage(err, "Failed to add "+ "the e2e processies") } - m.auth, err = auth.NewState(kv, client.GetCmix(), - m.e2e, client.GetRng(), client.GetEventReporter(), + m.auth, err = auth.NewState(kv, net.GetCmix(), + m.e2e, net.GetRng(), net.GetEventReporter(), params.Auth, params.Session, MakeAuthCallbacksAdapter(callbacks, m), m.backup.TriggerBackup) if err != nil { return nil, err } - client.network.AddIdentity(identity.ID, time.Time{}, true) + net.network.AddIdentity(identity.ID, time.Time{}, true) jww.INFO.Printf("Client logged in: \n\tReceptionID: %s", identity.ID) return m, err @@ -251,47 +185,29 @@ func login(client *Cmix, callbacks AuthCallbacks, identity ReceptionIdentity, // loadOrInitE2eLegacy loads the e2e handler or makes a new one, generating a new // e2e private key. It attempts to load via a legacy construction, then tries // to load the modern one, creating a new modern ID if neither can be found -func loadOrInitE2eLegacy(client *Cmix) (e2e.Handler, error) { - usr := client.GetStorage().PortableUserInfo() - e2eGrp := client.GetStorage().GetE2EGroup() - kv := client.GetStorage().GetKV() +func loadOrInitE2eLegacy(identity ReceptionIdentity, net *Cmix) (e2e.Handler, error) { + e2eGrp := net.GetStorage().GetE2EGroup() + kv := net.GetStorage().GetKV() //try to load a legacy e2e handler e2eHandler, err := e2e.LoadLegacy(kv, - client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(), - client.GetEventReporter(), rekey.GetDefaultParams()) + net.GetCmix(), identity.ID, e2eGrp, net.GetRng(), + net.GetEventReporter(), rekey.GetDefaultParams()) if err != nil { //if no legacy e2e handler exists, try to load a new one e2eHandler, err = e2e.Load(kv, - client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(), - client.GetEventReporter()) + net.GetCmix(), identity.ID, e2eGrp, net.GetRng(), + net.GetEventReporter()) if err != nil { jww.WARN.Printf("Failed to load e2e instance for %s, "+ - "creating a new one", usr.ReceptionID) - - //generate the key - var privkey *cyclic.Int - if client.GetStorage().IsPrecanned() { - 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()), - e2eGrp, rngStream) - rngStream.Close() - } + "creating a new one", identity.ID) //initialize the e2e storage - err = e2e.Init(kv, usr.ReceptionID, privkey, e2eGrp, + privKey, err := identity.GetDHKeyPrivate() + if err != nil { + return nil, err + } + err = e2e.Init(kv, identity.ID, privKey, e2eGrp, rekey.GetDefaultParams()) if err != nil { return nil, err @@ -299,19 +215,19 @@ func loadOrInitE2eLegacy(client *Cmix) (e2e.Handler, error) { //load the new e2e storage e2eHandler, err = e2e.Load(kv, - client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(), - client.GetEventReporter()) + net.GetCmix(), identity.ID, e2eGrp, net.GetRng(), + net.GetEventReporter()) if err != nil { return nil, errors.WithMessage(err, "Failed to load a "+ "newly created e2e store") } } else { jww.INFO.Printf("Loaded a modern e2e instance for %s", - usr.ReceptionID) + identity.ID) } } else { jww.INFO.Printf("Loaded a legacy e2e instance for %s", - usr.ReceptionID) + identity.ID) } return e2eHandler, nil } diff --git a/xxdk/identity.go b/xxdk/identity.go index ba4706b3489a20a09919c33b4808b59d34ed1d9b..8d4b392d8c79ea47fb39afa03f877542c8c2e0d0 100644 --- a/xxdk/identity.go +++ b/xxdk/identity.go @@ -8,6 +8,8 @@ package xxdk import ( "encoding/json" + "gitlab.com/elixxir/primitives/fact" + "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/contact" @@ -34,13 +36,13 @@ type ReceptionIdentity struct { // StoreReceptionIdentity stores the given identity in Cmix storage with the given key // This is the ideal way to securely store identities, as the caller of this function // is only required to store the given key separately rather than the keying material -func StoreReceptionIdentity(key string, identity ReceptionIdentity, client *Cmix) error { +func StoreReceptionIdentity(key string, identity ReceptionIdentity, net *Cmix) error { marshalledIdentity, err := identity.Marshal() if err != nil { return err } - return client.GetStorage().Set(key, &versioned.Object{ + return net.GetStorage().Set(key, &versioned.Object{ Version: idVersion, Timestamp: netTime.Now(), Data: marshalledIdentity, @@ -48,8 +50,8 @@ func StoreReceptionIdentity(key string, identity ReceptionIdentity, client *Cmix } // LoadReceptionIdentity loads the given identity in Cmix storage with the given key -func LoadReceptionIdentity(key string, client *Cmix) (ReceptionIdentity, error) { - storageObj, err := client.GetStorage().Get(key) +func LoadReceptionIdentity(key string, net *Cmix) (ReceptionIdentity, error) { + storageObj, err := net.GetStorage().Get(key) if err != nil { return ReceptionIdentity{}, err } @@ -89,10 +91,10 @@ func (r ReceptionIdentity) GetGroup() (*cyclic.Group, error) { // MakeReceptionIdentity generates a new cryptographic identity // for receiving messages. -func MakeReceptionIdentity(client *Cmix) (ReceptionIdentity, error) { - rng := client.GetRng().GetStream() +func MakeReceptionIdentity(net *Cmix) (ReceptionIdentity, error) { + rng := net.GetRng().GetStream() defer rng.Close() - grp := client.GetStorage().GetE2EGroup() + grp := net.GetStorage().GetE2EGroup() //make RSA Key rsaKey, err := rsa.GenerateKey(rng, @@ -140,6 +142,14 @@ func MakeReceptionIdentity(client *Cmix) (ReceptionIdentity, error) { return I, nil } +// MakeLegacyReceptionIdentity generates the cryptographic identity +// for receiving messages based on the extant stored user.Info +func MakeLegacyReceptionIdentity(net *Cmix) (ReceptionIdentity, error) { + userInfo := net.GetStorage().PortableUserInfo() + return buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt, + userInfo.ReceptionRSA, net.GetStorage().GetE2EGroup(), userInfo.E2eDhPrivateKey) +} + // DeepCopy produces a safe copy of a ReceptionIdentity func (r ReceptionIdentity) DeepCopy() ReceptionIdentity { saltCopy := make([]byte, len(r.Salt)) @@ -164,12 +174,11 @@ func (r ReceptionIdentity) GetContact() contact.Contact { grp, _ := r.GetGroup() dhKeyPriv, _ := r.GetDHKeyPrivate() - dhPub := grp.ExpG(dhKeyPriv, grp.NewInt(1)) ct := contact.Contact{ ID: r.ID, - DhPubKey: dhPub, + DhPubKey: diffieHellman.GeneratePublicKey(dhKeyPriv, grp), OwnershipProof: nil, - Facts: nil, + Facts: make([]fact.Fact, 0), } return ct } diff --git a/xxdk/precan.go b/xxdk/precan.go index e0e008e85863ce52ee53926eac8e8f8c69518ac4..98edf51028937e17a0e555c7de1d91b60a3ff35b 100644 --- a/xxdk/precan.go +++ b/xxdk/precan.go @@ -9,60 +9,26 @@ package xxdk import ( "encoding/binary" + "math/rand" + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" util "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/crypto/contact" - "gitlab.com/elixxir/crypto/cyclic" - "gitlab.com/elixxir/crypto/diffieHellman" - "gitlab.com/elixxir/primitives/fact" - "math/rand" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage" - "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/crypto/csprng" - "gitlab.com/xx_network/crypto/signature/rsa" - "gitlab.com/xx_network/primitives/id" ) -// CreatePrecannedUser creates a precanned user -func CreatePrecannedUser(precannedID uint, rng csprng.Source) user.Info { - - // Salt, UID, etc gen - salt := make([]byte, SaltSize) - - userID := id.ID{} - binary.BigEndian.PutUint64(userID[:], uint64(precannedID)) - userID.SetType(id.User) - - // NOTE: not used... RSA Keygen (4096 bit defaults) - rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - - return user.Info{ - TransmissionID: &userID, - TransmissionSalt: salt, - ReceptionID: &userID, - ReceptionSalt: salt, - Precanned: true, - E2eDhPrivateKey: nil, - E2eDhPublicKey: nil, - TransmissionRSA: rsaKey, - ReceptionRSA: rsaKey, - } -} - // NewPrecannedClient creates an insecure user with predetermined keys // with nodes It creates client storage, generates keys, connects, and // registers with the network. Note that this does not register a // username/identity, but merely creates a new cryptographic identity // for adding such information at a later date. func NewPrecannedClient(precannedID uint, defJSON, storageDir string, - password []byte) (ReceptionIdentity, error) { + password []byte) error { jww.INFO.Printf("NewPrecannedClient()") rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) @@ -70,51 +36,43 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, def, err := ParseNDF(defJSON) if err != nil { - return ReceptionIdentity{}, err + return err } cmixGrp, e2eGrp := DecodeGroups(def) - dhPrivKey := generatePrecanDHKeypair(precannedID, e2eGrp) - - userInfo := CreatePrecannedUser(precannedID, rngStream) - identity, err := buildReceptionIdentity(userInfo.ReceptionID, userInfo.ReceptionSalt, - userInfo.ReceptionRSA, e2eGrp, dhPrivKey) - if err != nil { - return ReceptionIdentity{}, err - } - + userInfo := createPrecannedUser(precannedID, rngStream, e2eGrp) store, err := CheckVersionAndSetupStorage(def, storageDir, password, userInfo, cmixGrp, e2eGrp, "") if err != nil { - return ReceptionIdentity{}, err + return err } // Mark the precanned user as finished with permissioning and registered // with the network. err = store.ForwardRegistrationStatus(storage.PermissioningComplete) if err != nil { - return ReceptionIdentity{}, err + return err } - return identity, err -} - -func generatePrecanDHKeypair(precannedID uint, e2eGrp *cyclic.Group) *cyclic.Int { - // DH Keygen - prng := rand.New(rand.NewSource(int64(precannedID))) - prime := e2eGrp.GetPBytes() - keyLen := len(prime) - priv := diffieHellman.GeneratePrivateKey(keyLen, e2eGrp, prng) - return priv + return err } -// Create an insecure e2e relationship with a precanned user +// MakePrecannedAuthenticatedChannel creates an insecure e2e relationship with a precanned user func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( contact.Contact, error) { - precan := m.MakePrecannedContact(precannedID) + rng := m.GetRng().GetStream() + precanUserInfo := createPrecannedUser(precannedID, rng, m.GetStorage().GetE2EGroup()) + rng.Close() + precanRecipient, err := buildReceptionIdentity(precanUserInfo.ReceptionID, + precanUserInfo.ReceptionSalt, precanUserInfo.ReceptionRSA, + m.GetStorage().GetE2EGroup(), precanUserInfo.E2eDhPrivateKey) + if err != nil { + return contact.Contact{}, err + } + precanContact := precanRecipient.GetContact() - myID := binary.BigEndian.Uint64(m.GetStorage().GetReceptionID()[:]) + myID := binary.BigEndian.Uint64(m.GetReceptionIdentity().ID[:]) // Pick a variant based on if their ID is bigger than mine. myVariant := sidh.KeyVariantSidhA theirVariant := sidh.KeyVariant(sidh.KeyVariantSidhB) @@ -125,19 +83,25 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( prng1 := rand.New(rand.NewSource(int64(precannedID))) theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant) theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant) - theirSIDHPrivKey.Generate(prng1) + err = theirSIDHPrivKey.Generate(prng1) + if err != nil { + return contact.Contact{}, err + } theirSIDHPrivKey.GeneratePublicKey(theirSIDHPubKey) prng2 := rand.New(rand.NewSource(int64(myID))) mySIDHPrivKey := util.NewSIDHPrivateKey(myVariant) mySIDHPubKey := util.NewSIDHPublicKey(myVariant) - mySIDHPrivKey.Generate(prng2) + err = mySIDHPrivKey.Generate(prng2) + if err != nil { + return contact.Contact{}, err + } mySIDHPrivKey.GeneratePublicKey(mySIDHPubKey) // add the precanned user as a e2e contact // FIXME: these params need to be threaded through... sesParam := session.GetDefaultParams() - _, err := m.e2e.AddPartner(precan.ID, precan.DhPubKey, + _, err = m.e2e.AddPartner(precanContact.ID, precanContact.DhPubKey, m.e2e.GetHistoricalDHPrivkey(), theirSIDHPubKey, mySIDHPrivKey, sesParam, sesParam) @@ -145,29 +109,5 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( // the channel m.GetCmix().CheckInProgressMessages() - return precan, err -} - -// Create an insecure e2e contact object for a precanned user -func (m *E2e) MakePrecannedContact(precannedID uint) contact.Contact { - - e2eGrp := m.GetStorage().GetE2EGroup() - - rng := m.GetRng().GetStream() - precanned := CreatePrecannedUser(precannedID, rng) - rng.Close() - - precanned.E2eDhPrivateKey = generatePrecanDHKeypair(precannedID, - m.GetStorage().GetE2EGroup()) - - // compute their public e2e key - partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey, - e2eGrp.NewInt(1)) - - return contact.Contact{ - ID: precanned.ReceptionID, - DhPubKey: partnerPubKey, - OwnershipProof: nil, - Facts: make([]fact.Fact, 0), - } + return precanContact, err } diff --git a/xxdk/user.go b/xxdk/user.go index 4eb421050ed68c242dff2b1f509d01b41c05cdc8..747fb3dbef16f64e0bb47cece6896b51477218da 100644 --- a/xxdk/user.go +++ b/xxdk/user.go @@ -8,6 +8,8 @@ package xxdk import ( + "encoding/binary" + "math/rand" "regexp" "runtime" "strings" @@ -31,13 +33,13 @@ const ( ) // createNewUser generates an identity for cMix -func createNewUser(rng *fastRNG.StreamGenerator) user.Info { +func createNewUser(rng *fastRNG.StreamGenerator, e2eGroup *cyclic.Group) user.Info { // CMIX Keygen var transmissionRsaKey, receptionRsaKey *rsa.PrivateKey var transmissionSalt, receptionSalt []byte - transmissionSalt, receptionSalt, - transmissionRsaKey, receptionRsaKey = createKeys(rng) + e2eKeyBytes, transmissionSalt, receptionSalt, + transmissionRsaKey, receptionRsaKey := createKeys(rng, e2eGroup) transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) @@ -51,6 +53,7 @@ func createNewUser(rng *fastRNG.StreamGenerator) user.Info { jww.FATAL.Panicf(err.Error()) } + dhPrivKey := e2eGroup.NewIntFromBytes(e2eKeyBytes) return user.Info{ TransmissionID: transmissionID.DeepCopy(), TransmissionSalt: transmissionSalt, @@ -59,29 +62,44 @@ func createNewUser(rng *fastRNG.StreamGenerator) user.Info { ReceptionSalt: receptionSalt, ReceptionRSA: receptionRsaKey, Precanned: false, - E2eDhPrivateKey: nil, - E2eDhPublicKey: nil, + E2eDhPrivateKey: dhPrivKey, + E2eDhPublicKey: diffieHellman.GeneratePublicKey(dhPrivKey, e2eGroup), } } -func createKeys(rng *fastRNG.StreamGenerator) ( +func createKeys(rng *fastRNG.StreamGenerator, + e2e *cyclic.Group) (e2eKeyBytes, transmissionSalt, receptionSalt []byte, transmissionRsaKey, receptionRsaKey *rsa.PrivateKey) { wg := sync.WaitGroup{} - wg.Add(2) + wg.Add(3) + + go func() { + defer wg.Done() + var err error + // DH Keygen + // FIXME: Why 256 bits? -- this is spec but not explained, it has + // to do with optimizing operations on one side and still preserves + // decent security -- cite this. Why valid for BOTH e2e and cmix? + stream := rng.GetStream() + e2eKeyBytes, err = csprng.GenerateInGroup(e2e.GetPBytes(), 256, stream) + stream.Close() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + }() // RSA Keygen (4096 bit defaults) go func() { defer wg.Done() var err error stream := rng.GetStream() - transmissionRsaKey, err = rsa.GenerateKey(stream, - rsa.DefaultRSABitLen) + transmissionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) if err != nil { jww.FATAL.Panicf(err.Error()) } - transmissionSalt = make([]byte, 32) + transmissionSalt = make([]byte, SaltSize) _, err = stream.Read(transmissionSalt) stream.Close() if err != nil { @@ -93,12 +111,11 @@ func createKeys(rng *fastRNG.StreamGenerator) ( defer wg.Done() var err error stream := rng.GetStream() - receptionRsaKey, err = rsa.GenerateKey(stream, - rsa.DefaultRSABitLen) + receptionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) if err != nil { jww.FATAL.Panicf(err.Error()) } - receptionSalt = make([]byte, 32) + receptionSalt = make([]byte, SaltSize) _, err = stream.Read(receptionSalt) stream.Close() if err != nil { @@ -107,28 +124,13 @@ func createKeys(rng *fastRNG.StreamGenerator) ( }() wg.Wait() - isZero := func(data []byte) bool { - if len(data) == 0 { - return true - } - for i := len(data) - 1; i != 0; i-- { - if data[i] != 0 { - return false - } - } - return true - } - - if isZero(receptionSalt) || isZero(transmissionSalt) { - jww.FATAL.Panicf("empty salt generation detected") - } return } // createNewVanityUser generates an identity for cMix // The identity's ReceptionID is not random but starts with the supplied prefix -func createNewVanityUser(rng csprng.Source, cmix, +func createNewVanityUser(rng csprng.Source, e2e *cyclic.Group, prefix string) user.Info { // DH Keygen prime := e2e.GetPBytes() @@ -194,7 +196,7 @@ func createNewVanityUser(rng csprng.Source, cmix, for { select { case <-done: - defer wg.Done() + wg.Done() return default: n, err = csprng.NewSystemRNG().Read( @@ -214,17 +216,17 @@ func createNewVanityUser(rng csprng.Source, cmix, if err != nil { jww.FATAL.Panicf(err.Error()) } - id := rID.String() + rid := rID.String() if ignoreCase { - id = strings.ToLower(id) + rid = strings.ToLower(rid) } - if strings.HasPrefix(id, pref) { + if strings.HasPrefix(rid, pref) { mu.Lock() receptionID = rID receptionSalt = rSalt mu.Unlock() found <- true - defer wg.Done() + wg.Done() return } } @@ -248,3 +250,35 @@ func createNewVanityUser(rng csprng.Source, cmix, E2eDhPublicKey: diffieHellman.GeneratePublicKey(e2eKey, e2e), } } + +// createPrecannedUser +func createPrecannedUser(precannedID uint, rng csprng.Source, grp *cyclic.Group) user.Info { + // Salt, UID, etc gen + salt := make([]byte, SaltSize) + + userID := id.ID{} + binary.BigEndian.PutUint64(userID[:], uint64(precannedID)) + userID.SetType(id.User) + + // NOTE: not used... RSA Keygen (4096 bit defaults) + rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + prime := grp.GetPBytes() + keyLen := len(prime) + prng := rand.New(rand.NewSource(int64(precannedID))) + dhPrivKey := diffieHellman.GeneratePrivateKey(keyLen, grp, prng) + return user.Info{ + TransmissionID: &userID, + TransmissionSalt: salt, + ReceptionID: &userID, + ReceptionSalt: salt, + Precanned: true, + E2eDhPrivateKey: dhPrivKey, + E2eDhPublicKey: diffieHellman.GeneratePublicKey(dhPrivKey, grp), + TransmissionRSA: rsaKey, + ReceptionRSA: rsaKey, + } +} diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go index 0f8b6a565b0903fd8ea98b279610a0e307902383..0ec8e38c00b8b2a7693921f88651c633ad643525 100644 --- a/xxmutils/restoreContacts.go +++ b/xxmutils/restoreContacts.go @@ -37,7 +37,7 @@ import ( // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e, +func RestoreContactsFromBackup(backupPartnerIDs []byte, messenger *xxdk.E2e, udManager *ud.Manager, updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID, []error, error) { @@ -63,7 +63,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e, } store := stateStore{ - apiStore: client.GetStorage(), + apiStore: messenger.GetStorage(), } // Unmarshal IDs and then check restore state @@ -99,8 +99,8 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e, rsWg := &sync.WaitGroup{} rsWg.Add(numRoutines) for i := 0; i < numRoutines; i++ { - go LookupContacts(lookupCh, foundCh, failCh, client, udContact, lcWg) - go ResetSessions(resetContactCh, restoredCh, failCh, client, + go LookupContacts(lookupCh, foundCh, failCh, messenger, udContact, lcWg) + go ResetSessions(resetContactCh, restoredCh, failCh, messenger, rsWg) } @@ -178,13 +178,13 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *xxdk.E2e, // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func LookupContacts(in chan *id.ID, out chan *contact.Contact, - failCh chan failure, client *xxdk.E2e, udContact contact.Contact, + failCh chan failure, messenger *xxdk.E2e, udContact contact.Contact, wg *sync.WaitGroup) { defer wg.Done() // Start looking up contacts with user discovery and feed this // contacts channel. for lookupID := range in { - c, err := LookupContact(lookupID, client, udContact) + c, err := LookupContact(lookupID, messenger, udContact) if err == nil { out <- c continue @@ -205,10 +205,10 @@ func LookupContacts(in chan *id.ID, out chan *contact.Contact, // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func ResetSessions(in, out chan *contact.Contact, failCh chan failure, - client *xxdk.E2e, wg *sync.WaitGroup) { + messenger *xxdk.E2e, wg *sync.WaitGroup) { defer wg.Done() for c := range in { - _, err := client.GetAuth().Reset(*c) + _, err := messenger.GetAuth().Reset(*c) if err == nil { out <- c continue @@ -224,7 +224,7 @@ func ResetSessions(in, out chan *contact.Contact, failCh chan failure, // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func LookupContact(userID *id.ID, client *xxdk.E2e, udContact contact.Contact) ( +func LookupContact(userID *id.ID, messenger *xxdk.E2e, udContact contact.Contact) ( *contact.Contact, error) { // This is a little wonky, but wait until we get called then // set the result to the contact objects details if there is @@ -243,9 +243,9 @@ func LookupContact(userID *id.ID, client *xxdk.E2e, udContact contact.Contact) ( waiter.Lock() // in MS, so 90 seconds - stream := client.GetRng().GetStream() + stream := messenger.GetRng().GetStream() defer stream.Close() - _, _, err = ud.Lookup(client.GetCmix(), stream, client.GetE2E().GetGroup(), + _, _, err = ud.Lookup(messenger.GetCmix(), stream, messenger.GetE2E().GetGroup(), udContact, lookupCB, userID, single.GetDefaultRequestParams()) // Now force a wait for callback to exit