From 18193b4f56a386f658469463ba69375fe937ecfc Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Fri, 13 Dec 2024 20:29:09 -0300 Subject: [PATCH 1/5] book: add FROST Server section --- book/src/SUMMARY.md | 1 + book/src/zcash/server.md | 361 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 362 insertions(+) create mode 100644 book/src/zcash/server.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 3970f8e0..004ef64d 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -13,6 +13,7 @@ - [FROST with Zcash](zcash.md) - [Technical Details](zcash/technical-details.md) - [Ywallet Demo](zcash/ywallet-demo.md) + - [FROST Server](zcash/server.md) - [Terminology](terminology.md) - [Developer Documentation](dev.md) - [List of Dependencies for Audit](dev/frost-dependencies-for-audit.md) diff --git a/book/src/zcash/server.md b/book/src/zcash/server.md new file mode 100644 index 00000000..383d6df5 --- /dev/null +++ b/book/src/zcash/server.md @@ -0,0 +1,361 @@ +# FROST Server + +One challenge for using FROST is allowing participants to communicate securely +with one another. Devices are usually behind firewalls and NATs, which make +direct connections hard. + +To mitigate this issue and to make it easier to use FROST, the FROST Server +was created. It is a JSON-HTTP server with a small API to allow participants +to create signing sessions and to communicate with one another. + +It works like this: + +- Clients (coordinator or participants) authenticate to the server using a key + pair, which will likely be the same key pair they use to end-to-end encrypt + messages. +- The Coordinator creates a session, specifying the public keys of the + participants. +- Participants list sessions they're participating in, and choose the proceed + with the signing session. +- Coordinator and Participants run the FROST protocol, end-to-end encrypting + messages and sending them to the server. +- The Coordinator closes the session. + +Note that the server doesn't really care about the particular key pair being +used; it is only used to enforce who can send messages to who. + +## Compiling, Running and Deploying + +You will need to have [Rust and +Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) +installed. Run: + +``` +cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git frost-server +``` + +The `frost-server` binary will be installed [per `cargo` +config](https://doc.rust-lang.org/cargo/commands/cargo-install.html#description) +and it will likely be in your `$PATH`, so you can run by simply running +`frost-server`. + +To deploy the FROST Server, **you need TLS/HTTPS certificates**. We strongly +recommend using a reverse proxy such as `nginx` to handle TLS and to also add +denial of service protections. In that case, use the `--no-tls-very-insecure` +flag in `frost-server` and make `nginx` connect to it (see example config below). + +If you want to expose `frost-server` directly, use the `--tls-cert` and +`--tls-key` to specify the paths of the PEM-encoded certificate and key. You can +use [Let's Encrypt](https://letsencrypt.org/) to get a free certificate. + + +### Local Testing + +For local testing, you can use the [`mkcert` +tool](https://github.com/FiloSottile/mkcert). Install it and run: + +``` +mkcert -install +mkcert localhost 127.0.0.1 ::1 +``` + +Then start the server with: + +``` +frost-server --tls-cert localhost+2.pem --tls-key localhost+2-key.pem +``` + + +### Sample nginx Config + +This is a sample nginx config file tested in a Ubuntu deployment (i.e. it +assumes it's in a `http` block and it's included by `/etc/nginx/nginx.conf`); +copy it to `/etc/nginx/sites-enabled/frost-server` and run `sudo service nginx +restart`. + +The config assumes the certificates were copied to `/etc/ssl`. + + +``` +limit_req_zone $binary_remote_addr zone=challenge:10m rate=30r/m; +limit_req_zone $binary_remote_addr zone=create:10m rate=10r/m; +limit_req_zone $binary_remote_addr zone=other:10m rate=240r/m; +limit_conn_zone $binary_remote_addr zone=addr:10m; + +server { + listen 443 ssl; + listen [::]:443 ssl; + ssl_certificate /etc/ssl/localhost+2.pem; + ssl_certificate_key /etc/ssl/localhost+2-key.pem; + ssl_protocols TLSv1.3; + ssl_ecdh_curve X25519:prime256v1:secp384r1; + ssl_prefer_server_ciphers off; + + server_name localhost; + + client_body_timeout 5s; + client_header_timeout 5s; + + location / { + proxy_pass http://127.0.0.1:2744; + limit_req zone=other burst=5; + limit_conn addr 10; + } + location /challenge { + proxy_pass http://127.0.0.1:2744/challenge; + limit_req zone=challenge burst=3; + limit_conn addr 10; + } + location /create_new_session { + proxy_pass http://127.0.0.1:2744/create_new_session; + limit_req zone=create burst=3; + limit_conn addr 10; + } +} +``` + +## API + +The API uses JSON/HTTP. All requests should have `Content-Type: +application/json`. Errors are returned with status code 500 and the content +body will have a JSON such as: + +``` +{ code: 1, msg: "error message" } +``` + +The codes are: (TODO: link to source code?) + +``` +pub const INVALID_ARGUMENT: usize = 1; +pub const UNAUTHORIZED: usize = 2; +pub const SESSION_NOT_FOUND: usize = 3; +pub const NOT_COORDINATOR: usize = 4; +``` + + +### Usage flow + +For the Coordinator: + +- Log in with `/challenge` and `/login` +- Create a new signing session with `/create_new_session` +- Wait for round 1 messages by repeatedly polling `/receive` each 2 seconds or longer +- Send round 2 messages by using `/send` +- Wait for round 2 message by repeatedly polling `/receive` each 2 seconds or longer +- Close the session with `/close_session` + +For Participants: + +- Log in with `/challenge` and `/login` +- Wait for signing sessions with `/list_sessions`, either by the user's request or by repeatedly + polling each 10 seconds or longer +- Get the session information with `/get_session_info` +- Show the user the session information (who the participants are) to select which + session (if more than one) +- Send round 1 message by using `/send` +- Wait for round 2 message by repeatedly polling `/receive` each 2 seconds or longer +- Send round 2 message by using `/send` + +```admonish info +**Polling** is not optimal. The server will support a better mechanism in the +future. +``` + +```admonish info +Selecting sessions is tricky. Ideally, the user should select what session +to proceed by checking the message being signed; however, that is usually +sent in Round 2. There are multiple ways to handle this: + +- Simply show the users who are participant, hoping that is enough to + disambiguate (we assume that concurrent signing sessions won't be that common) +- Quietly proceed with all sessions, and only prompt the user after the message + is received. (It's harmless to do round 1 of FROST even if the user might + not have agreed to sign the message yet.) +- Change the application so that the message is sent to the participants first + (the server does not really care how the protocol is run). +``` + +```admonish critical +Always gather consent from the user by showing them the message before +signing it. +``` + +### `/challenge` + +Input: empty + +Sample output: + +``` +{"challenge":"2c5cdb6d-a7db-470e-9e6f-2a7062532825"} +``` + +Returns a challenge that the client will need to sign in order to authenticate. + +### `/login` + +To call `/login`, you will need to sign the challenge with XEdDSA, see example +(TODO: link). Sign the challenge UUID, converted to bytes. + +TODO: fill valid signature + +Input sample: + +``` +{ + "challenge":"2c5cdb6d-a7db-470e-9e6f-2a7062532825", + "pubkey":"3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", + "signature":"" +} +``` + +Output sample: + +``` +{"access_token":"5a21ebf4-3f28-4198-bf3d-6174851adbb9"} +``` + +The returned access token must be included as a bearer token in an +`Authorization` header; e.g. `Authorization: Bearer +5a21ebf4-3f28-4198-bf3d-6174851adbb9`. + +Access token are currently valid for 1 hour. It's recommended to login at the +beginning of each FROST session; log in again if it needs to take longer. + +### `/logout` + +Input: empty (it will logout the authenticated user) + +Output: empty + +Logs out, invalidating the access token. Note that access tokens expire after +1 hour anyway. + +### `/create_new_session` + +Input sample: + +``` +{ + "pubkeys": [ + "3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", + "edbd661dec0a9d0468b4a166a4afa80560d769f6bcb152fb8f4224059329a518" + ], + message_count: 1, +} +``` + +Output sample: + +``` +{"session_id": "2c5cdb6d-a7db-470e-9e6f-2a7062532825"} +``` + +Creates a new session. The requesting user will be the Coordinator, and the +users with the hex-encoded public keys given in `pubkeys` will be the +participants (which might or might not include the Coordinator itself). + +The `message_count` parameter allows signing more than one message in the same +signing session, which will save roundtrips. This does not impacts the server +itself and is used to signal the participants (via `/get_session_info`). + +### `/list_sessions` + +Input: empty (it will list for the authenticated user) + +Output sample: + +``` +{"session_ids": ["2c5cdb6d-a7db-470e-9e6f-2a7062532825"]} +``` + +List the sessions IDs of the session a participant is in. + +### `/get_session_info` + +Input sample: + +```{"session_id": "2c5cdb6d-a7db-470e-9e6f-2a7062532825"}``` + +Output sample: + +``` +{ + "message_count": 1, + "pubkeys": [ + "3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", + "edbd661dec0a9d0468b4a166a4afa80560d769f6bcb152fb8f4224059329a518" + ], + "coordinator_pubkey": "3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", +} +``` + +Returns information about the given session. + +### `/send` + +Input sample: + +``` +{ + "session_id": "2c5cdb6d-a7db-470e-9e6f-2a7062532825", + "recipients": ["3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c"], + "msg": "000102", +} +``` + +Output: empty + +Sends a (hex-encoded) message to one or more participants. To send to the +Coordinator, pass an empty list in `recipients` (**do not** use the +Coordinator's public key, because that might be ambiguous if they're also a +Participant). + +```admonish critical +Messages **MUST** be end-to-end encrypted to their recipients. The server can't +enforce this and if you will fail to encrypt them then the server could read +all the messages. +``` + +### `/receive` + +Input sample: + +``` +{ + "session_id": "2c5cdb6d-a7db-470e-9e6f-2a7062532825", + "as_coordinator": false, +} +``` + +Output sample: + +``` +{ + "msgs":[ + { + "sender": "3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", + "msg": "000102", + } + ] +} +``` + +Receives messages sent to the requesting user. Note that if a user is both a +Coordinator and a Participant, it is not possible to distinguish if a message +received from them was sent as Coordinator or as a Participant. This does not +matter in FROST since this ambiguity never arises (Participants always receive +messages from the Coordinator, and vice-versa, except during DKG where there is +no Coordinator anyway). + +### `/close_session` + +Input sample: + +```{"session_id": "2c5cdb6d-a7db-470e-9e6f-2a7062532825"}``` + +Output: empty + +Closes the given session. Only the Coordinator who created the session can close +it. Sessions also expire, by default after 24 hours. From af385a17973a47c96ef3f60853e0703b73fc36d2 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Fri, 17 Jan 2025 20:50:29 -0300 Subject: [PATCH 2/5] book: update Ywallet demo section --- book/src/zcash/server.md | 22 +-- book/src/zcash/ywallet-demo.md | 296 ++++++++++++++++++++++----------- 2 files changed, 210 insertions(+), 108 deletions(-) diff --git a/book/src/zcash/server.md b/book/src/zcash/server.md index 383d6df5..e878f011 100644 --- a/book/src/zcash/server.md +++ b/book/src/zcash/server.md @@ -1,12 +1,12 @@ -# FROST Server +# ZF FROST Server (frostd) One challenge for using FROST is allowing participants to communicate securely with one another. Devices are usually behind firewalls and NATs, which make direct connections hard. -To mitigate this issue and to make it easier to use FROST, the FROST Server -was created. It is a JSON-HTTP server with a small API to allow participants -to create signing sessions and to communicate with one another. +To mitigate this issue and to make it easier to use FROST, the ZF FROST Server +(frostd) was created. It is a JSON-HTTP server with a small API to allow +participants to create signing sessions and to communicate with one another. It works like this: @@ -31,20 +31,20 @@ Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed. Run: ``` -cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git frost-server +cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git --locked frostd ``` -The `frost-server` binary will be installed [per `cargo` +The `frostd` binary will be installed [per `cargo` config](https://doc.rust-lang.org/cargo/commands/cargo-install.html#description) and it will likely be in your `$PATH`, so you can run by simply running -`frost-server`. +`frostd`. To deploy the FROST Server, **you need TLS/HTTPS certificates**. We strongly recommend using a reverse proxy such as `nginx` to handle TLS and to also add denial of service protections. In that case, use the `--no-tls-very-insecure` -flag in `frost-server` and make `nginx` connect to it (see example config below). +flag in `frostd` and make `nginx` connect to it (see example config below). -If you want to expose `frost-server` directly, use the `--tls-cert` and +If you want to expose `frostd` directly, use the `--tls-cert` and `--tls-key` to specify the paths of the PEM-encoded certificate and key. You can use [Let's Encrypt](https://letsencrypt.org/) to get a free certificate. @@ -62,7 +62,7 @@ mkcert localhost 127.0.0.1 ::1 Then start the server with: ``` -frost-server --tls-cert localhost+2.pem --tls-key localhost+2-key.pem +frostd --tls-cert localhost+2.pem --tls-key localhost+2-key.pem ``` @@ -70,7 +70,7 @@ frost-server --tls-cert localhost+2.pem --tls-key localhost+2-key.pem This is a sample nginx config file tested in a Ubuntu deployment (i.e. it assumes it's in a `http` block and it's included by `/etc/nginx/nginx.conf`); -copy it to `/etc/nginx/sites-enabled/frost-server` and run `sudo service nginx +copy it to `/etc/nginx/sites-enabled/frostd` and run `sudo service nginx restart`. The config assumes the certificates were copied to `/etc/ssl`. diff --git a/book/src/zcash/ywallet-demo.md b/book/src/zcash/ywallet-demo.md index ea4f1343..701bad0e 100644 --- a/book/src/zcash/ywallet-demo.md +++ b/book/src/zcash/ywallet-demo.md @@ -1,7 +1,8 @@ # Ywallet Demo Tutorial This tutorial explaining how to run the FROST demo using Ywallet that was -[presented during Zcon4](https://www.youtube.com/watch?v=xvzESdDtczo). +[presented during Zcon4](https://www.youtube.com/watch?v=xvzESdDtczo) (though it +has been updated and it differs from what was presented). Ywallet supports [offline signing](https://ywallet.app/advanced/offline_signature/), which allows having a @@ -11,88 +12,215 @@ the transaction plan with a command line tool, using FROST. This tutorial assumes familiarity with the command line. + ## Setting up Install `cargo` and `git`. [Install Ywallet](https://ywallet.app/installation/). -Clone the repository: +Install the `frost-client` tool: + +``` +cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git --locked frost-client +``` + +Install the `zcash-sign` tool: + +``` +cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git --locked zcash-sign +``` + +Switch to an empty folder which will store the files generate in the demo. +For example: ``` -git clone https://github.com/ZcashFoundation/frost-zcash-demo.git +mkdir frost-demo +cd frost-demo/ +``` + + +### Running the server + +This demo uses the ZF FROST server (frostd) to help participants communicate. +While in practice users would use an existing online server, for the demo you +can run a local server by following [these instructions](./server.md) (the +"Compiling, Running and Deploying" and "Local Testing" sections). + +The rest of the tutorial assumes the server is up and running. + + +### Initializing the users + +Run the following command to initialize three users (in practice, each user +would run a similar command, but for demo purposes we're assuming +you will simulate all of them in the same machine, so run these +commands in your machine): + +``` +frost-client init -c alice.toml +frost-client init -c bob.toml +frost-client init -c eve.toml +``` + +This will create a config file for three users; Alice, Bob and Eve. + +```admonish note +If you really want to run the demo in separate machines, then you can omit the +`-c alice.toml` part of the command (i.e. run `frost-client init`); it will +save to a default location in the user's home directory. ``` + ## Generating FROST key shares First we will generate the FROST key shares. For simplicity we'll use trusted -dealer, DKG will be described later. +dealer; if you want to use Distributed Key Generation, skip to the next section. + +In a new terminal (in case the previous terminal is running the server), run the +following: + +``` +frost-client trusted-dealer -d "Alice, Bob and Eve's group" --names Alice,Bob,Eve -c alice.toml -c bob.toml -c eve.toml -C redpallas +``` + +This will by default generate a 2-of-3 key shares. The key shares will be +written into each participant's config file. You can change the threhsold, +number of shares and file names using the command line; append `-h` to the +commend above for the command line help. + + +## Genearting FROST key shares using DKG + +For real-word usage we commend generating key shares using Distributed Key +Generation. If you did the previous section, skip to "Generating the Full +Viewing Key for the wallet". + + +```admonish note +This section assumes each participant is running the commands in their own +machine. If you want to simulate all of them in a single machine, +specify the config file for the user (e.g. `-c alice.toml`) accordingly. +``` + + +### Initializing config files + +If they haven't yet, each participant should run: + +``` +frost-client init +``` + + +### Sharing contacts + +Each participant must now generate a contact string that they will need to share +with the other participants. This contact string will include a name, which they +can choose when exporting and will be shown to whoever they send the contact to. + +Run the following, substituting the name accordingly: -Run the following (it will take a bit to compile): +``` +frost-client export --name 'Alice' +``` + +The command will print an encoded contact string such as +`zffrost1qyqq2stvd93k2g84hudcr98zp67a9rnx9v00euw9e5424hjathvre7ymy344fynjdvxmwxfg`. +Send it to the other participants using some trusted communication channel +(instant messaging, etc.). + +The other participants will send you their contacts. Import them by running the +following command for each contact (replace `` with the contact +string accordingly): ``` -cd frost-zcash-demo/ -cargo run --bin trusted-dealer -- -C redpallas +frost-client import ``` -This will by default generate a 2-of-3 key shares. The public key package -will be written to `public-key-package.json`, while key packages will be -written to `key-package-1.json` through `-3`. You can change the threshold, -number of shares and file names using the command line; append `-- -h` -to the command above for the command line help. -```admonish info -If you want to use DKG instead of Trusted Dealer, instead of the command above, - run this for each participant, in separate terminals for each: +### Generating shares + +Finally, to generate the shares, one of the participants will need to initiate +the process. They will need to public key of each participant, so they need to +first list them with the following command: + +``` +frost-client contacts +``` -`cargo run --bin dkg -- -C redpallas` +Then run the following command, replacing the `` and `` hex +strings with the public keys of the contacts which will participate (along with +the user running the command): -and follow the instructions. (There will be a considerable amount of -copy&pasting!) +``` +frost-client dkg -d 'Alice, Bob and Eve's group' -s localhost:2744 -S , -t 2 -C redpallas -c alice.toml ``` +The user should then notify the others that a signing session has started (e.g. +via instant messaging again), and also share the threshold number that was used. +They should then run the following, replacing the name of the group if they wish +and the threshold number with the one given by the first participant. + +``` +frost-client dkg -d 'Alice, Bob and Eve's group' -s localhost:2744 -t 2 -C redpallas +``` + +```admonish note +A future version might not require specifying the threshold and group name. +``` + + ## Generating the Full Viewing Key for the wallet -Get the `verifying_key` value that is listed inside the Public Key Package in -`public-key-package.json`. For example, in the following package +Next, we will need to generate a Zcash Full Viewing Key from the FROST group +material we have just generated; this address will then be imported into a wallet +so that we'll be able to create Zcash transactions for it. + +Run the following command: ``` -{"verifying_shares": ...snip... ,"verifying_key":"d2bf40ca860fb97e9d6d15d7d25e4f17d2e8ba5dd7069188cbf30b023910a71b","ciphersuite":"FROST(Pallas, BLAKE2b-512)"} +frost-client groups ``` -you would need to copy -`d2bf40ca860fb97e9d6d15d7d25e4f17d2e8ba5dd7069188cbf30b023910a71b`. +It will list all groups you're in - at this point it should list the only one +you have just created. Copy the Public Key it shows (it will look like e.g. +`79d6bcee79c88ad9ba259067772b97f5de12f1435b474d03bc98f255be08a610`) The run the following command, replacing `` with the value you copied. ``` -cd zcash-sign/ -cargo run --release -- generate --ak --danger-dummy-sapling +zcash-sign generate --ak --danger-dummy-sapling ``` It will print an Orchard address, and a Unified Full Viewing Key. Copy and paste both somewhere to use them later. + ## Importing the Full Viewing Key into Ywallet Open Ywallet and click "New account". Check "Restore an account" and paste the Unified Full Viewing Key created in the previous step. Click "Import". + ## Funding the wallet Now you will need to fund this wallet with some ZEC. Use the Orchard address printed by the signer (see warning below). Send ZEC to that address using another account (or try [ZecFaucet](https://zecfaucet.com/)). -```admonish warning +```admonish danger The address being show by Ywallet is a unified address that includes both an Orchard and Sapling address. For the demo to work, you need to receive funds in your Orchard address. Whether that will happen depends on multiple factors so it's probably easier to use just the Orchard-only address printed by the signer. -**If you send it to the Sapling address, the funds will be unspendable and lost!** +In Ywallet, you can also swipe right on the QR Code until it shows the "Orchard +Address". **IF YOU SEND IT TO THE SAPLING ADDRESS, THE FUNDS WILL BECOME +UNSPENDABLE AND WILL BE LOST!** ``` + ## Creating the transaction Now you will create the transaction that you wish to sign with FROST. Click @@ -102,112 +230,84 @@ click the arrow button. The wallet will show the transaction plan. Click the snowflake button. It will show a QR code, but we want that information as a file, so click the floppy disk -button and save the file somewhere (e.g. `tx.raw` as suggested by Ywallet). +button and save the file somewhere (e.g. `tx-plan.json`). + ## Signing the transaction +Now you will need to simulate two participants and a Coordinator to sign the +transaction, and you should still have the FROST server running which will +handle communications between them. It's probably easier to open three new +terminals. + Go back to the signer terminal and run the following, replacing `` with the path to the file you saved in the previous step, `` with the UFVK hex string printed previously, and `` with the path where you want to write the signed transaction (e.g. `tx-signed.raw`). ``` -cargo run --release -- sign --tx-plan --ufvk -o +zcash-sign sign --tx-plan --ufvk -o ``` -The program will print a SIGHASH and a Randomizer. - - -### Running the server - -Now you will need to simulate two participants and a Coordinator to sign the -transaction, and the FROST server that handles communications between them. -It's probably easier to open four terminals. +The program will print a SIGHASH and a Randomizer, and will prompt for a +signature. This is what you will get after running FROST, so let's do that; +leave the prompt there without typing anything. -In the first one, the server, run (in the same folder where key generation was -run): -``` -RUST_LOG=debug cargo run --bin server -``` - -### Registering users +### Coordinator -In order to interact with the server, you will need to register users. For this -guide we will need two. In a new terminal, run the following command for user -"alice" (replace the password if you want): +In the second terminal, the Coordinator, run (in the same folder where you +initialized the users and ran the key generation) the following: ``` -curl --data-binary '{"username": "alice", "password": "foobar10", "pubkey": ""}' -H 'Content-Type: application/json' http://127.0.0.1:2744/register +frost-client groups -c alice.toml ``` -It will output "null". (The "pubkey" parameter is not used currently and should -be empty.) Also register user "bob": +This will list the groups Alice is in; it should only list the one you created +earlier. You will need to copy some values in the command. Run the following, +replacing the value after `` with the "Public key" listed for the group; +replacing `` and `` with the public keys of Alice and Bob (the +hexadecimal values printed next to their names; Alice's name will be empty to +indicate it's her own). ``` -curl --data-binary '{"username": "bob", "password": "foobar10", "pubkey": ""}' -H 'Content-Type: application/json' http://127.0.0.1:2744/register +frost-client coordinator -c alice.toml --server-url localhost:2744 --group -S , -m - -r - ``` -You only need to do this once, even if you want to sign more than one -transaction. If for some reason you want to start over, close the server and -delete the `db.sqlite` file. +It will prompt you for a message. Paste the SIGHASH generated with the +`zcash-sign` tool and press enter. It will then prompt for a randomizer. Paste +the one generated with the `zcash-sign` tool and press enter. -Feel free to close this terminal, or reuse it for the next step. +The tool will connect to the server and wait for the other participants. ```admonish warning -Do not use passwords that you use in practice; use dummy ones instead. (You -shouldn't reuse passwords anyway!) For real world usage you would need to take -more care to not end up writing the password to your shell history. (In real -world usage we'd expect this to be done by applications anyway.) +If you prefer to pass the message (SIGHASH) or randomizer as files by using +the `-m` and `-r` arguments, you will need to convert them to binary format. ``` -### Coordinator -In the second terminal, the Coordinator, run (in the same folder where key -generation was run): +### Participant 1 (Alice) + +In the third terminal, Participant 1, run the following (replacing `` +with the same group public key used in the previous command): ``` -export PW=foobar10 -cargo run --bin coordinator -- -C redpallas --http -u alice -w PW -S alice,bob -r - +frost-client participant -c alice.toml --server-url localhost:2744 --group ``` -We will use "alice" as the Coordinator, so change the value next to `export PW=` -if you used another password when registering "alice". - -And then: - -- It should read the public key package from `public-key-package.json`. -- When prompted for the message to be signed, paste the SIGHASH printed by the - signer above (just the hex value, e.g. - ``4d065453cfa4cfb4f98dbc9cff60c4a3904ed91c523b8ef8d67d28bea7f12ea3``). -- When prompted for the randomizer, paste the randomizer printed by the signer - above (again just the hex value) +(We are using "Alice" again. There's nothing stopping a Coordinator from being a +Partcipant too!) -```admonish warning -If you prefer to pass the randomizer as a file by using the `--randomizer` -argument, you will need to convert it to binary format. -``` -### Participant 1 (alice) +### Participant 2 (Bob) -In the third terminal, Participant 1, run the following: +In the fourth terminal, for Participant 2, run the following (replacing `` +again): ``` -export PW=foobar10 -cargo run --bin participant -- -C redpallas --http --key-package key-package-1.json -u alice -w PW +frost-client participant -c bob.toml --server-url localhost:2744 --group ``` -(We are using "alice" again. There's nothing stopping a Coordinator from being a -Participant too!) - -### Participant 2 (bob) - -In the fourth terminal, for Participant 2, run the following: - -``` -export PW=foobar10 -cargo run --bin participant -- -C redpallas --http --key-package key-package-2.json -u bob -w PW -``` ### Coordinator @@ -218,10 +318,12 @@ successfully. It will print the final FROST-generated signature. Hurrah! Copy it Go back to the signer and paste the signature. It will write the raw signed transaction to the file you specified. + ## Broadcasting the transaction -Go back to Ywallet and return to its main screen. In the menu, select "Advanced" -and "Broadcast". Select the raw signed transaction file you have just generated -(`tx-signed.raw` if you followed the suggestion). +Go back to Ywallet and return to its main screen. In the menu, select "More" and +"Broadcast". Click the upper-right box-with-an-arrow icon and select the raw +signed transaction file you have just generated (`tx-signed.raw` if you followed +the suggestion). That's it! You just sent a FROST-signed Zcash transaction. From 8932af0c0e025eddcb1024f63dde01e272cb5859 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Mon, 3 Feb 2025 19:13:06 -0300 Subject: [PATCH 3/5] fill TODOs --- book/src/zcash/server.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/book/src/zcash/server.md b/book/src/zcash/server.md index e878f011..e1fb39f7 100644 --- a/book/src/zcash/server.md +++ b/book/src/zcash/server.md @@ -124,7 +124,9 @@ body will have a JSON such as: { code: 1, msg: "error message" } ``` -The codes are: (TODO: link to source code?) +The +[codes](https://github.com/ZcashFoundation/frost-zcash-demo/blob/548a8a7329c6eed8180464662f430d12cd71dfcc/frostd/src/lib.rs#L95-L98) +are: ``` pub const INVALID_ARGUMENT: usize = 1; @@ -195,30 +197,30 @@ Returns a challenge that the client will need to sign in order to authenticate. ### `/login` -To call `/login`, you will need to sign the challenge with XEdDSA, see example -(TODO: link). Sign the challenge UUID, converted to bytes. +To call `/login`, you will need to sign the challenge with XEdDSA, see +[example](https://github.com/ZcashFoundation/frost-zcash-demo/blob/548a8a7329c6eed8180464662f430d12cd71dfcc/frostd/tests/integration_tests.rs#L443-L476). +Sign the challenge UUID, converted to bytes. -TODO: fill valid signature Input sample: ``` { - "challenge":"2c5cdb6d-a7db-470e-9e6f-2a7062532825", - "pubkey":"3c9f4a3b2ae28c8e11fbc90b693a9712c181275fb4b554a140c68dc13cdd9b4c", - "signature":"" + "challenge":"b771757e-085a-4a88-ab8f-28bd4ba67f3a", + "pubkey":"f5bf1b8194e20ebdd28e662b1efcf1c5cd2aaade5d5dd83cf89b246b5492726b", + "signature":"bba398d0963ab88e28134ad41c127eeee816a219838db01dd7bcd9d7fcd975f082330c134e6f7238580ba8434652aa116891495452d9048f5615e07f4ad6b204" } ``` Output sample: ``` -{"access_token":"5a21ebf4-3f28-4198-bf3d-6174851adbb9"} +{"access_token":"061a18ba-2c3c-4685-a79e-2c0c93000af5"} ``` The returned access token must be included as a bearer token in an `Authorization` header; e.g. `Authorization: Bearer -5a21ebf4-3f28-4198-bf3d-6174851adbb9`. +061a18ba-2c3c-4685-a79e-2c0c93000af5`. Access token are currently valid for 1 hour. It's recommended to login at the beginning of each FROST session; log in again if it needs to take longer. From a0b73e050c71ae165a2e19237cc8a693d4fdce6f Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 4 Feb 2025 13:56:42 -0300 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: natalie --- book/src/zcash/server.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/zcash/server.md b/book/src/zcash/server.md index e1fb39f7..24cf6e28 100644 --- a/book/src/zcash/server.md +++ b/book/src/zcash/server.md @@ -169,7 +169,7 @@ Selecting sessions is tricky. Ideally, the user should select what session to proceed by checking the message being signed; however, that is usually sent in Round 2. There are multiple ways to handle this: -- Simply show the users who are participant, hoping that is enough to +- Simply show the users who are participants, hoping that is enough to disambiguate (we assume that concurrent signing sessions won't be that common) - Quietly proceed with all sessions, and only prompt the user after the message is received. (It's harmless to do round 1 of FROST even if the user might @@ -222,7 +222,7 @@ The returned access token must be included as a bearer token in an `Authorization` header; e.g. `Authorization: Bearer 061a18ba-2c3c-4685-a79e-2c0c93000af5`. -Access token are currently valid for 1 hour. It's recommended to login at the +Access tokens are currently valid for 1 hour. It's recommended to login at the beginning of each FROST session; log in again if it needs to take longer. ### `/logout` @@ -315,8 +315,8 @@ Coordinator's public key, because that might be ambiguous if they're also a Participant). ```admonish critical -Messages **MUST** be end-to-end encrypted to their recipients. The server can't -enforce this and if you will fail to encrypt them then the server could read +Messages **MUST** be end-to-end encrypted between recipients. The server can't +enforce this and if you fail to encrypt them then the server could read all the messages. ``` From a448949af5e38405fe43943b9c1a1dc2c5eb555f Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 4 Feb 2025 13:58:07 -0300 Subject: [PATCH 5/5] Apply suggestions from code review --- book/src/zcash/server.md | 2 +- book/src/zcash/ywallet-demo.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/zcash/server.md b/book/src/zcash/server.md index 24cf6e28..63503946 100644 --- a/book/src/zcash/server.md +++ b/book/src/zcash/server.md @@ -360,4 +360,4 @@ Input sample: Output: empty Closes the given session. Only the Coordinator who created the session can close -it. Sessions also expire, by default after 24 hours. +it. Sessions also expire by default after 24 hours. diff --git a/book/src/zcash/ywallet-demo.md b/book/src/zcash/ywallet-demo.md index 701bad0e..c36513ee 100644 --- a/book/src/zcash/ywallet-demo.md +++ b/book/src/zcash/ywallet-demo.md @@ -90,7 +90,7 @@ number of shares and file names using the command line; append `-h` to the commend above for the command line help. -## Genearting FROST key shares using DKG +## Generating FROST key shares using DKG For real-word usage we commend generating key shares using Distributed Key Generation. If you did the previous section, skip to "Generating the Full