diff --git a/README.md b/README.md index a5041e876b23c787616d2f260830f2aca19de0d3..cb6d69e09ad7aab6c7676b2aae8c310539d286b4 100644 --- a/README.md +++ b/README.md @@ -145,59 +145,49 @@ Usage: client [command] Available Commands: - generate Generates version and dependency information for the - Elixxir binary + generate Generates version and dependency information for the Elixxir binary + getndf Download the network definition file from the network and print it. + group Group commands for cMix client help Help about any command - version Print the version and dependency information for the - Elixxir binary + init Initialize a user ID but do not connect to the network + proto Load client with a proto client JSON file. + single Send and respond to single-use messages. + ud Register for and search users using the xx network user discovery service. + version Print the version and dependency information for the Elixxir binary Flags: - --accept-channel Accept the channel request for the - corresponding recipient ID - --delete-channel Delete the channel information for the - corresponding recipient ID + --accept-channel Accept the channel request for the corresponding recipient ID + --auth-timeout uint The number of seconds to wait for an authentication channelto confirm (default 120) + --delete-channel Delete the channel information for the corresponding recipient ID --destfile string Read this contact file for the destination id - -d, --destid string ID to send message to (if below 40, will be - precanned. Use '0x' or 'b64:' for hex and - base64 representations) (default "0") - --forceHistoricalRounds Force all rounds to be sent to historical - round retrieval - --forceMessagePickupRetry Enable a mechanism which forces a 50% chance - of no message pickup, instead triggering the - message pickup retry mechanism + -d, --destid string ID to send message to (if below 40, will be precanned. Use '0x' or 'b64:' for hex and base64 representations) (default "0") + --e2eMaxKeys uint Max keys used before blocking until a rekey completes (default 800) + --e2eMinKeys uint Minimum number of keys used before requesting rekey (default 500) + --e2eNumReKeys uint Number of rekeys reserved for rekey operations (default 16) + --forceHistoricalRounds Force all rounds to be sent to historical round retrieval + --forceMessagePickupRetry Enable a mechanism which forces a 50% chance of no message pickup, instead triggering the message pickup retry mechanism -h, --help help for client - -l, --log string Path to the log output path (- is stdout) - (default "-") + -l, --log string Path to the log output path (- is stdout) (default "-") + -v, --logLevel uint Verbose mode for debugging -m, --message string Message to send - -n, --ndf string Path to the network definition JSON file - (default "ndf.json") + -n, --ndf string Path to the network definition JSON file (default "ndf.json") -p, --password string Password to the session file - --receiveCount uint How many messages we should wait for before - quitting (default 1) - --regcode string Registration code (optional) - --sendCount uint The number of times to send the message - (default 1) - --sendDelay uint The delay between sending the messages in ms - (default 500) - --sendid uint Use precanned user id (must be between 1 and - 40, inclusive) - --slowPolling bool Enables polling for all network updates and RSA signed rounds. - Defaults to true (filtered updates with ECC signed rounds) if not set - - -s, --session string Sets the initial directory for client storage - --unsafe Send raw, unsafe messages without e2e - encryption. - --unsafe-channel-creation Turns off the user identity authenticated - channel check, automatically approving - authenticated channels - --verboseRoundTracking Verbose round tracking, keeps track and prints - all rounds the client was aware of while running. - Defaults to false if not set. - -v, --logLevel uint Level of debugging to print (0 = info, - 1 = debug, >1 = trace). (Default info) - --waitTimeout uint The number of seconds to wait for messages to - arrive (default 15) - -w, --writeContact string Write the contact file for this user to this + --profile-cpu string Enable cpu profiling to this file + --protoUserOut string Path to which a normally constructed client will write proto user JSON file (default "protoUser.json") + --protoUserPath string Path to proto user JSON file containing cryptographic primitives the client will load (default "protoUser.json") + --receiveCount uint How many messages we should wait for before quitting (default 1) + --regcode string Identity code (optional) + --send-auth-request Send an auth request to the specified destination and waitfor confirmation + --sendCount uint The number of times to send the message (default 1) + --sendDelay uint The delay between sending the messages in ms (default 500) + --sendid uint Use precanned user id (must be between 1 and 40, inclusive) + -s, --session string Sets the initial storage directory for client session data + --slowPolling Enables polling for unfiltered network updates with RSA signatures + --unsafe Send raw, unsafe messages without e2e encryption. + --unsafe-channel-creation Turns off the user identity authenticated channel check, automatically approving authenticated channels + --verboseRoundTracking Verbose round tracking, keeps track and prints all rounds the client was aware of while running. Defaults to false if not set. + --waitTimeout uint The number of seconds to wait for messages to arrive (default 15) + -w, --writeContact string Write contact information, if any, to this file, defaults to stdout (default "-") file Use "client [command] --help" for more information about a command. diff --git a/api/client.go b/api/client.go index 7919c62b869f1befb9a7567022bdc51475e8b4c2..3cedff02094d341e55735773867ae1f1e04fbbea 100644 --- a/api/client.go +++ b/api/client.go @@ -8,6 +8,7 @@ package api import ( + "encoding/json" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/auth" @@ -74,7 +75,8 @@ type Client struct { // 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 NewClient(ndfJSON, storageDir string, password []byte, registrationCode string) error { +func NewClient(ndfJSON, storageDir string, password []byte, + registrationCode string) error { jww.INFO.Printf("NewClient(dir: %s)", storageDir) // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) @@ -90,7 +92,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str protoUser := createNewUser(rngStreamGen, cmixGrp, e2eGrp) jww.DEBUG.Printf("User generation took: %s", time.Now().Sub(start)) - err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) if err != nil { return err @@ -105,7 +107,8 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str // 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) error { +func NewPrecannedClient(precannedID uint, defJSON, storageDir string, + password []byte) error { jww.INFO.Printf("NewPrecannedClient()") // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) @@ -120,7 +123,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ protoUser := createPrecannedUser(precannedID, rngStream, cmixGrp, e2eGrp) - err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, rngStreamGen, true, "") if err != nil { return err @@ -134,7 +137,8 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ // 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 NewVanityClient(ndfJSON, storageDir string, password []byte, registrationCode string, userIdPrefix string) error { +func NewVanityClient(ndfJSON, storageDir string, password []byte, + registrationCode string, userIdPrefix string) error { jww.INFO.Printf("NewVanityClient()") // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG) @@ -149,7 +153,7 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, registrationCo protoUser := createNewVanityUser(rngStream, cmixGrp, e2eGrp, userIdPrefix) - err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, + _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) if err != nil { return err @@ -195,6 +199,55 @@ func OpenClient(storageDir string, password []byte, parameters params.Network) ( return c, nil } +// NewProtoClient_Unsafe initializes a client object from a JSON containing +// 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, + protoClientJSON []byte) error { + jww.INFO.Printf("NewProtoClient_Unsafe") + + // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) + rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) + + // Parse the NDF + def, err := parseNDF(ndfJSON) + if err != nil { + return err + } + + cmixGrp, e2eGrp := decodeGroups(def) + + // Pull the proto user from the JSON + protoUser := &user.Proto{} + err = json.Unmarshal(protoClientJSON, protoUser) + if err != nil { + return err + } + + // Initialize a user object for storage set up + usr := user.NewUserFromProto(protoUser) + + // Set up storage + storageSess, err := checkVersionAndSetupStorage(def, storageDir, password, usr, + cmixGrp, e2eGrp, rngStreamGen, false, protoUser.RegCode) + if err != nil { + return err + } + + // Set registration values in storage + storageSess.User().SetReceptionRegistrationValidationSignature(protoUser.ReceptionRegValidationSig) + storageSess.User().SetTransmissionRegistrationValidationSignature(protoUser.TransmissionRegValidationSig) + storageSess.User().SetRegistrationTimestamp(protoUser.RegistrationTimestamp) + + //move the registration state to indicate registered with registration on proto client + err = storageSess.ForwardRegistrationStatus(storage.PermissioningComplete) + if err != nil { + return err + } + + return nil +} + // Login initializes a client object from existing storage. func Login(storageDir string, password []byte, parameters params.Network) (*Client, error) { jww.INFO.Printf("Login()") @@ -236,7 +289,8 @@ func Login(storageDir string, password []byte, parameters params.Network) (*Clie hp.KaClientOpts.Time = time.Duration(math.MaxInt64) hp.AuthEnabled = false hp.MaxRetries = 5 - _, err = c.comms.AddHost(&id.NotificationBot, def.Notification.Address, []byte(def.Notification.TlsCertificate), hp) + _, err = c.comms.AddHost(&id.NotificationBot, def.Notification.Address, + []byte(def.Notification.TlsCertificate), hp) if err != nil { jww.WARN.Printf("Failed adding host for notifications: %+v", err) } @@ -382,7 +436,9 @@ func (c *Client) registerFollower() error { } //register the core follower service - err = c.followerServices.add(func() (stoppable.Stoppable, error) { return c.network.Follow(cer) }) + err = c.followerServices.add(func() (stoppable.Stoppable, error) { + return c.network.Follow(cer) + }) if err != nil { return errors.WithMessage(err, "Failed to start following "+ "the network") @@ -698,13 +754,15 @@ func decodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) { // checkVersionAndSetupStorage is common code shared by NewClient, NewPrecannedClient and NewVanityClient // it checks client version and creates a new storage for user data -func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, password []byte, - protoUser user.User, cmixGrp, e2eGrp *cyclic.Group, rngStreamGen *fastRNG.StreamGenerator, - isPrecanned bool, registrationCode string) error { +func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, + storageDir string, password []byte, + protoUser user.User, + cmixGrp, e2eGrp *cyclic.Group, rngStreamGen *fastRNG.StreamGenerator, + isPrecanned bool, registrationCode string) (*storage.Session, error) { // Get current client version currentVersion, err := version.ParseVersion(SEMVER) if err != nil { - return errors.WithMessage(err, "Could not parse version string.") + return nil, errors.WithMessage(err, "Could not parse version string.") } // Create Storage @@ -712,7 +770,7 @@ func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, storageSess, err := storage.New(storageDir, passwordStr, protoUser, currentVersion, cmixGrp, e2eGrp, rngStreamGen) if err != nil { - return err + return nil, err } // Save NDF to be used in the future @@ -736,9 +794,9 @@ func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, }, protoUser.ReceptionID) if err != nil { - return errors.WithMessage(err, "Failed to denote state "+ + return nil, errors.WithMessage(err, "Failed to denote state "+ "change in session") } - return nil + return storageSess, nil } diff --git a/api/notifications.go b/api/notifications.go index 2a7d1b7c107128360f89930c8bf0bcb16dfc54de..58e97190e469a7d21d9175b9b84ddaff89b75e2c 100644 --- a/api/notifications.go +++ b/api/notifications.go @@ -43,7 +43,7 @@ func (c *Client) RegisterForNotifications(token string) error { TransmissionSalt: c.GetUser().TransmissionSalt, TransmissionRsaSig: c.GetStorage().User().GetTransmissionRegistrationValidationSignature(), IIDTransmissionRsaSig: sig, - RegistrationTimestamp: c.GetUser().RegistrationTimestamp.UnixNano(), + RegistrationTimestamp: c.GetUser().RegistrationTimestamp, }) if err != nil { err := errors.Errorf( diff --git a/api/permissioning.go b/api/permissioning.go index ef94e61daf315472ecde87eddc360335c08b445d..85aac34b93f333f4994c49b1dac1ec868965807a 100644 --- a/api/permissioning.go +++ b/api/permissioning.go @@ -8,7 +8,9 @@ package api import ( + "encoding/json" "github.com/pkg/errors" + "gitlab.com/elixxir/client/interfaces/user" "gitlab.com/elixxir/client/storage" ) @@ -47,3 +49,41 @@ func (c *Client) registerWithPermissioning() error { } return nil } + +// ConstructProtoUerFile is a helper function which is used for proto client testing. +// This is used for development testing. +func (c *Client) ConstructProtoUerFile() ([]byte, error) { + + //load the registration code + regCode, err := c.storage.GetRegCode() + if err != nil { + return nil, errors.WithMessage(err, "failed to register with "+ + "permissioning") + } + + Usr := user.Proto{ + TransmissionID: c.GetUser().TransmissionID, + TransmissionSalt: c.GetUser().TransmissionSalt, + TransmissionRSA: c.GetUser().TransmissionRSA, + ReceptionID: c.GetUser().ReceptionID, + ReceptionSalt: c.GetUser().ReceptionSalt, + ReceptionRSA: c.GetUser().ReceptionRSA, + Precanned: c.GetUser().Precanned, + RegistrationTimestamp: c.GetUser().RegistrationTimestamp, + RegCode: regCode, + TransmissionRegValidationSig: c.storage.User().GetTransmissionRegistrationValidationSignature(), + ReceptionRegValidationSig: c.storage.User().GetReceptionRegistrationValidationSignature(), + CmixDhPrivateKey: c.GetStorage().Cmix().GetDHPrivateKey(), + CmixDhPublicKey: c.GetStorage().Cmix().GetDHPublicKey(), + E2eDhPrivateKey: c.GetStorage().E2e().GetDHPrivateKey(), + E2eDhPublicKey: c.GetStorage().E2e().GetDHPublicKey(), + } + + jsonBytes, err := json.Marshal(Usr) + if err != nil { + return nil, errors.WithMessage(err, "failed to register with "+ + "permissioning") + } + + return jsonBytes, nil +} diff --git a/api/user.go b/api/user.go index ef8eb1092ee61e8e766c00d2979cb4c20d108d82..1b22a0877235636c55bbd2be922cddfcf4fe2b39 100644 --- a/api/user.go +++ b/api/user.go @@ -36,6 +36,62 @@ func createNewUser(rng *fastRNG.StreamGenerator, cmix, e2e *cyclic.Group) user.U var cMixKeyBytes, e2eKeyBytes, transmissionSalt, receptionSalt []byte + cMixKeyBytes, e2eKeyBytes, transmissionSalt, receptionSalt, + transmissionRsaKey, receptionRsaKey = createDhKeys(rng, cmix, e2e) + + // Salt, UID, etc gen + stream := rng.GetStream() + transmissionSalt = make([]byte, SaltSize) + + n, err := stream.Read(transmissionSalt) + + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + if n != SaltSize { + jww.FATAL.Panicf("transmissionSalt size too small: %d", n) + } + + receptionSalt = make([]byte, SaltSize) + + n, err = stream.Read(receptionSalt) + + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + if n != SaltSize { + jww.FATAL.Panicf("transmissionSalt size too small: %d", n) + } + + stream.Close() + + transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + + return user.User{ + TransmissionID: transmissionID.DeepCopy(), + TransmissionSalt: transmissionSalt, + TransmissionRSA: transmissionRsaKey, + ReceptionID: receptionID.DeepCopy(), + ReceptionSalt: receptionSalt, + ReceptionRSA: receptionRsaKey, + Precanned: false, + CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes), + E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), + } +} + +func createDhKeys(rng *fastRNG.StreamGenerator, + cmix, e2e *cyclic.Group) (cMixKeyBytes, e2eKeyBytes, + transmissionSalt, receptionSalt []byte, + transmissionRsaKey, receptionRsaKey *rsa.PrivateKey) { wg := sync.WaitGroup{} wg.Add(4) @@ -93,53 +149,8 @@ func createNewUser(rng *fastRNG.StreamGenerator, cmix, e2e *cyclic.Group) user.U }() wg.Wait() - // Salt, UID, etc gen - stream := rng.GetStream() - transmissionSalt = make([]byte, SaltSize) - - n, err := stream.Read(transmissionSalt) - - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - if n != SaltSize { - jww.FATAL.Panicf("transmissionSalt size too small: %d", n) - } - - receptionSalt = make([]byte, SaltSize) - - n, err = stream.Read(receptionSalt) - - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - if n != SaltSize { - jww.FATAL.Panicf("transmissionSalt size too small: %d", n) - } - - stream.Close() - - transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - - receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } + return - return user.User{ - TransmissionID: transmissionID.DeepCopy(), - TransmissionSalt: transmissionSalt, - TransmissionRSA: transmissionRsaKey, - ReceptionID: receptionID.DeepCopy(), - ReceptionSalt: receptionSalt, - ReceptionRSA: receptionRsaKey, - Precanned: false, - CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes), - E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes), - } } // TODO: Add precanned user code structures here. diff --git a/cmd/root.go b/cmd/root.go index 23416872ee7e210fbe6b886bee12788a17d0e1bc..a2c9db19265e702aec3c5d268185cd2156b3b8dd 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -23,6 +23,7 @@ import ( "gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/utils" "io/ioutil" "log" "os" @@ -382,6 +383,8 @@ func createClient() *api.Client { regCode := viper.GetString("regcode") precannedID := viper.GetUint("sendid") userIDprefix := viper.GetString("userid-prefix") + protoUserPath := viper.GetString("protoUserPath") + //create a new client if none exist if _, err := os.Stat(storeDir); os.IsNotExist(err) { // Load NDF @@ -394,14 +397,19 @@ func createClient() *api.Client { if precannedID != 0 { err = api.NewPrecannedClient(precannedID, string(ndfJSON), storeDir, []byte(pass)) - } else { - if userIDprefix != "" { - err = api.NewVanityClient(string(ndfJSON), storeDir, - []byte(pass), regCode, userIDprefix) - } else { - err = api.NewClient(string(ndfJSON), storeDir, - []byte(pass), regCode) + } else if protoUserPath != "" { + protoUserJson, err := utils.ReadFile(protoUserPath) + if err != nil { + jww.FATAL.Panicf("%v", err) } + err = api.NewProtoClient_Unsafe(string(ndfJSON), storeDir, + []byte(pass), protoUserJson) + } else if userIDprefix != "" { + err = api.NewVanityClient(string(ndfJSON), storeDir, + []byte(pass), regCode, userIDprefix) + } else { + err = api.NewClient(string(ndfJSON), storeDir, + []byte(pass), regCode) } if err != nil { @@ -431,7 +439,7 @@ func initClient() *api.Client { pass := viper.GetString("password") storeDir := viper.GetString("session") - + jww.DEBUG.Printf("sessionDur: %v", storeDir) netParams := params.GetDefaultNetwork() netParams.E2EParams.MinKeys = uint16(viper.GetUint("e2eMinKeys")) netParams.E2EParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys")) @@ -453,6 +461,20 @@ func initClient() *api.Client { jww.FATAL.Panicf("%+v", err) } + if protoUser := viper.GetString("protoUserOut"); protoUser != "" { + + jsonBytes, err := client.ConstructProtoUerFile() + if err != nil { + jww.FATAL.Panicf("Failed to construct proto user file: %v", err) + } + + err = utils.WriteFileDef(protoUser, jsonBytes) + if err != nil { + jww.FATAL.Panicf("Failed to write proto user to file: %v", err) + } + + } + return client } @@ -823,30 +845,30 @@ func init() { rootCmd.Flags().UintP("receiveCount", "", 1, "How many messages we should wait for before quitting") viper.BindPFlag("receiveCount", rootCmd.Flags().Lookup("receiveCount")) - rootCmd.Flags().UintP("waitTimeout", "", 15, + rootCmd.PersistentFlags().UintP("waitTimeout", "", 15, "The number of seconds to wait for messages to arrive") viper.BindPFlag("waitTimeout", - rootCmd.Flags().Lookup("waitTimeout")) + rootCmd.PersistentFlags().Lookup("waitTimeout")) rootCmd.Flags().BoolP("unsafe", "", false, "Send raw, unsafe messages without e2e encryption.") viper.BindPFlag("unsafe", rootCmd.Flags().Lookup("unsafe")) - rootCmd.Flags().BoolP("unsafe-channel-creation", "", false, + rootCmd.PersistentFlags().BoolP("unsafe-channel-creation", "", false, "Turns off the user identity authenticated channel check, "+ "automatically approving authenticated channels") viper.BindPFlag("unsafe-channel-creation", - rootCmd.Flags().Lookup("unsafe-channel-creation")) + rootCmd.PersistentFlags().Lookup("unsafe-channel-creation")) rootCmd.Flags().BoolP("accept-channel", "", false, "Accept the channel request for the corresponding recipient ID") viper.BindPFlag("accept-channel", rootCmd.Flags().Lookup("accept-channel")) - rootCmd.Flags().Bool("delete-channel", false, + rootCmd.PersistentFlags().Bool("delete-channel", false, "Delete the channel information for the corresponding recipient ID") viper.BindPFlag("delete-channel", - rootCmd.Flags().Lookup("delete-channel")) + rootCmd.PersistentFlags().Lookup("delete-channel")) rootCmd.Flags().BoolP("send-auth-request", "", false, "Send an auth request to the specified destination and wait"+ @@ -893,6 +915,17 @@ func init() { rootCmd.Flags().String("profile-cpu", "", "Enable cpu profiling to this file") viper.BindPFlag("profile-cpu", rootCmd.Flags().Lookup("profile-cpu")) + + // Proto user flags + rootCmd.Flags().String("protoUserPath", "", + "Path to proto user JSON file containing cryptographic primitives "+ + "the client will load") + viper.BindPFlag("protoUserPath", rootCmd.Flags().Lookup("protoUserPath")) + rootCmd.Flags().String("protoUserOut", "", + "Path to which a normally constructed client "+ + "will write proto user JSON file") + viper.BindPFlag("protoUserOut", rootCmd.Flags().Lookup("protoUserOut")) + } // initConfig reads in config file and ENV variables if set. diff --git a/interfaces/user/proto.go b/interfaces/user/proto.go new file mode 100644 index 0000000000000000000000000000000000000000..6b9cf1e3a6b338a08abd386b92772314b5f499e3 --- /dev/null +++ b/interfaces/user/proto.go @@ -0,0 +1,33 @@ +package user + +import ( + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" +) + +type Proto struct { + //General Identity + TransmissionID *id.ID + TransmissionSalt []byte + TransmissionRSA *rsa.PrivateKey + ReceptionID *id.ID + ReceptionSalt []byte + ReceptionRSA *rsa.PrivateKey + Precanned bool + // Timestamp in which user has registered with the network + RegistrationTimestamp int64 + + RegCode string + + TransmissionRegValidationSig []byte + ReceptionRegValidationSig []byte + + //cmix Identity + CmixDhPrivateKey *cyclic.Int + CmixDhPublicKey *cyclic.Int + + //e2e Identity + E2eDhPrivateKey *cyclic.Int + E2eDhPublicKey *cyclic.Int +} diff --git a/interfaces/user/user.go b/interfaces/user/user.go index 8788856b494cf386dbd903510680935f2b320daa..56f260d03527ce2c605c5fe781f3be3935cc106c 100644 --- a/interfaces/user/user.go +++ b/interfaces/user/user.go @@ -13,7 +13,6 @@ import ( "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" - "time" ) type User struct { @@ -26,7 +25,7 @@ type User struct { ReceptionRSA *rsa.PrivateKey Precanned bool // Timestamp in which user has registered with the network - RegistrationTimestamp time.Time + RegistrationTimestamp int64 //cmix Identity CmixDhPrivateKey *cyclic.Int @@ -44,3 +43,20 @@ func (u User) GetContact() contact.Contact { Facts: make([]fact.Fact, 0), } } + +func NewUserFromProto(proto *Proto) User { + return User{ + TransmissionID: proto.TransmissionID, + TransmissionSalt: proto.TransmissionSalt, + TransmissionRSA: proto.TransmissionRSA, + ReceptionID: proto.ReceptionID, + ReceptionSalt: proto.ReceptionSalt, + ReceptionRSA: proto.ReceptionRSA, + Precanned: proto.Precanned, + RegistrationTimestamp: proto.RegistrationTimestamp, + CmixDhPrivateKey: proto.CmixDhPrivateKey, + CmixDhPublicKey: proto.CmixDhPublicKey, + E2eDhPrivateKey: proto.E2eDhPrivateKey, + E2eDhPublicKey: proto.E2eDhPublicKey, + } +} diff --git a/network/message/sendCmixUtils.go b/network/message/sendCmixUtils.go index 30fb94088c1b339462c87405e7b10e221299f3a2..b889b0ad86a7a09e7df10ab1ea72bd03541a4057 100644 --- a/network/message/sendCmixUtils.go +++ b/network/message/sendCmixUtils.go @@ -146,7 +146,7 @@ func buildSlotMessage(msg format.Message, recipient *id.ID, target *id.ID, if param.IdentityPreimage != nil { preimage = param.IdentityPreimage jww.INFO.Printf("Sending to %s with override preimage %v", recipient, preimage) - }else{ + } else { preimage = preimage2.MakeDefault(recipient) jww.INFO.Printf("Sending to %s with default preimage %v", recipient, preimage) } diff --git a/storage/session.go b/storage/session.go index 4a380b7911699490b0d6437beaa84c911b3ba080..8ee2b43d3119b222612389685360d53b26bc9abf 100644 --- a/storage/session.go +++ b/storage/session.go @@ -94,7 +94,7 @@ func New(baseDir, password string, u userInterface.User, currentVersion version. s, err := initStore(baseDir, password) if err != nil { - return nil, errors.WithMessage(err, "Failed to create session") + return nil, errors.WithMessagef(err, "Failed to create session for %s", baseDir) } err = s.newRegStatus() @@ -103,7 +103,8 @@ func New(baseDir, password string, u userInterface.User, currentVersion version. "Create new session") } - s.user, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt, u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned) + s.user, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt, + u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned) if err != nil { return nil, errors.WithMessage(err, "Failed to create user") } diff --git a/storage/user.go b/storage/user.go index 975b574a2e9678a31eff7f0598b396ab6427a6af..313741471ee5e3fefa12349d2e9b441352b983e1 100644 --- a/storage/user.go +++ b/storage/user.go @@ -16,9 +16,9 @@ func (s *Session) GetUser() user.User { return user.User{ TransmissionID: ci.GetTransmissionID().DeepCopy(), TransmissionSalt: copySlice(ci.GetTransmissionSalt()), - TransmissionRSA: ci.GetReceptionRSA(), + TransmissionRSA: ci.GetTransmissionRSA(), ReceptionID: ci.GetReceptionID().DeepCopy(), - RegistrationTimestamp: s.user.GetRegistrationTimestamp(), + RegistrationTimestamp: s.user.GetRegistrationTimestamp().UnixNano(), ReceptionSalt: copySlice(ci.GetReceptionSalt()), ReceptionRSA: ci.GetReceptionRSA(), Precanned: ci.IsPrecanned(),