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/cmd/backup.go b/cmd/backup.go index 6a54958e88bd4441b268b979d82f3e10c4dd477a..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,9 +19,6 @@ 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 diff --git a/cmd/init.go b/cmd/init.go index 20dc35ede7d85dbce8310798d2233e2df8e877d3..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 @@ -54,6 +57,9 @@ var initCmd = &cobra.Command{ 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,9 +71,9 @@ 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") @@ -87,7 +93,12 @@ func loadOrInitClient(password []byte, storeDir, regCode string, jww.FATAL.Panicf("%+v", err) } - identity, err = xxdk.MakeReceptionIdentity(net) + 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) } @@ -108,11 +119,11 @@ func loadOrInitClient(password []byte, storeDir, regCode string, } } - client, err := xxdk.Login(net, 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 diff --git a/cmd/root.go b/cmd/root.go index 9d0709e82bff6f7d282768d9829b7281f57ee524..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. @@ -602,7 +603,7 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { } else if backupPath != "" { messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams) } else { - messenger = loadOrInitClient(storePassword, storeDir, regCode, cmixParams, e2eParams) + messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams) } // Handle protoUser output @@ -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)) @@ -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/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/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/identity.go b/xxdk/identity.go index 0d3f5d54771fa7cdf7ee8353624313c5beac92d3..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" @@ -172,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 a515a598e1d5f1e525bef2fb1fbaac0cefe56142..98edf51028937e17a0e555c7de1d91b60a3ff35b 100644 --- a/xxdk/precan.go +++ b/xxdk/precan.go @@ -9,11 +9,12 @@ 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" - "math/rand" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage" @@ -60,9 +61,18 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( contact.Contact, error) { - precan := m.GetReceptionIdentity().GetContact() + 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) @@ -73,7 +83,7 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( prng1 := rand.New(rand.NewSource(int64(precannedID))) theirSIDHPrivKey := util.NewSIDHPrivateKey(theirVariant) theirSIDHPubKey := util.NewSIDHPublicKey(theirVariant) - err := theirSIDHPrivKey.Generate(prng1) + err = theirSIDHPrivKey.Generate(prng1) if err != nil { return contact.Contact{}, err } @@ -91,7 +101,7 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( // 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) @@ -99,5 +109,5 @@ func (m *E2e) MakePrecannedAuthenticatedChannel(precannedID uint) ( // the channel m.GetCmix().CheckInProgressMessages() - return precan, err + return precanContact, err } diff --git a/xxdk/user.go b/xxdk/user.go index 8b513fd6e39e27d758c43ffd16f1d393c751aa97..747fb3dbef16f64e0bb47cece6896b51477218da 100644 --- a/xxdk/user.go +++ b/xxdk/user.go @@ -39,7 +39,7 @@ func createNewUser(rng *fastRNG.StreamGenerator, e2eGroup *cyclic.Group) user.In var transmissionSalt, receptionSalt []byte e2eKeyBytes, transmissionSalt, receptionSalt, - transmissionRsaKey, receptionRsaKey := createDhKeys(rng, e2eGroup) + transmissionRsaKey, receptionRsaKey := createKeys(rng, e2eGroup) transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(), transmissionSalt, id.User) @@ -53,6 +53,7 @@ func createNewUser(rng *fastRNG.StreamGenerator, e2eGroup *cyclic.Group) user.In jww.FATAL.Panicf(err.Error()) } + dhPrivKey := e2eGroup.NewIntFromBytes(e2eKeyBytes) return user.Info{ TransmissionID: transmissionID.DeepCopy(), TransmissionSalt: transmissionSalt, @@ -61,12 +62,12 @@ func createNewUser(rng *fastRNG.StreamGenerator, e2eGroup *cyclic.Group) user.In ReceptionSalt: receptionSalt, ReceptionRSA: receptionRsaKey, Precanned: false, - E2eDhPrivateKey: e2eGroup.NewIntFromBytes(e2eKeyBytes), - E2eDhPublicKey: nil, + E2eDhPrivateKey: dhPrivKey, + E2eDhPublicKey: diffieHellman.GeneratePublicKey(dhPrivKey, e2eGroup), } } -func createDhKeys(rng *fastRNG.StreamGenerator, +func createKeys(rng *fastRNG.StreamGenerator, e2e *cyclic.Group) (e2eKeyBytes, transmissionSalt, receptionSalt []byte, transmissionRsaKey, receptionRsaKey *rsa.PrivateKey) { @@ -95,6 +96,11 @@ func createDhKeys(rng *fastRNG.StreamGenerator, var err error stream := rng.GetStream() transmissionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + transmissionSalt = make([]byte, SaltSize) + _, err = stream.Read(transmissionSalt) stream.Close() if err != nil { jww.FATAL.Panicf(err.Error()) @@ -106,6 +112,11 @@ func createDhKeys(rng *fastRNG.StreamGenerator, var err error stream := rng.GetStream() receptionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + receptionSalt = make([]byte, SaltSize) + _, err = stream.Read(receptionSalt) stream.Close() if err != nil { jww.FATAL.Panicf(err.Error()) @@ -185,7 +196,7 @@ func createNewVanityUser(rng csprng.Source, for { select { case <-done: - defer wg.Done() + wg.Done() return default: n, err = csprng.NewSystemRNG().Read( @@ -205,17 +216,17 @@ func createNewVanityUser(rng csprng.Source, 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 } } @@ -241,17 +252,7 @@ func createNewVanityUser(rng csprng.Source, } // createPrecannedUser -func createPrecannedUser(precannedID uint, rng csprng.Source, e2e *cyclic.Group) user.Info { - // 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? - prng := rand.New(rand.NewSource(int64(precannedID))) - e2eKeyBytes, err := csprng.GenerateInGroup(e2e.GetPBytes(), 256, prng) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - +func createPrecannedUser(precannedID uint, rng csprng.Source, grp *cyclic.Group) user.Info { // Salt, UID, etc gen salt := make([]byte, SaltSize) @@ -265,13 +266,18 @@ func createPrecannedUser(precannedID uint, rng csprng.Source, e2e *cyclic.Group) 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: e2e.NewIntFromBytes(e2eKeyBytes), + E2eDhPrivateKey: dhPrivKey, + E2eDhPublicKey: diffieHellman.GeneratePublicKey(dhPrivKey, grp), TransmissionRSA: rsaKey, ReceptionRSA: rsaKey, }