From 173c425bf920e8f5afdc3fbbdf4a361d25e4d2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=20G=C3=A1mez=20Franco?= Date: Mon, 27 Jan 2025 11:43:38 +0100 Subject: [PATCH 1/4] WIP test flows documentation. --- README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..e69de29bb From 24e5c3c8092c2b3e16de589581e19420787a2998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=20G=C3=A1mez=20Franco?= Date: Mon, 27 Jan 2025 11:44:11 +0100 Subject: [PATCH 2/4] WIP test flows documentation. --- README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/README.md b/README.md index e69de29bb..c0372d7c9 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,84 @@ +# ArConnect Browser Extension & ArConnect Embedded + +## Testing + +### Embedded + +Scenarios to test: + +**New account & wallet:** + +After signing up, a new account is created. Verify: + +- A new wallet is generated and split with SSS. +- The wallet seedphrase is persisted encrypted in `localStorage` to allow future wallet exports as seedphrase (in this + same device only). +- A `deviceNonce` is generated and persisted in `localStorage`. +- Its `authShare` is stored in the server +- Its `deviceShare` is persisted in `localStorage`. + +**Wallet backup:** + +After signing up/in, backup a wallet using the wallet recovery option, twice on the same wallet. Verify: + +- The wallet we are backing is split with SSS. +- Its `recoveryAuthShare` is stored in the server. +- Its `recoveryBackupShare` is downloaded in a JSON file. +- The JSON file includes a signature from the server, that allows it to verify this file was once filed even after the + recovery share is deleted from the DB. +- The `recoveryBackupShare` is persisted encrypted in `localStorage` to avoid re-creating new recovery shares if the + user wants to download it again on that same device. +- Downloading the same wallet recovery option doesn't register a new recovery share on the backend, as stated above. + +**Wallet activation:** + +After signing in or reloading a session on an existing account a wallet should be activated: + +- Initially (v0.1), the last recently used wallet with a matching `deviceShare` available will be automatically + activated upon successful authentication. + +- Later (v1.0), no wallet will be activated until the user/dApp tries to use it. At that point, it will be activated. + After some time (TBD), it will be deactivated (removed from memory, even encrypted). + +Then, verify: + +- The `deviceSharePublicKey` is generated using the `deviceShare`. +- A wallet activation challenge is requested from the backend, providing the target `walletId`. +- An `authShare` is fetched after solving the server activation challenge and providing it with the `deviceNonce`. +- The wallet private key is reconstructed and stored encrypted in memory, with a randomly generated password that is + rotated regularly (until the wallet is deactivated in v1.0) + +Note: The backend should also verify when requesting or resolving activation challenges that the `deviceNonce` matches +the stored device data (ip, country, userAgent...). + +**Wallet recovery (`deviceNonce` gone):** + +**Wallet recovery (`deviceShare` gone):** + +4A. (AR+R) Delete deviceShare. Reload. Account fetched. no authShare fetched, deviceNonce not sent (because +deviceShare is missing). Recovery screen. recoveryShare provided. authRecoveryShare fetched. +pk reconstructed. pk re-split into new deviceShare and authShare. Recovery stays the same. deviceNonce with +corresponding authShare stays on the server (we have no way to tell if it's still needed). + +4B. (AR+R) Delete deviceNonce. Same as above. + +5A. encrypted recoveryShare deleted. Download recoveryShard. It needs to be re-split, so a new recoveryShare - +authRecoveryShare is generated and stored. + +5B. encrypted recoveryShare deleted. Download recoveryShard. It needs to be re-split, so a new recoveryShare - +authRecoveryShare is generated and stored. The backend says only 2 can be stored, so user must pick which one +to delete. + +6. (DR+R) Recover account. This rare scenario happens when the user loses access to their authentication, + but still has access to a previously used device and recoveryShare. + recoveryShare provided. pk reconstructed. Challenge signature sent. Old auth methods + cleared. New one added. pk re-split. deviceNonce, authShare and deviceShare generated. + +7 (DR + AR) Recover account. This rare scenario happens when the user has access to a previously used device that +somehow lost the deviceShare, but not the deviceRecoveryShare, and they do not have the recovery share (so 6 and +4 not possible). This is unlikely to happen, so we could not serve AR, given DR, only given R. This just happens +to be a possibility if we go for a 2/3 SSS scheme for the recovery shares to enable DR+R. + +7. (pk) Recover account. pk provided. Signature sent. Auth methods cleared. pk re-split. + +8. Weird scenarios where the address is not right. From 5fbd2313402235c8cec8bc5932a230e9a2147316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=20G=C3=A1mez=20Franco?= Date: Mon, 27 Jan 2025 12:30:59 +0100 Subject: [PATCH 3/4] Document test scenarios. --- README.md | 60 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c0372d7c9..713202048 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ After signing up, a new account is created. Verify: - The wallet seedphrase is persisted encrypted in `localStorage` to allow future wallet exports as seedphrase (in this same device only). - A `deviceNonce` is generated and persisted in `localStorage`. -- Its `authShare` is stored in the server +- Its `authShare` is stored in the server, linked to that specific `deviceNonce`. - Its `deviceShare` is persisted in `localStorage`. **Wallet backup:** @@ -53,32 +53,48 @@ the stored device data (ip, country, userAgent...). **Wallet recovery (`deviceNonce` gone):** -**Wallet recovery (`deviceShare` gone):** +On an active session or previously used device, remove the `deviceNonce` from `localStorage`. Then verify: + +- The app detects the `deviceNonce` is gone and re-generates it. +- Trying to activate a wallet will fail as the newly generated `deviceNonce` is not linked to any of the existing shares + stored in the DB. +- The wallet recovery flow is presented to users. +- The `recoveryBackupSharePublicKey` is generated using the `recoveryBackupShare` the user provided using a wallet + recovery file. +- A wallet recovery challenge is requested form the backend, providing the target `walletId`. As this is the first + action performed using the newly generated `deviceNonce`, the new device will be registered on the backend. +- A `recoveryAuthShare` is fetched after solving the server wallet recovery challenge and providing it with the new + `deviceNonce`, which was just registered. +- The wallet private key is reconstructed and stored encrypted in memory, with a randomly generated password that is + rotated regularly (until the wallet is deactivated in v1.0). Also, the private key is split again using SSS and the + new work shares are stored in `localStorage` and the server (as per the _New account & wallet_ flow). -4A. (AR+R) Delete deviceShare. Reload. Account fetched. no authShare fetched, deviceNonce not sent (because -deviceShare is missing). Recovery screen. recoveryShare provided. authRecoveryShare fetched. -pk reconstructed. pk re-split into new deviceShare and authShare. Recovery stays the same. deviceNonce with -corresponding authShare stays on the server (we have no way to tell if it's still needed). +**Wallet recovery (`deviceShare` gone):** -4B. (AR+R) Delete deviceNonce. Same as above. +On an active session or previously used device, remove the `deviceShare` from `localStorage`. Then verify: -5A. encrypted recoveryShare deleted. Download recoveryShard. It needs to be re-split, so a new recoveryShare - -authRecoveryShare is generated and stored. +- The app detects the `deviceShare` is gone and the recovery flow is presented to users. +- The `recoveryBackupSharePublicKey` is generated using the `recoveryBackupShare` the user provided using a wallet + recovery file. +- A wallet recovery challenge is requested form the backend, providing the target `walletId` and the `deviceNonce`. +- A `recoveryAuthShare` is fetched after solving the server wallet recovery challenge. +- The wallet private key is reconstructed and stored encrypted in memory, with a randomly generated password that is + rotated regularly (until the wallet is deactivated in v1.0). Also, the private key is split again using SSS and the + new work shares are stored in `localStorage` and the server (as per the _New account & wallet_ flow). -5B. encrypted recoveryShare deleted. Download recoveryShard. It needs to be re-split, so a new recoveryShare - -authRecoveryShare is generated and stored. The backend says only 2 can be stored, so user must pick which one -to delete. +**Account recovery:** -6. (DR+R) Recover account. This rare scenario happens when the user loses access to their authentication, - but still has access to a previously used device and recoveryShare. - recoveryShare provided. pk reconstructed. Challenge signature sent. Old auth methods - cleared. New one added. pk re-split. deviceNonce, authShare and deviceShare generated. +Click on the account recovery option, import a wallet seedphrase or private key linked to an account. Then verify: -7 (DR + AR) Recover account. This rare scenario happens when the user has access to a previously used device that -somehow lost the deviceShare, but not the deviceRecoveryShare, and they do not have the recovery share (so 6 and -4 not possible). This is unlikely to happen, so we could not serve AR, given DR, only given R. This just happens -to be a possibility if we go for a 2/3 SSS scheme for the recovery shares to enable DR+R. +- An account recovery list challenge is requested, sending the `walletAddress`. +- A list of wallets linked to that wallet is received upon successful resolution of the challenge. +- After selecting one account (if more than one are linked to the same wallet), an account recovery challenge is + requested, sending the `accountId`. +- A new authentication method can be linked to the account after solving the server account recovery challenge. -7. (pk) Recover account. pk provided. Signature sent. Auth methods cleared. pk re-split. +**Missing test scenarios:** -8. Weird scenarios where the address is not right. +- Reached out work shares limit. +- Reached out recovery shares limit. +- Link auth methods to existing accounts. +- Different errors when the different params mentioned in all the above are incorrect. From 50fd363fa219ec5fc929be73b7df644d7daabaa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=20G=C3=A1mez=20Franco?= Date: Mon, 27 Jan 2025 13:55:42 +0100 Subject: [PATCH 4/4] Move documented test flows for embedded to src/iframe. --- README.md => src/iframe/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename README.md => src/iframe/README.md (99%) diff --git a/README.md b/src/iframe/README.md similarity index 99% rename from README.md rename to src/iframe/README.md index 713202048..2c3ec0198 100644 --- a/README.md +++ b/src/iframe/README.md @@ -1,4 +1,4 @@ -# ArConnect Browser Extension & ArConnect Embedded +# ArConnect Embedded ## Testing