From f5b6e4d0959ca03848892f929907300aa202d12f Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 10 Aug 2023 19:12:56 +0000 Subject: [PATCH 01/17] wallet: add doc for importing seeds --- README.md | 3 +++ docs/wallets.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 docs/wallets.md diff --git a/README.md b/README.md index 3d7cba7..40a7f32 100644 --- a/README.md +++ b/README.md @@ -45,4 +45,7 @@ This repository is actively being developed and does not cointain the latest exp * The mathematical companion can be found in [a separate repo](https://github.com/apoelstra/volvelle-math-companion) * The official website is at https://secretcodex32.com +# For Wallet Developers + +See our [Wallet Developer Guide](./docs/wallets.md) diff --git a/docs/wallets.md b/docs/wallets.md new file mode 100644 index 0000000..8cdc059 --- /dev/null +++ b/docs/wallets.md @@ -0,0 +1,57 @@ +# For Wallet Developers + +codex32 is a new format for BIP32 master seeds. It is essentially a replacement for +BIP39 or SLIP39 seed words, and the user workflow should be much the same, except +that: + +* The character set is different (bech32 characters rather than a wordlist). +* Seeds may be encoded across multiple shares, rather than a single string. +* It is possible to do specific error detection/correction during entry. + +There are two levels of wallet support: + +* The ability to import seeds/shares; here we essentially just have recommendations about dealing with errors. +* The ability to generate seeds/shares on the device; here our guidance is more involved. + +We encourage every wallet to support importing seeds and shares, since +* the technial difficulty is low (roughly on par with that of supporting Segwit addresses, plus optional error-correction support); +* the added functionality is isolated from the rest of the wallet (once the seed is imported you don't care where it came from); and +* beyond correctness of the code, there is little risk (no need to source randomness or execute potentially variable-time algoritms). + +Supporting seed generation is a little more involved so the tradeoff between +implementation complexity and user value is less clear, especially since the +Codex provides users instructions on doing generation themselves. + +## Import Support + +codex32 shares may be any length between 128 and 512 bits. +Wallets should support import of 128- or 256-bit seeds; other lengths are optional. + +128-bit seeds are 48 characters in length, including the `MS1` prefix. +256-bit seeds are 74. For other bitlengths, see the BIP. + +The process for entering shares is: + +1. The user should select the bit length of the import before entering any actual data. +1. Then the user should enter the first share. To the entext possible given screen limitations, when entering share data, data should be displayed in uppercase, visually separated into four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. +1. Once the first share is fully entered, the wallet should validate the checksum and header before accepting it. + * The user should not be able to entire mixed-case or non-bech32 characters. + * If the header is invalid, the wallet should highlight this and prevent the user from entering additional data until it is fixed. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. + * If the checksum is invalid, the wallet may use an error-correction algorithm to determine a corrected share, but the wallet MUST show these corrections to the user rather than silently applying them. + * For substitution errors, the wallet may highlight the offending 4-character window or the offending character. It may also show the corrected character. + * If the wallet can determine insertion or deletion errors, it should highlight the offending 4-character window. +1. After the first share has been entered and accepted, the wallet now knows the seed ID and threshold value. + * If the first share had index `S`, this was the actual seed and the import process is complete. + * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. +1. The user should then enter the remaining shares, in the same manner as the first. + * The wallet may pre-fill the header (threshold value and seed ID). + * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected. +1. Once all shares are entered, the wallet should derive the master seed and import this. + +**The master seed should be used directly as a master seed, as specified in BIP32.** +Unlike in BIP39 or other specifications, no PBKDF or other pre-processing should be applied. + +## Generate Support + +TODO + From 3fcfe9681667a49fa6069f0e5c5c9fac30fc6f2b Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 14 Aug 2023 15:22:45 +0000 Subject: [PATCH 02/17] import doc: update based on comments from ben and russell --- docs/wallets.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 8cdc059..0b12c68 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -14,9 +14,9 @@ There are two levels of wallet support: * The ability to generate seeds/shares on the device; here our guidance is more involved. We encourage every wallet to support importing seeds and shares, since -* the technial difficulty is low (roughly on par with that of supporting Segwit addresses, plus optional error-correction support); +* the technical difficulty is low (roughly on par with that of supporting Segwit addresses, plus optional error-correction support); * the added functionality is isolated from the rest of the wallet (once the seed is imported you don't care where it came from); and -* beyond correctness of the code, there is little risk (no need to source randomness or execute potentially variable-time algoritms). +* beyond correctness of the code, there is little risk (no need to source randomness or execute potentially variable-time algorithms). Supporting seed generation is a little more involved so the tradeoff between implementation complexity and user value is less clear, especially since the @@ -28,18 +28,18 @@ codex32 shares may be any length between 128 and 512 bits. Wallets should support import of 128- or 256-bit seeds; other lengths are optional. 128-bit seeds are 48 characters in length, including the `MS1` prefix. -256-bit seeds are 74. For other bitlengths, see the BIP. +256-bit seeds are 74. For other bit-lengths, see the BIP. The process for entering shares is: -1. The user should select the bit length of the import before entering any actual data. -1. Then the user should enter the first share. To the entext possible given screen limitations, when entering share data, data should be displayed in uppercase, visually separated into four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. +1. The user should enter the first share. To the extent possible given screen limitations, when entering share data, data should be displayed in uppercase, with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. 1. Once the first share is fully entered, the wallet should validate the checksum and header before accepting it. - * The user should not be able to entire mixed-case or non-bech32 characters. + * The user should not be able to entire mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, e.g. by attempting to replace all `B`s with `8`s.) * If the header is invalid, the wallet should highlight this and prevent the user from entering additional data until it is fixed. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. * If the checksum is invalid, the wallet may use an error-correction algorithm to determine a corrected share, but the wallet MUST show these corrections to the user rather than silently applying them. * For substitution errors, the wallet may highlight the offending 4-character window or the offending character. It may also show the corrected character. - * If the wallet can determine insertion or deletion errors, it should highlight the offending 4-character window. + * If the wallet can determine insertion or deletion errors, it should highlight the offending 4-character window. When detecting insertion or deletion errors, the wallet may assume that the correct share length is a multiple of 16 bytes. +1. If the share length is *not* 16, 32 or 64 bytes, but the checksum passes, the wallet should confirm that the user intends to import a non-standard share length. 1. After the first share has been entered and accepted, the wallet now knows the seed ID and threshold value. * If the first share had index `S`, this was the actual seed and the import process is complete. * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. From 4e2826006546e18cb7bd76b69326c153a52d0c96 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 14 Aug 2023 23:33:01 +0000 Subject: [PATCH 03/17] more BenWestgate comments --- docs/wallets.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 0b12c68..ea0e905 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -5,7 +5,7 @@ BIP39 or SLIP39 seed words, and the user workflow should be much the same, excep that: * The character set is different (bech32 characters rather than a wordlist). -* Seeds may be encoded across multiple shares, rather than a single string. +* Seeds may be split across multiple shares, rather than encoded as a single string. * It is possible to do specific error detection/correction during entry. There are two levels of wallet support: @@ -34,8 +34,8 @@ The process for entering shares is: 1. The user should enter the first share. To the extent possible given screen limitations, when entering share data, data should be displayed in uppercase, with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. 1. Once the first share is fully entered, the wallet should validate the checksum and header before accepting it. - * The user should not be able to entire mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, e.g. by attempting to replace all `B`s with `8`s.) - * If the header is invalid, the wallet should highlight this and prevent the user from entering additional data until it is fixed. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. + * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, e.g. by attempting to replace all `B`s with `8`s.) + * If the header is invalid, the wallet should highlight this and prevent the user from entering additional data until it is fixed. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. * If the checksum is invalid, the wallet may use an error-correction algorithm to determine a corrected share, but the wallet MUST show these corrections to the user rather than silently applying them. * For substitution errors, the wallet may highlight the offending 4-character window or the offending character. It may also show the corrected character. * If the wallet can determine insertion or deletion errors, it should highlight the offending 4-character window. When detecting insertion or deletion errors, the wallet may assume that the correct share length is a multiple of 16 bytes. @@ -45,7 +45,7 @@ The process for entering shares is: * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet may pre-fill the header (threshold value and seed ID). - * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected. + * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index should be replaced by `?`. 1. Once all shares are entered, the wallet should derive the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From 78029f48b1098189eb5f4751c6ac9b9fa00d55ed Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 20 Aug 2023 14:31:58 +0000 Subject: [PATCH 04/17] another round of BenWestgate comments --- docs/wallets.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index ea0e905..7e59644 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -35,14 +35,15 @@ The process for entering shares is: 1. The user should enter the first share. To the extent possible given screen limitations, when entering share data, data should be displayed in uppercase, with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. 1. Once the first share is fully entered, the wallet should validate the checksum and header before accepting it. * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, e.g. by attempting to replace all `B`s with `8`s.) - * If the header is invalid, the wallet should highlight this and prevent the user from entering additional data until it is fixed. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. - * If the checksum is invalid, the wallet may use an error-correction algorithm to determine a corrected share, but the wallet MUST show these corrections to the user rather than silently applying them. - * For substitution errors, the wallet may highlight the offending 4-character window or the offending character. It may also show the corrected character. - * If the wallet can determine insertion or deletion errors, it should highlight the offending 4-character window. When detecting insertion or deletion errors, the wallet may assume that the correct share length is a multiple of 16 bytes. + * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. + * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the share and show these to the user. It MAY additinally determine corrected share data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. + * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. + * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct share length is 16, 32 or (optionally) 64 bytes. 1. If the share length is *not* 16, 32 or 64 bytes, but the checksum passes, the wallet should confirm that the user intends to import a non-standard share length. 1. After the first share has been entered and accepted, the wallet now knows the seed ID and threshold value. * If the first share had index `S`, this was the actual seed and the import process is complete. * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. + * Wallets MAY encrypt and store recovery progress, to allow recovery without having all shares available at once. The details of this are currently outside of the scope of this specification. 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet may pre-fill the header (threshold value and seed ID). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index should be replaced by `?`. From a01ef25ea2760e3ec18d5f152e9acd44f794733a Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 24 Sep 2023 18:01:01 +0000 Subject: [PATCH 05/17] another round of BenWestgate comments --- docs/wallets.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 7e59644..cf10265 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -32,21 +32,23 @@ Wallets should support import of 128- or 256-bit seeds; other lengths are option The process for entering shares is: -1. The user should enter the first share. To the extent possible given screen limitations, when entering share data, data should be displayed in uppercase, with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. -1. Once the first share is fully entered, the wallet should validate the checksum and header before accepting it. - * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, e.g. by attempting to replace all `B`s with `8`s.) - * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. - * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the share and show these to the user. It MAY additinally determine corrected share data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. +1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. +1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. + * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) + * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first string. + * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the string and show these to the user. It MAY additionally determine corrected data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. - * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct share length is 16, 32 or (optionally) 64 bytes. -1. If the share length is *not* 16, 32 or 64 bytes, but the checksum passes, the wallet should confirm that the user intends to import a non-standard share length. -1. After the first share has been entered and accepted, the wallet now knows the seed ID and threshold value. - * If the first share had index `S`, this was the actual seed and the import process is complete. + * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). +1. If the string length is *not* 48, 74 or 127 characters, but the checksum passes, the wallet should confirm that the user intends to import a non-standard string length. + * If the string length is *not* 48, 74 or 127 bytes, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting or inserting up to 3 characters. +1. After the first string has been entered and accepted, the wallet now knows the identifier and threshold value. + * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. * Wallets MAY encrypt and store recovery progress, to allow recovery without having all shares available at once. The details of this are currently outside of the scope of this specification. 1. The user should then enter the remaining shares, in the same manner as the first. - * The wallet may pre-fill the header (threshold value and seed ID). - * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index should be replaced by `?`. + * The wallet SHOULD pre-fill the header (threshold value and identifier). + * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. + * The wallet MUST assume the valid length of all subsequent strings is equal to the valid length of the first string. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters. 1. Once all shares are entered, the wallet should derive the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From 5b358f43e9759c14107ab74fb39e14388e58f3af Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 1 Oct 2023 17:10:32 +0000 Subject: [PATCH 06/17] final(?) round of BenWestgate comments --- docs/wallets.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index cf10265..3c568bd 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -1,6 +1,6 @@ # For Wallet Developers -codex32 is a new format for BIP32 master seeds. It is essentially a replacement for +Codex32 is a new format for BIP32 master seeds. It is essentially a replacement for BIP39 or SLIP39 seed words, and the user workflow should be much the same, except that: @@ -24,7 +24,7 @@ Codex provides users instructions on doing generation themselves. ## Import Support -codex32 shares may be any length between 128 and 512 bits. +Codex32 shares may be any length between 128 and 512 bits. Wallets should support import of 128- or 256-bit seeds; other lengths are optional. 128-bit seeds are 48 characters in length, including the `MS1` prefix. @@ -35,13 +35,13 @@ The process for entering shares is: 1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. 1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) - * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first string. + * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the string and show these to the user. It MAY additionally determine corrected data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). -1. If the string length is *not* 48, 74 or 127 characters, but the checksum passes, the wallet should confirm that the user intends to import a non-standard string length. - * If the string length is *not* 48, 74 or 127 bytes, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting or inserting up to 3 characters. -1. After the first string has been entered and accepted, the wallet now knows the identifier and threshold value. +1. If the string length is *not* 48, 74 or 127 bytes, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting or inserting up to 3 characters. + * If the wallet succeeds in error correction by deleting or inserting characters, it MUST ask the user for confirmation that they have a nonstandard-length string. +1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. * Wallets MAY encrypt and store recovery progress, to allow recovery without having all shares available at once. The details of this are currently outside of the scope of this specification. @@ -49,7 +49,7 @@ The process for entering shares is: * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. * The wallet MUST assume the valid length of all subsequent strings is equal to the valid length of the first string. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters. -1. Once all shares are entered, the wallet should derive the master seed and import this. +1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** Unlike in BIP39 or other specifications, no PBKDF or other pre-processing should be applied. From b5f74d1bdd532840beb1318f7aace9227b8cf971 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 1 Oct 2023 17:15:25 +0000 Subject: [PATCH 07/17] change 'string' back to 'share' in two places --- docs/wallets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wallets.md b/docs/wallets.md index 3c568bd..cf8794f 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -48,7 +48,7 @@ The process for entering shares is: 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. - * The wallet MUST assume the valid length of all subsequent strings is equal to the valid length of the first string. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters. + * The wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From 395c251402a5bcfd7dd235e2e3479652902f2ae5 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 22 Oct 2023 13:30:45 +0000 Subject: [PATCH 08/17] another round of BenWestgate comments --- docs/wallets.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index cf8794f..3bc6826 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -24,13 +24,13 @@ Codex provides users instructions on doing generation themselves. ## Import Support -Codex32 shares may be any length between 128 and 512 bits. -Wallets should support import of 128- or 256-bit seeds; other lengths are optional. +Wallets MAY accept seeds whose length is any multiple of 8 between 128 and 512 bits, inclusive. +Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optional. -128-bit seeds are 48 characters in length, including the `MS1` prefix. -256-bit seeds are 74. For other bit-lengths, see the BIP. +128-bit seeds encode as length-48 codex32 strings, including the `MS1` prefix. +256-bit seeds encode as length-74 codex32 strings. For other bit-lengths, see the BIP. -The process for entering shares is: +The process for entering codex32 strings is: 1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. 1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. @@ -39,16 +39,16 @@ The process for entering shares is: * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the string and show these to the user. It MAY additionally determine corrected data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). -1. If the string length is *not* 48, 74 or 127 bytes, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting or inserting up to 3 characters. +1. If the string length is *not* 48, 74 or 127 characters, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. * If the wallet succeeds in error correction by deleting or inserting characters, it MUST ask the user for confirmation that they have a nonstandard-length string. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. - * Otherwise, the first character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. + * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. * Wallets MAY encrypt and store recovery progress, to allow recovery without having all shares available at once. The details of this are currently outside of the scope of this specification. 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. - * The wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters. + * The wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters to match the length of the first share. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From 0e62ae22410fa52996e618e61271238b3d3a50b5 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 22 Oct 2023 14:31:43 +0000 Subject: [PATCH 09/17] clarify insertion/deletion instructions for subsequent shares --- docs/wallets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wallets.md b/docs/wallets.md index 3bc6826..15bc782 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -48,7 +48,7 @@ The process for entering codex32 strings is: 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. - * The wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share. If the lengths do not match, the wallet MAY attempt correction by deleting or inserting characters to match the length of the first share. + * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting up to 3 characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From 8e6c3335849a873ef25532c7a3ec92c020189b39 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 22 Oct 2023 15:03:20 +0000 Subject: [PATCH 10/17] change "confirm length" line to "confirm any corrections" --- docs/wallets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wallets.md b/docs/wallets.md index 15bc782..17f7df2 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -40,7 +40,6 @@ The process for entering codex32 strings is: * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). 1. If the string length is *not* 48, 74 or 127 characters, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. - * If the wallet succeeds in error correction by deleting or inserting characters, it MUST ask the user for confirmation that they have a nonstandard-length string. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. @@ -49,6 +48,7 @@ The process for entering codex32 strings is: * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting up to 3 characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. +1. For all codex32 strings, if the entered string does not pass the checksum but the wallet is able to correct the errors (by substitution, insertion and/or deletion), the wallet MUST show the corrected string to the user and request confirmation that the corrected string matches the user's copy of the data. The wallet MAY highlight the locations of changed characters. The wallet MUST NOT silently apply corrections without approval from the user. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From c12312095e05065e5ae0aa22dc77f6a62d6e8218 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 22 Oct 2023 20:37:20 +0000 Subject: [PATCH 11/17] "exactly matches" --- docs/wallets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wallets.md b/docs/wallets.md index 17f7df2..2d44214 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -48,7 +48,7 @@ The process for entering codex32 strings is: * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting up to 3 characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. -1. For all codex32 strings, if the entered string does not pass the checksum but the wallet is able to correct the errors (by substitution, insertion and/or deletion), the wallet MUST show the corrected string to the user and request confirmation that the corrected string matches the user's copy of the data. The wallet MAY highlight the locations of changed characters. The wallet MUST NOT silently apply corrections without approval from the user. +1. For all codex32 strings, if the entered string does not pass the checksum but the wallet is able to correct the errors (by substitution, insertion and/or deletion), the wallet MUST show the corrected string to the user and request confirmation that the corrected string **exactly matches** the user's copy of the data. The wallet MAY highlight the locations of changed characters. The wallet MUST NOT silently apply corrections without approval from the user. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.** From b325ee812f319f3853b427d60424aa336c4ec201 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 25 Oct 2023 22:30:01 +0000 Subject: [PATCH 12/17] new BenWestgate suggested text --- docs/wallets.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 2d44214..c491f63 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -36,10 +36,10 @@ The process for entering codex32 strings is: 1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. - * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to locate errors in the string and show these to the user. It MAY additionally determine corrected data, but if so, the wallet MUST show these corrections to the user rather than silently applying them. - * To show locations of substitution errors, the wallet SHOULD highlight the offending 4-character window or the specific offending character. - * If the wallet can determine insertion or deletion errors, it SHOULD highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). -1. If the string length is *not* 48, 74 or 127 characters, and the checksum does *not* pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. + * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to attempt to correct errors in the string. If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. + * To show locations of substitution errors, the wallet MAY highlight the offending 4-character window or the specific offending character. + * If the wallet can determine insertion or deletion errors, it MAY highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). +1. If the checksum does not pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. From 8de58bb6d5df2f6370a87d593b98465b8fe7e515 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 25 Oct 2023 22:30:41 +0000 Subject: [PATCH 13/17] reorder a couple lines --- docs/wallets.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index c491f63..8c95982 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -33,13 +33,13 @@ Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optio The process for entering codex32 strings is: 1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. -1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. +1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. + * If the checksum does not pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to attempt to correct errors in the string. If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. * To show locations of substitution errors, the wallet MAY highlight the offending 4-character window or the specific offending character. * If the wallet can determine insertion or deletion errors, it MAY highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). -1. If the checksum does not pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. From f6953274b415f6cb16d1e34e94bb0c2efd97f969 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 25 Oct 2023 22:32:28 +0000 Subject: [PATCH 14/17] change length-X to X-character --- docs/wallets.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 8c95982..1763b58 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -27,8 +27,8 @@ Codex provides users instructions on doing generation themselves. Wallets MAY accept seeds whose length is any multiple of 8 between 128 and 512 bits, inclusive. Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optional. -128-bit seeds encode as length-48 codex32 strings, including the `MS1` prefix. -256-bit seeds encode as length-74 codex32 strings. For other bit-lengths, see the BIP. +128-bit seeds encode as 48-character codex32 strings, including the `MS1` prefix. +256-bit seeds encode as 74-character codex32 strings. For other bit-lengths, see the BIP. The process for entering codex32 strings is: From 2bd4cbec1f41221398662b0b95b41f4d7285b33d Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 26 Oct 2023 13:55:38 +0000 Subject: [PATCH 15/17] introduce "error-correcting wallet" and change checksum text to use this term --- docs/wallets.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 1763b58..2129656 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -22,6 +22,19 @@ Supporting seed generation is a little more involved so the tradeoff between implementation complexity and user value is less clear, especially since the Codex provides users instructions on doing generation themselves. +## Error Detection and Correction + +Wallets MUST support detection of errors using the codex32 checksum algorithm. +Wallets MAY additionally support error correction; such wallets are referred to as "error-correcting wallets (ECWs)" and have additional requirements. + +An ECW + +* MUST support correction of up to 4 substitution errors; +* MAY also support correction of up to 8 erasures; +* MAY support correction of further errors, including insertion or deletion errors. + +If a wallet is unable to meet these specifications, it is not an ECW and it SHOULD NOT expose error-correction functionality to the user. + ## Import Support Wallets MAY accept seeds whose length is any multiple of 8 between 128 and 512 bits, inclusive. @@ -33,10 +46,11 @@ Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optio The process for entering codex32 strings is: 1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. - * The user should not be able to enter mixed-case characters. The user must be able to enter all bech32 characters as well as `?` indicating an erasure. Wallets may allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) + * The user should not be able to enter mixed-case characters. The user MUST be able to enter all bech32 characters. ECWs MUST also allow entry of `?` which indicates an erasure (unknown character). Wallets MAY allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. -1. Once the first string is fully entered, the wallet should validate the checksum and header before accepting it. - * If the checksum does not pass, then the wallet MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. +1. Once the first string is fully entered, the wallet MUST validate the checksum and header before accepting it. + * If the checksum does not pass, then an ECW MUST attempt error correction of substitution and erasure errors. + * If the checksum does not pass, an ECW MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to attempt to correct errors in the string. If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. * To show locations of substitution errors, the wallet MAY highlight the offending 4-character window or the specific offending character. * If the wallet can determine insertion or deletion errors, it MAY highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). From 3ea09d411f8dd43b84e58481cbd26ca8d0293727 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 26 Oct 2023 13:59:50 +0000 Subject: [PATCH 16/17] more BenWestgate text cleanups --- docs/wallets.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 2129656..49f60cd 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -49,11 +49,11 @@ The process for entering codex32 strings is: * The user should not be able to enter mixed-case characters. The user MUST be able to enter all bech32 characters. ECWs MUST also allow entry of `?` which indicates an erasure (unknown character). Wallets MAY allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. 1. Once the first string is fully entered, the wallet MUST validate the checksum and header before accepting it. - * If the checksum does not pass, then an ECW MUST attempt error correction of substitution and erasure errors. - * If the checksum does not pass, an ECW MAY attempt correction by deleting and/or inserting up to 3 characters, as long as the resulting string has a valid length for a codex32 string. - * If the checksum is invalid, the wallet SHOULD use an error-correction algorithm to attempt to correct errors in the string. If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. - * To show locations of substitution errors, the wallet MAY highlight the offending 4-character window or the specific offending character. - * If the wallet can determine insertion or deletion errors, it MAY highlight the offending 4-character window or the specific location of the inserted or missing character. When detecting insertion or deletion errors, the wallet MAY assume that the correct string length is 48, 74 or (optionally) 127 characters (corresponding to 16-, 32- or 64-byte seeds). + * If the checksum does not pass, then an ECW + * MUST attempt error correction of substitution and erasure errors. + * MAY attempt correction by deleting and/or inserting characters, as long as the resulting string has a valid length for a codex32 string. + * If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. + * When displaying a candidate correction, wallets MAY highlight the corrected 4-character windows and/or the specific locations of substitution, insertion and/or deletion corrections. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. @@ -61,7 +61,7 @@ The process for entering codex32 strings is: 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet SHOULD pre-fill the header (threshold value and identifier). * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. - * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting up to 3 characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. + * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. 1. For all codex32 strings, if the entered string does not pass the checksum but the wallet is able to correct the errors (by substitution, insertion and/or deletion), the wallet MUST show the corrected string to the user and request confirmation that the corrected string **exactly matches** the user's copy of the data. The wallet MAY highlight the locations of changed characters. The wallet MUST NOT silently apply corrections without approval from the user. 1. Once all shares are entered, the wallet should recover the master seed and import this. From 4e812322ad72f9cd09c01e17fe2b6ce9c3d4a9f0 Mon Sep 17 00:00:00 2001 From: Ben Westgate <73506583+BenWestgate@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:02:24 -0600 Subject: [PATCH 17/17] Update wallets.md --- docs/wallets.md | 51 +++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/docs/wallets.md b/docs/wallets.md index 49f60cd..4012b4e 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -25,44 +25,57 @@ Codex provides users instructions on doing generation themselves. ## Error Detection and Correction Wallets MUST support detection of errors using the codex32 checksum algorithm. -Wallets MAY additionally support error correction; such wallets are referred to as "error-correcting wallets (ECWs)" and have additional requirements. +Wallets SHOULD additionally support error correction; such wallets are referred to as "error-correcting wallets (ECWs)" and have additional requirements. -An ECW +An ECW: -* MUST support correction of up to 4 substitution errors; -* MAY also support correction of up to 8 erasures; +* MUST support correction of up to 4 substitution errors and erasures; +* MAY also support correction of up to 8 erasures, up to 13 if contiguous; * MAY support correction of further errors, including insertion or deletion errors. If a wallet is unable to meet these specifications, it is not an ECW and it SHOULD NOT expose error-correction functionality to the user. ## Import Support -Wallets MAY accept seeds whose length is any multiple of 8 between 128 and 512 bits, inclusive. -Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optional. - -128-bit seeds encode as 48-character codex32 strings, including the `MS1` prefix. -256-bit seeds encode as 74-character codex32 strings. For other bit-lengths, see the BIP. +Wallets SHOULD support import of 128- and 256-bit seeds; other lengths are optional. 128-bit seeds encode as 48-character codex32 strings, including the `MS1` prefix. 256-bit seeds encode as 74-character codex32 strings. For other bit-lengths, see the BIP. The process for entering codex32 strings is: -1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which should be pre-filled. - * The user should not be able to enter mixed-case characters. The user MUST be able to enter all bech32 characters. ECWs MUST also allow entry of `?` which indicates an erasure (unknown character). Wallets MAY allow users to enter non-bech32 characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) - * If the header is invalid, the wallet SHOULD highlight this and request confirmation from the user before allowing additional data to be entered. An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share. +1. The user should enter the first string. To the extent possible given screen limitations, data should be displayed in uppercase with visually distinct four-character windows. The first four-character window should include the `MS1` prefix, which SHOULD be pre-filled. + * The user MUST be able to enter all bech32 characters. + * ECWs MUST also allow entry of `?` which indicates an erasure (unknown character). + * The user SHOULD NOT be able to enter mixed-case characters. + * If the header is invalid, the wallet SHOULD highlight the problem and request confirmation from the user before allowing additional data to be entered. + * An invalid header is one that starts with a character other than `0` or `2` through `9`, or one which starts with `0` but whose share index is not `S`. For shares after the first, a header is also invalid if its threshold and identifier do not match those of the first share or whose share index matches any previous share. + * ECWs MAY replace the offending characters of the header with '?'. + * Wallets MAY: + * Allow users to enter invalid characters, at their discretion. (This may be useful to guide error correction, by attempting to replace commonly confused characters.) + * Use predictive text for on-screen keyboards to suggest the codex32 checksum characters but if so MUST require user to manually accept the prediction. + * Indicate when the entry has a valid checksum, e.g. by highlighting the string green or displaying the 'Submit' option but they MUST NOT submit a string with a valid checksum without user request. + * ECWs MAY additionally indicate when an entry of sufficient length to correct has an invalid checksum, e.g. by highlighting the string red or displaying an "Attempt Correction" option. + + 1. Once the first string is fully entered, the wallet MUST validate the checksum and header before accepting it. - * If the checksum does not pass, then an ECW - * MUST attempt error correction of substitution and erasure errors. - * MAY attempt correction by deleting and/or inserting characters, as long as the resulting string has a valid length for a codex32 string. - * If a valid candidate correction is found, the wallet MUST show it to the user for confirmation rather than silently applying it. - * When displaying a candidate correction, wallets MAY highlight the corrected 4-character windows and/or the specific locations of substitution, insertion and/or deletion corrections. + * If the checksum does not pass, then an ECW: + * MUST attempt error correction of substitution errors and erasures. + * MAY attempt correction by deleting and/or inserting characters, as long as the resulting string has a valid length for a codex32 string. ECWs MAY assume the correct length is the closest of 48 or 74. + * MUST show any valid correction candidate found to the user for confirmation rather than silently applying it. + * If insertion and/or deletion correction candidates are found, the shortest edit distance valid string SHOULD be displayed. + * This is the sum of all edits with erasures and deletes weighted 1 and substitutions and insertions weighted 2. + * ECWs displaying a candidate correction MAY highlight corrected 4-character windows and/or specific correction locations. 1. After the first string has been entered and accepted, the wallet now knows the identifier, threshold value and valid length. * If the first string had index `S`, this was the codex32 secret and the import process is complete. * Otherwise, the fourth character of the share will be a numeric character between `2` and `9` inclusive. The user must enter this many shares in total. * Wallets MAY encrypt and store recovery progress, to allow recovery without having all shares available at once. The details of this are currently outside of the scope of this specification. 1. The user should then enter the remaining shares, in the same manner as the first. * The wallet SHOULD pre-fill the header (threshold value and identifier). - * If the user tries to repeat an already-entered share index, they should be prevented from entering additional data until it is corrected, with the exception that `?` may be used as a share index arbitrarily many times. The wallet may guide the user by indicating that a share index has been repeated; if the user indicates that they are not repeating the share, the share index SHOULD be replaced by `?`. + * If the user tries to repeat an already-entered share index, they SHOULD be prevented from entering additional data until it is corrected. + * The wallet MAY guide the user by indicating that a share index has been repeated; + * ECWs may use `?` as a share index arbitrarily many times. If the user indicates they are not repeating the share, the share index SHOULD be replaced by `?`. * If the checksum fails, the wallet MAY attempt correction by deleting and/or inserting characters. However, the wallet MUST assume the valid length of all subsequent shares is equal to the valid length of the first share, so the number of characters inserted and deleted must net out to the correct length. -1. For all codex32 strings, if the entered string does not pass the checksum but the wallet is able to correct the errors (by substitution, insertion and/or deletion), the wallet MUST show the corrected string to the user and request confirmation that the corrected string **exactly matches** the user's copy of the data. The wallet MAY highlight the locations of changed characters. The wallet MUST NOT silently apply corrections without approval from the user. +1. For all invalid codex32 strings entered, if an ECW is able to correct the errors (by deletion, insertion, substitution and/or filling erasures), it MUST show the corrected string to the user and request confirmation that the corrected string **exactly matches** the user's copy of the data. It MUST NOT silently apply corrections without approval from the user. + * If no valid string is found with a correct hrp, header and unique index within correction distance limits or within 10 seconds of search, give up. + * ECWs MAY warn the user they've repeated a share if the only valid string found exactly matches a previously entered share. 1. Once all shares are entered, the wallet should recover the master seed and import this. **The master seed should be used directly as a master seed, as specified in BIP32.**