diff --git a/Makefile b/Makefile index 8e59d3126d0c93a8958ffaeda27130e100b1fc5b..f1955bd0c974351c212a82888947bf58774343fa 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ update_release: GOFLAGS="" go get gitlab.com/xx_network/primitives@release GOFLAGS="" go get gitlab.com/elixxir/primitives@release GOFLAGS="" go get gitlab.com/xx_network/crypto@release - GOFLAGS="" go get gitlab.com/elixxir/crypto@singleUseMultiPartRequest + GOFLAGS="" go get gitlab.com/elixxir/crypto@release GOFLAGS="" go get gitlab.com/xx_network/comms@release GOFLAGS="" go get gitlab.com/elixxir/comms@release GOFLAGS="" go get gitlab.com/elixxir/ekv@master diff --git a/README.md b/README.md index 62b1ed0de9a3a23929243db3299027af71793ee2..85caa9719203f12bf8bfbcb7d9e22b02cf37102f 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ [](https://gitlab.com/elixxir/client/commits/master) -The client is a library and related command-line tool +The client is a library and related command-line tool that facilitates making full-featured xx clients for all platforms. It interfaces with the cMix system, enabling access to all xx network messaging features, including end-to-end encryption and metadata protection. This repository contains everything necessary to implement all of the -xx network messaging features. It also contains features to extend the base +xx network messaging features. It also contains features to extend the base messaging protocols. The command-line tool accompanying the client library can be built for any platform supported by @@ -27,7 +27,7 @@ The client is open-source software released under the simplified BSD License. ## Command Line Usage The command-line tool is intended for testing xx network functionality and not -for regular user use. +for regular user use. These instructions assume that you have [Go 1.17.X installed](https://go.dev/doc/install), and GCC installed for Cgo (such as `build-essential` on Debian or Ubuntu). @@ -51,12 +51,26 @@ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/clie #### Fetching an NDF -All actions performed with the client require a current [NDF](https://xxdk-dev.xx.network/technical-glossary#network-definition-file-ndf). The NDF is downloadable from the command line or [via an access point](https://xxdk-dev.xx.network/quick-reference#func-downloadandverifysignedndfwithurl) in the Client API. +All actions performed with the client require a +current [NDF](https://xxdk-dev.xx.network/technical-glossary#network-definition-file-ndf). The NDF is downloadable from +the command line +or [via an access point](https://xxdk-dev.xx.network/quick-reference#func-downloadandverifysignedndfwithurl) in the +Client API. -Use the `getndf` command to fetch the NDF via the command line. `getndf` enables command-line users to poll the NDF from a network gateway without any pre-established client connection: +Use the `getndf` command to fetch the NDF via the command line. `getndf` enables command-line users to poll the NDF from +a network gateway without any pre-established client connection. + +First, you'll want to download an SSL certificate: + +``` +// Assumes you are running a gateway locally +openssl s_client -showcerts -connect localhost:8440 < /dev/null 2>&1 | openssl x509 -outform PEM > certfile.pem +``` + +Now you can fetch the NDF: ``` -// Fetch NDF (example usage for Gateways, assumes you are running a gateway locally) +// Example usage for Gateways, assumes you are running a gateway locally $ go run main.go getndf --gwhost localhost:8440 --cert certfile.pem | jq . >ndf.json ``` @@ -83,10 +97,16 @@ Sample content of `ndf.json`: ..... ``` -#### Sending safe messages between 2 users +#### Sending Safe Messages Between Two (2) Users + +**Note:** For information on receiving messages and troubleshooting authenticated channel requests, +see [Receiving Messages](#receiving-messages) +and [Confirming authenticated channel requests](#confirming-authenticated-channel-requests). To send messages with end-to-end encryption, you must first establish a connection -or [authenticated channel](https://xxdk-dev.xx.network/technical-glossary#authenticated-channel) with the other user: +or [authenticated channel](https://xxdk-dev.xx.network/technical-glossary#authenticated-channel) with the other user. +See below for example commands for sending or confirming authenticated channel requests, as well as for sending E2E +messages: ``` # Get user contact jsons for each client @@ -102,9 +122,9 @@ Message received: Sending to Qm40C5hRUm7uhp5aATVWhSL6Mt+Z4JVBQrsEDvMORh4D: Received 1 -# Alternatively, to accept an authenticated channel request implicitly -# (should be within the timeout window of requesting client, or the request will need to be resent): -$ client --password "password" --ndf ndf.json -l client.log -s session-directory --destfile user2-contact.json" --unsafe-channel-creation --waitTimeout 200 +# Accept/Confirm an authenticated channel request implicitly +# (should be within the timeout window of requesting client, or the request will need to be re-sent): +$ client --password "password" --ndf ndf.json -l client.log -s session-directory --destfile user2-contact.json --unsafe-channel-creation --waitTimeout 200 Authentication channel request from: o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD Sending to o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD: Message received: @@ -128,7 +148,7 @@ Received 0 * `-s`: The storage directory for client session data. * `--writeContact`: Output the user's contact information to this file. * `--destfile` is used to specify the recipient. You can also use - `--destid b64:...` using the user's base64 id which is printed in the logs. + `--destid b64:...` using the user's base64 id, which is printed in the logs. * `--unsafe`: Send message without encryption (necessary whenever you have not already established an e2e channel). * `--unsafe-channel-creation` Auto-create and auto-accept channel requests. @@ -136,12 +156,12 @@ Received 0 Note that the client defaults to sending to itself when a destination is not supplied. This is why we've used the `--unsafe` flag when creating the user contact jsons. -However, when sending between users it is dropped in exchange for `--unsafe-channel-creation`. +However, when sending between users, it is dropped in exchange for `--unsafe-channel-creation`. -For the authenticated channel creation to be considered "safe" the user should be prompted. You can do this -on the command line by explicitly accepting the channel creation -when sending a request with `--send-auth-request` and/or explicitly accepting a request with -`--accept-channel`: +For the authenticated channel creation to be considered "safe", the user should be prompted. You can do this by +explicitly accepting the channel creation +when sending a request with `--send-auth-request` (while excluding the `--unsafe-channel-creation` flag) or explicitly +accepting a request with `--accept-channel`: ``` $ client --password user-password --ndf ndf.json -l client.log -s session-directory --destfile user-contact.json --accept-channel @@ -151,6 +171,61 @@ Message received: Received 1 ``` +#### Receiving Messages + +There is no explicit command for receiving messages. Instead, the client will attempt to fetch pending messages on each +run. + +You can use the `--receiveCount` flag to limit the number of messages the client waits for before a timeout occurs: + +``` +$ client --password <password> --ndf <NDF JSON file> -l client.log -s <session directory> --destfile <contact JSON file> --receiveCount <integer count> +``` + +#### Sending Authenticated Channel Requests + +See [Sending Safe Messages Between Two (2) Users](#sending-safe-messages-between-two-2-users) + +#### Confirming Authenticated Channel Requests + +Setting up an authenticated channel between clients is a back-and-forth process that happens in sequence. One client +sends a request and waits for the other to accept it. + +See the previous section, [Sending safe messages between 2 users](#sending-safe-messages-between-2-users), for example +commands showing how to set up an end-to-end connection between clients before sending messages. + +As with received messages, there is no command for checking for authenticated channel requests; you'll be notified of +any pending requests whenever the client is run. + +``` +$ ./client.win64 --password password --ndf ndf.json -l client.log -s session-directory --destfile user-contact8.json --waitTimeout 120 -m "Hi User 7, from User 8 with E2E Encryption" +Authentication channel request from: 8zAWY69UUK/FkMBGY3ViR5MMfcp1GoKn6Y3c/64NYNYD +Sending to yYAztmoCoAH2VIr00zPxnj/ZRvdiDdURjdDWys0KYI4D: Hi User 7, from User 8 with E2E Encryption +Timed out! +Received 0 + +``` + +##### Troubleshooting + +**`panic: Could not confirm authentication channel for ...`** + +Suppose the receiving client does not confirm the authentication channel before the requesting client reaches a +timeout (default 120s). In that case, the request eventually terminates in +a `panic: Could not confirm authentication channel for ...` error. + +Retrying the request should fix this. If necessary, you may increase the time the client waits to confirm the channel +before timeout using the `--auth-timeout` flag (default 120s). + +This error will also occur with the receiving client if it received the request but failed to confirm it before the +requesting client reached a timeout. In this case, the request needs to be resent while the other client reattempts to +confirm the channel. + +**`panic: Received request not found`** + +You may also run into the `panic: Received request not found` error when attempting to confirm an authenticated channel +request. This means your client has not received the request. If one has been sent, simply retrying should fix this. + Full usage of client can be found with `client --help`: ``` @@ -221,9 +296,9 @@ Use "client [command] --help" for more information about a command. ## Library Overview -The xx client is designed to be used as a go library (and by extension a -c library). - +The xx client is designed to be used as a go library (and by extension a +c library). + Support is also present for go mobile to build Android and iOS libraries. We bind all exported symbols from the bindings package for use on mobile platforms. @@ -232,7 +307,8 @@ platforms. Clients need to perform the same actions *in the same order* as shown in `cmd/root.go`. Specifically, certain handlers need to be registered and -set up before starting network threads. Additionally, you cannot perform certain actions until the network connection reaches a "healthy" state. +set up before starting network threads. Additionally, you cannot perform certain actions until the network connection +reaches a "healthy" state. See [main.go](https://git.xx.network/elixxir/xxdk-examples/-/blob/sample-messaging-app/sample-messaging-app/main.go) for relevant code listings on when and how to perform these actions. The [Getting Started](https://xxdk-dev.xx.network/getting-started) guide provides further detail. @@ -340,7 +416,7 @@ parts of the roadmap that are intended for the client: * User Discovery - A bot that will allow the user to look for others on the network. * Notifications - An optional notifications system which uses firebase -* Efficiency improvements - mechanisms for message pickup and network tracking +* Efficiency improvements - mechanisms for message pickup and network tracking * will evolve to allow tradeoffs and options for use We are also always looking at simplifying and improving the library interface. diff --git a/api/version_vars.go b/api/version_vars.go index b681e79ff65784d85fc3b31c182c6f51e09c8697..01757159c19fdb14130d00b25907d48091e56967 100644 --- a/api/version_vars.go +++ b/api/version_vars.go @@ -1,9 +1,9 @@ // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2022-03-10 11:46:32.709433 -0600 CST m=+0.047217210 +// 2022-06-06 15:29:07.985136 -0500 CDT m=+0.025770522 package api -const GITVERSION = `0d927b59 Update deps` +const GITVERSION = `3f73b1f6 re-add utils` const SEMVER = "4.1.0" const DEPENDENCIES = `module gitlab.com/elixxir/client @@ -18,14 +18,15 @@ require ( github.com/spf13/cobra v1.1.1 github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.7.1 - gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 - gitlab.com/elixxir/comms v0.0.4-0.20220308183624-c2183e687a03 - gitlab.com/elixxir/crypto v0.0.7-0.20220309234716-1ba339865787 - gitlab.com/elixxir/ekv v0.1.6 - gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623 - gitlab.com/xx_network/comms v0.0.4-0.20220223205228-7c4974139569 - gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4 - gitlab.com/xx_network/primitives v0.0.4-0.20220222211843-901fa4a2d72b + gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f + gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 + gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea + gitlab.com/elixxir/ekv v0.1.7 + gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f + gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac + gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 + gitlab.com/xx_network/primitives v0.0.4-0.20220324193139-b292d1ae6e7e + go.uber.org/ratelimit v0.2.0 golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 google.golang.org/grpc v1.42.0 @@ -33,6 +34,7 @@ require ( ) require ( + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/badoux/checkmail v1.2.1 // indirect github.com/elliotchance/orderedmap v1.4.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect @@ -56,6 +58,7 @@ require ( gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/text v0.3.6 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/backup/backup.go b/backup/backup.go index 0e025f3fe28e116f77a19a81a873238db8c4b38a..46f5bf73019e9c26e66b2a780f141a5b788647a4 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -30,9 +30,6 @@ const ( errSavePassword = "failed to save password: %+v" errSaveKeySaltParams = "failed to save key, salt, and params: %+v" - // ResumeBackup - errLoadPassword = "backup not initialized: load user password failed: %+v" - // Backup.StopBackup errDeletePassword = "failed to delete password: %+v" errDeleteCrypto = "failed to delete key, salt, and parameters: %+v" @@ -106,12 +103,6 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn, rng: rng, } - // Save password to storage - err := savePassword(password, b.kv) - if err != nil { - return nil, errors.Errorf(errSavePassword, err) - } - // Derive key and get generated salt and parameters rand := b.rng.GetStream() salt, err := backup.MakeSalt(rand) @@ -121,9 +112,9 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn, rand.Close() params := backup.DefaultParams() - params.Memory = 256 * 1024 // 256 MiB - params.Threads = 4 - params.Time = 100 + params.Memory = 64 * 1024 // 64 MiB + params.Threads = 1 + params.Time = 5 key := backup.DeriveKey(password, salt, params) // Save key, salt, and parameters to storage @@ -147,9 +138,9 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn, func ResumeBackup(updateBackupCb UpdateBackupFn, container *messenger.Container, e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) { - _, err := loadPassword(kv) + _, _, _, err := loadBackup(kv) if err != nil { - return nil, errors.Errorf(errLoadPassword, err) + return nil, err } b := &Backup{ @@ -253,12 +244,7 @@ func (b *Backup) StopBackup() error { defer b.mux.Unlock() b.updateBackupCb = nil - err := deletePassword(b.kv) - if err != nil { - return errors.Errorf(errDeletePassword, err) - } - - err = deleteBackup(b.kv) + err := deleteBackup(b.kv) if err != nil { return errors.Errorf(errDeleteCrypto, err) } diff --git a/backup/backup_test.go b/backup/backup_test.go index eeda3711c16697038f98228e228ee04c441ea627..f61dc0a06b02adcaa3218c909a90dda6c90c3985 100644 --- a/backup/backup_test.go +++ b/backup/backup_test.go @@ -15,6 +15,7 @@ import ( "time" "gitlab.com/elixxir/client/api/messenger" + "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" @@ -44,16 +45,6 @@ func Test_InitializeBackup(t *testing.T) { t.Error("Timed out waiting for callback.") } - // Check that the correct password is in storage - loadedPassword, err := loadPassword(b.kv) - if err != nil { - t.Errorf("Failed to load password: %+v", err) - } - if expectedPassword != loadedPassword { - t.Errorf("Loaded invalid key.\nexpected: %q\nreceived: %q", - expectedPassword, loadedPassword) - } - // Check that the key, salt, and params were saved to storage key, salt, _, err := loadBackup(b.kv) if err != nil { @@ -121,17 +112,7 @@ func Test_ResumeBackup(t *testing.T) { t.Errorf("ResumeBackup returned an error: %+v", err) } - // Check that the correct password is in storage - loadedPassword, err := loadPassword(b.kv) - if err != nil { - t.Errorf("Failed to load password: %+v", err) - } - if expectedPassword != loadedPassword { - t.Errorf("Loaded invalid key.\nexpected: %q\nreceived: %q", - expectedPassword, loadedPassword) - } - - // get key, salt, and parameters of resumed backup + // Get key, salt, and parameters of resumed backup key2, salt2, _, err := loadBackup(b.kv) if err != nil { t.Errorf("Failed to load key, salt, and params from resumed "+ @@ -164,12 +145,12 @@ func Test_ResumeBackup(t *testing.T) { // Error path: Tests that ResumeBackup returns an error if no password is // present in storage. -func Test_ResumeBackup_NoKeyError(t *testing.T) { - expectedErr := strings.Split(errLoadPassword, "%")[0] - kv := versioned.NewKV(ekv.MakeMemstore()) +func Test_resumeBackup_NoKeyError(t *testing.T) { + expectedErr := "object not found" + s := storage.InitTestingSession(t) rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG) _, err := ResumeBackup(nil, &messenger.Container{}, newMockE2e(t), newMockSession(t), - newMockUserDiscovery(), kv, rngGen) + newMockUserDiscovery(), s.GetKV(), rngGen) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("ResumeBackup did not return the expected error when no "+ "password is present.\nexpected: %s\nreceived: %+v", expectedErr, err) @@ -181,13 +162,8 @@ func Test_ResumeBackup_NoKeyError(t *testing.T) { func TestBackup_TriggerBackup(t *testing.T) { cbChan := make(chan []byte) cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup } - b := newTestBackup("MySuperSecurePassword", cb, t) - - // get password - password, err := loadPassword(b.kv) - if err != nil { - t.Errorf("Failed to load password from storage: %+v", err) - } + password := "MySuperSecurePassword" + b := newTestBackup(password, cb, t) collatedBackup := b.assembleBackup() @@ -265,12 +241,6 @@ func TestBackup_StopBackup(t *testing.T) { case <-time.After(10 * time.Millisecond): } - // Make sure password is deleted - password, err := loadPassword(b.kv) - if err == nil || len(password) != 0 { - t.Errorf("Loaded password that should be deleted: %q", password) - } - // Make sure key, salt, and params are deleted key, salt, p, err := loadBackup(b.kv) if err == nil || len(key) != 0 || len(salt) != 0 || p != (backup.Params{}) { diff --git a/backup/keyStorage.go b/backup/keyStorage.go index 9a3f5cfe564abc782e4eb199ed7dbde254318fea..f0e11469e850f17363bee97f6c5cc9d47d377b97 100644 --- a/backup/keyStorage.go +++ b/backup/keyStorage.go @@ -9,6 +9,7 @@ package backup import ( "bytes" + "github.com/pkg/errors" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/backup" @@ -100,29 +101,3 @@ func unmarshalBackup(buf []byte) (key, salt []byte, params backup.Params, err er return } - -// savePassword saves the user's backup password to storage. -func savePassword(password string, kv *versioned.KV) error { - obj := &versioned.Object{ - Version: passwordStorageVersion, - Timestamp: netTime.Now(), - Data: []byte(password), - } - - return kv.Set(passwordStorageKey, passwordStorageVersion, obj) -} - -// loadPassword returns the user's backup password from storage. -func loadPassword(kv *versioned.KV) (string, error) { - obj, err := kv.Get(passwordStorageKey, passwordStorageVersion) - if err != nil { - return "", err - } - - return string(obj.Data), nil -} - -// deletePassword deletes the user's backup password from storage. -func deletePassword(kv *versioned.KV) error { - return kv.Delete(passwordStorageKey, passwordStorageVersion) -} diff --git a/backup/keyStorage_test.go b/backup/keyStorage_test.go deleted file mode 100644 index 95e7a08915f4255dfc742277cf47b72a5e97b470..0000000000000000000000000000000000000000 --- a/backup/keyStorage_test.go +++ /dev/null @@ -1,95 +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 backup - -import ( - "testing" - - "gitlab.com/elixxir/client/storage/versioned" - "gitlab.com/elixxir/ekv" - "gitlab.com/xx_network/primitives/netTime" -) - -// Tests that savePassword saves the password to storage by loading it and -// comparing it to the original. -func Test_savePassword(t *testing.T) { - kv := versioned.NewKV(ekv.MakeMemstore()) - expectedPassword := "MySuperSecurePassword" - - // Save the password - err := savePassword(expectedPassword, kv) - if err != nil { - t.Errorf("savePassword returned an error: %+v", err) - } - - // Attempt to load the password - obj, err := kv.Get(passwordStorageKey, passwordStorageVersion) - if err != nil { - t.Errorf("Failed to get password from storage: %+v", err) - } - - // Check that the password matches the original - if expectedPassword != string(obj.Data) { - t.Errorf("Loaded password does not match original."+ - "\nexpected: %q\nreceived: %q", expectedPassword, obj.Data) - } -} - -// Tests that loadPassword restores the original password saved to stage and -// compares it to the original. -func Test_loadPassword(t *testing.T) { - kv := versioned.NewKV(ekv.MakeMemstore()) - expectedPassword := "MySuperSecurePassword" - - // Save the password - err := kv.Set(passwordStorageKey, passwordStorageVersion, &versioned.Object{ - Version: passwordStorageVersion, - Timestamp: netTime.Now(), - Data: []byte(expectedPassword), - }) - if err != nil { - t.Errorf("Failed to save password to storage: %+v", err) - } - - // Attempt to load the password - loadedPassword, err := loadPassword(kv) - if err != nil { - t.Errorf("loadPassword returned an error: %+v", err) - } - - // Check that the password matches the original - if expectedPassword != loadedPassword { - t.Errorf("Loaded password does not match original."+ - "\nexpected: %q\nreceived: %q", expectedPassword, loadedPassword) - } -} - -// Tests that deletePassword deletes the password from storage by trying to recover a -// deleted password. -func Test_deletePassword(t *testing.T) { - kv := versioned.NewKV(ekv.MakeMemstore()) - expectedPassword := "MySuperSecurePassword" - - // Save the password - err := savePassword(expectedPassword, kv) - if err != nil { - t.Errorf("Failed to save password to storage: %+v", err) - } - - // Delete the password - err = deletePassword(kv) - if err != nil { - t.Errorf("deletePassword returned an error: %+v", err) - } - - // Attempt to load the password - obj, err := loadPassword(kv) - if err == nil || obj != "" { - t.Errorf("Loaded object from storage when it should be deleted: %+v", obj) - } -} diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go index 224489af202afd203c1f917ce163b901deeade3d..52b29d45f1661cb025799d993e401e2dd9108cc3 100644 --- a/cmix/gateway/hostPool.go +++ b/cmix/gateway/hostPool.go @@ -271,7 +271,7 @@ func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator, return result, nil } -// initialize initializes the HostPool with a performant set of Hosts. +// initialize the HostPool with a performant set of Hosts. func (h *HostPool) initialize(startIdx uint32) error { // If HostPool is full, there is no need to initialize if startIdx == h.poolParams.PoolSize { diff --git a/cmix/nodes/register.go b/cmix/nodes/register.go index 80c85547f333df28eda9cd21b14a98ab73623d71..000b5751501b8120c35f099f3a2db59257a8fb07 100644 --- a/cmix/nodes/register.go +++ b/cmix/nodes/register.go @@ -95,7 +95,7 @@ func registerNodes(r *registrar, s session, stop *stoppable.Single, // Process the result if err != nil { - jww.ERROR.Printf("Failed to register nodes: %s", err.Error()) + jww.ERROR.Printf("Failed to register node: %s", err.Error()) // If we have not reached the attempt limit for this gateway, // then send it back into the channel to retry if numAttempts < maxAttempts { diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go index b75f7801cbb53ed41843a92511a2e89cfafae91f..f41b6b88e2cf476c59f8b00344cfff7101537673 100644 --- a/cmix/nodes/request.go +++ b/cmix/nodes/request.go @@ -64,8 +64,8 @@ func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface, result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) { keyResponse, err2 := comms.SendRequestClientKeyMessage(host, signedKeyReq) if err2 != nil { - return nil, errors.WithMessage(err2, - "Register: Failed requesting client key from gateway") + return nil, errors.WithMessagef(err2, + "Register: Failed requesting client key from gateway %s", gatewayID.String()) } if keyResponse.Error != "" { return nil, errors.WithMessage(err2, diff --git a/go.mod b/go.mod index 45cbd29359501276d3da18b7745794d21cdaaa8c..51d6cbb6177ab2785337edbe1864cbca8ac62689 100644 --- a/go.mod +++ b/go.mod @@ -12,12 +12,12 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.7.1 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f - gitlab.com/elixxir/comms v0.0.4-0.20220323190139-9ed75f3a8b2c - gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b + gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 + gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea gitlab.com/elixxir/ekv v0.1.7 - gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f + gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac - gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce + gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 gitlab.com/xx_network/primitives v0.0.4-0.20220324193139-b292d1ae6e7e go.uber.org/ratelimit v0.2.0 golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed diff --git a/go.sum b/go.sum index c3aa45ee09d936b71b808d039ce87d0ea1bd0b5d..21c95717bd4b37fdda8fb56a405cf34685a293d7 100644 --- a/go.sum +++ b/go.sum @@ -397,6 +397,8 @@ gitlab.com/elixxir/comms v0.0.4-0.20220308183624-c2183e687a03 h1:4eNjO3wCyHgxpGe gitlab.com/elixxir/comms v0.0.4-0.20220308183624-c2183e687a03/go.mod h1:4yMdU+Jee5W9lqkZGHJAuipEhW7FloT0eyVEFUJza+E= gitlab.com/elixxir/comms v0.0.4-0.20220323190139-9ed75f3a8b2c h1:ajjTw08YjRjl3HvtBNGtoCWhOg8k8upqmTweH18wkC4= gitlab.com/elixxir/comms v0.0.4-0.20220323190139-9ed75f3a8b2c/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk= +gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 h1:Zid8oNHtbOqF6ebrcGIccvIMabFNGh9dzY1b7mgIcF0= +gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= gitlab.com/elixxir/crypto v0.0.7-0.20220222221347-95c7ae58da6b/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= @@ -442,6 +444,10 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220513133141-46faee2d8fca h1:0EINaZCe/0dPbQ gitlab.com/elixxir/crypto v0.0.7-0.20220513133141-46faee2d8fca/go.mod h1:cJF80ad9YCR+UcOlZNzfDVBAQqGEEhhs3y5taMEvXaE= gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b h1:HZlcbi+rTr1MACtLoNUJDV2iTvy7JtkRjWWaPF45bcM= gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b/go.mod h1:L3duHa+GppnsY8x22/ixrEdQSM7WXa1ORWPS90HZ/JI= +gitlab.com/elixxir/crypto v0.0.7-0.20220606195831-6a6ac5f01c05 h1:q3KPJN/LfL2+5R24ls0ZhJmSn9FH4pC9BLBLlgKEBrE= +gitlab.com/elixxir/crypto v0.0.7-0.20220606195831-6a6ac5f01c05/go.mod h1:TeqwH6LVx1uabvFB9IpYOdy9/myQbVwmW8Ktn0IQc/E= +gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea h1:+FjwbKl6X9TDT7qd7gG5N5PSbziPWP3NgjK5ci1b7/8= +gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea/go.mod h1:Oy+VWQ2Sa0Ybata3oTV+Yc46hkaDwAsuIMW0wJ01z2M= gitlab.com/elixxir/ekv v0.1.6 h1:M2hUSNhH/ChxDd+s8xBqSEKgoPtmE6hOEBqQ73KbN6A= gitlab.com/elixxir/ekv v0.1.6/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/ekv v0.1.7 h1:OW2z+N4QCqqMFzouAwFTWWMKz0Y/PDhyYReN7gQ5NiQ= @@ -458,6 +464,8 @@ gitlab.com/elixxir/primitives v0.0.3-0.20220325212708-5e2a7a385db7 h1:2yIEkxkPJb gitlab.com/elixxir/primitives v0.0.3-0.20220325212708-5e2a7a385db7/go.mod h1:MtFIyJUQn9P7djzVlBpEYkPNnnWFTjZvw89swoXY+QM= gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f h1:bOX9nsG+ihvZAUP2OimpM/0UNIcfz5tYlvQfS2IFUoU= gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= +gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f h1:CTf2+ewHWYrzp5Ar3RwNvHePfTHyFniJTVjFW4zqoaE= +gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= gitlab.com/xx_network/comms v0.0.4-0.20220223205228-7c4974139569/go.mod h1:isHnwem0v4rTcwwHP455FhVlFyPcHkHiVz+N3s/uCSI= gitlab.com/xx_network/comms v0.0.4-0.20220311192415-d95fe8906580 h1:IV0gDwdTxtCpc9Vkx7IeSStSqvG+0ZpF57X+OhTQDIM= @@ -474,6 +482,10 @@ gitlab.com/xx_network/crypto v0.0.5-0.20220502201458-dabab1ef2982 h1:iUMwO/lIeOE gitlab.com/xx_network/crypto v0.0.5-0.20220502201458-dabab1ef2982/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce h1:zkPtJLJUpoWDYD4z30nmKU8OvnIOnBvSu7e6q6WhY5A= gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= +gitlab.com/xx_network/crypto v0.0.5-0.20220606200131-b631a14ef56c h1:F3smqkDtpBdjCzn+quaQvPo1GLkam5JJYp3ppoWVa6M= +gitlab.com/xx_network/crypto v0.0.5-0.20220606200131-b631a14ef56c/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= +gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 h1:9HK48ZEGFKLm3HBcE/FdQitllJRYPPS0zeaiRL+MBhI= +gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk= gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug= gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc= diff --git a/groupChat/receive.go b/groupChat/receive.go index 56f8d56fd76cb2461b0612ee3492812596463e89..63e6f91c0c904351d2c8590d29ebb7aa9a6d98d8 100644 --- a/groupChat/receive.go +++ b/groupChat/receive.go @@ -9,6 +9,7 @@ package groupChat import ( "fmt" + "gitlab.com/xx_network/primitives/netTime" "time" "github.com/pkg/errors" @@ -55,8 +56,10 @@ func (p *receptionProcessor) Process(message format.Message, } // Obtain the decryption key for the public message + // We use PRECOMPUTING here because all Rounds have that timestamp available to them + // QUEUED can be missing sometimes and cause a lot of hidden problems further down the line key, err := getCryptKey(p.g.Key, pubMsg.GetSalt(), message.GetMac(), - pubMsg.GetPayload(), p.g.DhKeys, round.Timestamps[states.QUEUED]) + pubMsg.GetPayload(), p.g.DhKeys, round.Timestamps[states.PRECOMPUTING]) if err != nil { jww.ERROR.Printf(getDecryptionKeyErr, err) return @@ -125,6 +128,12 @@ func decryptMessage(g gs.Group, fingerprint format.Fingerprint, func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte, dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) { + // If given zero time, try to guesstimate roundTimestamp as right now + if roundTimestamp.Equal(time.Unix(0, 0)) { + jww.ERROR.Printf("getCryptKey missing roundTimestamp") + roundTimestamp = netTime.Now() + } + // Compute the current epoch epoch := group.ComputeEpoch(roundTimestamp) for _, dhKey := range dhKeys { diff --git a/groupChat/send_test.go b/groupChat/send_test.go index bad4858985f742c681d090d92d5137b4e5bfd66f..71e252e5835ba1834f6108dbba0e6e813884df0b 100644 --- a/groupChat/send_test.go +++ b/groupChat/send_test.go @@ -51,7 +51,7 @@ func Test_manager_Send(t *testing.T) { } timestamps := make(map[states.Round]time.Time) - timestamps[states.QUEUED] = netTime.Now().Round(0) + timestamps[states.PRECOMPUTING] = netTime.Now().Round(0) for _, msg := range messages { reception.Process(msg, receptionID.EphemeralIdentity{ EphId: ephemeral.Id{1, 2, 3}, Source: &id.ID{4, 5, 6},