diff --git a/api/client.go b/api/client.go index 20fdcc1e9991ad34f3039c07f7d08121c85fefce..3cedff02094d341e55735773867ae1f1e04fbbea 100644 --- a/api/client.go +++ b/api/client.go @@ -92,7 +92,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, 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 @@ -123,7 +123,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, 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 @@ -153,7 +153,7 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, 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 @@ -202,42 +202,50 @@ func OpenClient(storageDir string, password []byte, parameters params.Network) ( // 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(storageDir string, password []byte, - protoClientJSON []byte, - parameters params.Network, def *ndf.NetworkDefinition) (*Client, error) { +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) + err = json.Unmarshal(protoClientJSON, protoUser) if err != nil { - return nil, err + return err } // Initialize a user object for storage set up usr := user.NewUserFromProto(protoUser) // Set up storage - err = checkVersionAndSetupStorage(def, storageDir, password, usr, + storageSess, err := checkVersionAndSetupStorage(def, storageDir, password, usr, cmixGrp, e2eGrp, rngStreamGen, false, protoUser.RegCode) - - //Open the client - c, err := OpenClient(storageDir, password, parameters) if err != nil { - return nil, err + return err } // Set registration values in storage - c.GetStorage().User().SetReceptionRegistrationValidationSignature(protoUser.ReceptionRegValidationSig) - c.GetStorage().User().SetTransmissionRegistrationValidationSignature(protoUser.TransmissionRegValidationSig) - c.GetStorage().User().SetRegistrationTimestamp(protoUser.RegistrationTimestamp.UnixNano()) + storageSess.User().SetReceptionRegistrationValidationSignature(protoUser.ReceptionRegValidationSig) + storageSess.User().SetTransmissionRegistrationValidationSignature(protoUser.TransmissionRegValidationSig) + storageSess.User().SetRegistrationTimestamp(protoUser.RegistrationTimestamp) - return c, nil + //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. @@ -366,54 +374,6 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, return c, 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. It is unsafe because all network relationships -// will no longer be present in the new session file. -func LoginWithProtoClient(storageDir string, password []byte, - protoClientJSON []byte, - newBaseNdf string, parameters params.Network) (*Client, error) { - jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()") - - // Parse the NDF - def, err := parseNDF(newBaseNdf) - if err != nil { - return nil, err - } - - //Open the client - c, err := NewProtoClient_Unsafe(storageDir, password, protoClientJSON, parameters, def) - if err != nil { - return nil, err - } - - //initialize comms - err = c.initComms() - if err != nil { - return nil, err - } - - //store the updated base NDF - c.storage.SetNDF(def) - - // Initialize network and link it to context - c.network, err = network.NewManager(c.storage, c.switchboard, c.rng, - c.events, c.comms, parameters, def) - if err != nil { - return nil, err - } - - // initialize the auth tracker - c.auth = auth.NewManager(c.switchboard, c.storage, c.network) - - err = c.registerFollower() - if err != nil { - return nil, err - } - - return c, nil -} - func (c *Client) initComms() error { var err error @@ -476,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") @@ -792,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 @@ -806,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 @@ -830,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/cmd/proto.go b/cmd/proto.go deleted file mode 100644 index d1a93b889759d75dad4e0330426e3446e9350efa..0000000000000000000000000000000000000000 --- a/cmd/proto.go +++ /dev/null @@ -1,102 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright © 2020 xx network SEZC // -// // -// Use of this source code is governed by a license that can be found in the // -// LICENSE file // -/////////////////////////////////////////////////////////////////////////////// - -package cmd - -import ( - "github.com/spf13/cobra" - jww "github.com/spf13/jwalterweatherman" - "github.com/spf13/viper" - "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/interfaces/params" - "gitlab.com/xx_network/primitives/utils" - "io/ioutil" - "time" -) - -var protoCmd = &cobra.Command{ - Use: "proto", - Short: "Load client with a proto client JSON file.", - Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { - // If output path is specified, only write to file - var client *api.Client - jww.INFO.Printf("In proto user path") - protoOutputPath := viper.GetString("protoUserOut") - if protoOutputPath != "" { - client = initClient() - - - jsonBytes, err := client.ConstructProtoUerFile() - if err != nil { - jww.FATAL.Panicf("Failed to construct proto user file: %v", err) - } - - err = utils.WriteFileDef(protoOutputPath, jsonBytes) - if err != nil { - jww.FATAL.Panicf("Failed to write proto user to file: %v", err) - } - } else { - jww.INFO.Printf("Loading proto client") - - client = loadProtoClient() - } - }, -} - -func loadProtoClient() *api.Client { - protoUserPath := viper.GetString("protoUserPath") - protoUserFile, err := utils.ReadFile(protoUserPath) - if err != nil { - jww.FATAL.Panicf("Failed to read proto user: %v", err) - } - - pass := viper.GetString("password") - storeDir := viper.GetString("session") - - netParams := params.GetDefaultNetwork() - netParams.E2EParams.MinKeys = uint16(viper.GetUint("e2eMinKeys")) - netParams.E2EParams.MaxKeys = uint16(viper.GetUint("e2eMaxKeys")) - netParams.E2EParams.NumRekeys = uint16( - viper.GetUint("e2eNumReKeys")) - netParams.ForceHistoricalRounds = viper.GetBool("forceHistoricalRounds") - netParams.FastPolling = viper.GetBool("slowPolling") - netParams.ForceMessagePickupRetry = viper.GetBool("forceMessagePickupRetry") - if netParams.ForceMessagePickupRetry { - period := 3 * time.Second - jww.INFO.Printf("Setting Uncheck Round Period to %v", period) - netParams.UncheckRoundPeriod = period - } - netParams.VerboseRoundTracking = viper.GetBool("verboseRoundTracking") - - // Load NDF - ndfPath := viper.GetString("ndf") - ndfJSON, err := ioutil.ReadFile(ndfPath) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - - jww.INFO.Printf("login with proto") - - client, err := api.LoginWithProtoClient(storeDir, []byte(pass), - protoUserFile, string(ndfJSON), netParams) - if err != nil { - jww.FATAL.Panicf("Failed to login: %v", err) - } - - return client -} - -// init is the initialization function for Cobra which defines commands -// and flags. -func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - - rootCmd.AddCommand(protoCmd) -} diff --git a/cmd/root.go b/cmd/root.go index cb68de315961afedadca2cb338c1b5833a580c12..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" @@ -58,13 +59,8 @@ var rootCmd = &cobra.Command{ pprof.StartCPUProfile(f) } - protoUserPath := viper.GetString("protoUserPath") - var client *api.Client - if protoUserPath != "" { - loadProtoClient() - } else { - client = initClient() - } + client := initClient() + user := client.GetUser() jww.INFO.Printf("User: %s", user.ReceptionID) writeContact(user.GetContact()) @@ -387,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 @@ -399,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 { @@ -458,12 +461,19 @@ func initClient() *api.Client { jww.FATAL.Panicf("%+v", err) } - jsoBytes, err := client.ConstructProtoUerFile() - if err != nil { - jww.WARN.Printf("err: %v", err) - } + if protoUser := viper.GetString("protoUserOut"); protoUser != "" { - jww.WARN.Printf("json %s", string(jsoBytes)) + 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 } @@ -907,15 +917,14 @@ func init() { viper.BindPFlag("profile-cpu", rootCmd.Flags().Lookup("profile-cpu")) // Proto user flags - protoCmd.Flags().String("protoUserPath", "protoUser.json", + rootCmd.Flags().String("protoUserPath", "", "Path to proto user JSON file containing cryptographic primitives "+ "the client will load") - viper.BindPFlag("protoUserPath", protoCmd.Flags().Lookup("protoUserPath")) - protoCmd.Flags().String("protoUserOut", "protoUser.json", + 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", protoCmd.Flags().Lookup("protoUserOut")) - + viper.BindPFlag("protoUserOut", rootCmd.Flags().Lookup("protoUserOut")) } diff --git a/interfaces/user/proto.go b/interfaces/user/proto.go index 0fcc0920a6b134800b9d8c73df6ee08417a92274..6b9cf1e3a6b338a08abd386b92772314b5f499e3 100644 --- a/interfaces/user/proto.go +++ b/interfaces/user/proto.go @@ -4,7 +4,6 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" - "time" ) type Proto struct { @@ -17,9 +16,9 @@ type Proto struct { ReceptionRSA *rsa.PrivateKey Precanned bool // Timestamp in which user has registered with the network - RegistrationTimestamp time.Time + RegistrationTimestamp int64 - RegCode string + RegCode string TransmissionRegValidationSig []byte ReceptionRegValidationSig []byte diff --git a/interfaces/user/user.go b/interfaces/user/user.go index c3f5875aa6dae91879a063ac83372321f9c0eff3..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 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/network/node/register.go b/network/node/register.go index a4424eb18b16b98f2b1766f68101fcf7c8fe11b4..fd61aa77f17623981f9e3a489920ff3e1dc15401 100644 --- a/network/node/register.go +++ b/network/node/register.go @@ -96,6 +96,10 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, //registerWithNode serves as a helper for RegisterWithNodes // It registers a user with a specific in the client's ndf. +// todo: follow uci. TransmissionRSA and ReceptionRSA are marshaled into JSON as +// objects. MAke sure JSON is intelligent enough on unmarshal to read that data. +// Also make sure (if unmarshalled correctly) that data makes it's way to storage +// as expected. func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface, ngw network.NodeGateway, regSig []byte, registrationTimestampNano int64, uci *user.CryptographicIdentity, store *cmix.Store, rng csprng.Source, 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(),