Skip to content
Snippets Groups Projects
Commit 6d9f24f4 authored by Jake Taylor's avatar Jake Taylor
Browse files

add release changes

parent 29a1cd96
No related branches found
No related tags found
3 merge requests!510Release,!232Modify restructure branch to make it ready for merge to release,!207WIP: Client Restructure
...@@ -51,12 +51,26 @@ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/clie ...@@ -51,12 +51,26 @@ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/clie
#### Fetching an NDF #### 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 $ go run main.go getndf --gwhost localhost:8440 --cert certfile.pem | jq . >ndf.json
``` ```
...@@ -83,10 +97,16 @@ Sample content of `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 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 # Get user contact jsons for each client
...@@ -102,9 +122,9 @@ Message received: ...@@ -102,9 +122,9 @@ Message received:
Sending to Qm40C5hRUm7uhp5aATVWhSL6Mt+Z4JVBQrsEDvMORh4D: Sending to Qm40C5hRUm7uhp5aATVWhSL6Mt+Z4JVBQrsEDvMORh4D:
Received 1 Received 1
# Alternatively, to accept an authenticated channel request implicitly # Accept/Confirm an authenticated channel request implicitly
# (should be within the timeout window of requesting client, or the request will need to be resent): # (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 $ 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 Authentication channel request from: o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD
Sending to o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD: Sending to o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD:
Message received: Message received:
...@@ -128,7 +148,7 @@ Received 0 ...@@ -128,7 +148,7 @@ Received 0
* `-s`: The storage directory for client session data. * `-s`: The storage directory for client session data.
* `--writeContact`: Output the user's contact information to this file. * `--writeContact`: Output the user's contact information to this file.
* `--destfile` is used to specify the recipient. You can also use * `--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 * `--unsafe`: Send message without encryption (necessary whenever you have not
already established an e2e channel). already established an e2e channel).
* `--unsafe-channel-creation` Auto-create and auto-accept channel requests. * `--unsafe-channel-creation` Auto-create and auto-accept channel requests.
...@@ -136,12 +156,12 @@ Received 0 ...@@ -136,12 +156,12 @@ Received 0
Note that the client defaults to sending to itself when a destination is not supplied. 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. 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 For the authenticated channel creation to be considered "safe", the user should be prompted. You can do this by
on the command line by explicitly accepting the channel creation explicitly accepting the channel creation
when sending a request with `--send-auth-request` and/or explicitly accepting a request with when sending a request with `--send-auth-request` (while excluding the `--unsafe-channel-creation` flag) or explicitly
`--accept-channel`: 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 $ 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: ...@@ -151,6 +171,61 @@ Message received:
Received 1 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`: Full usage of client can be found with `client --help`:
``` ```
...@@ -232,7 +307,8 @@ platforms. ...@@ -232,7 +307,8 @@ platforms.
Clients need to perform the same actions *in the same order* as shown in 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 `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. 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. The [Getting Started](https://xxdk-dev.xx.network/getting-started) guide provides further detail.
......
...@@ -271,7 +271,7 @@ func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator, ...@@ -271,7 +271,7 @@ func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator,
return result, nil 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 { func (h *HostPool) initialize(startIdx uint32) error {
// If HostPool is full, there is no need to initialize // If HostPool is full, there is no need to initialize
if startIdx == h.poolParams.PoolSize { if startIdx == h.poolParams.PoolSize {
......
...@@ -95,7 +95,7 @@ func registerNodes(r *registrar, s session, stop *stoppable.Single, ...@@ -95,7 +95,7 @@ func registerNodes(r *registrar, s session, stop *stoppable.Single,
// Process the result // Process the result
if err != nil { 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, // If we have not reached the attempt limit for this gateway,
// then send it back into the channel to retry // then send it back into the channel to retry
if numAttempts < maxAttempts { if numAttempts < maxAttempts {
......
...@@ -64,8 +64,8 @@ func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface, ...@@ -64,8 +64,8 @@ func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface,
result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) { result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) {
keyResponse, err2 := comms.SendRequestClientKeyMessage(host, signedKeyReq) keyResponse, err2 := comms.SendRequestClientKeyMessage(host, signedKeyReq)
if err2 != nil { if err2 != nil {
return nil, errors.WithMessage(err2, return nil, errors.WithMessagef(err2,
"Register: Failed requesting client key from gateway") "Register: Failed requesting client key from gateway %s", gatewayID.String())
} }
if keyResponse.Error != "" { if keyResponse.Error != "" {
return nil, errors.WithMessage(err2, return nil, errors.WithMessage(err2,
......
...@@ -9,6 +9,7 @@ package groupChat ...@@ -9,6 +9,7 @@ package groupChat
import ( import (
"fmt" "fmt"
"gitlab.com/xx_network/primitives/netTime"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
...@@ -55,8 +56,10 @@ func (p *receptionProcessor) Process(message format.Message, ...@@ -55,8 +56,10 @@ func (p *receptionProcessor) Process(message format.Message,
} }
// Obtain the decryption key for the public 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(), 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 { if err != nil {
jww.ERROR.Printf(getDecryptionKeyErr, err) jww.ERROR.Printf(getDecryptionKeyErr, err)
return return
...@@ -125,6 +128,12 @@ func decryptMessage(g gs.Group, fingerprint format.Fingerprint, ...@@ -125,6 +128,12 @@ func decryptMessage(g gs.Group, fingerprint format.Fingerprint,
func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte, func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte,
dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) { 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 // Compute the current epoch
epoch := group.ComputeEpoch(roundTimestamp) epoch := group.ComputeEpoch(roundTimestamp)
for _, dhKey := range dhKeys { for _, dhKey := range dhKeys {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment