Skip to content

Commit 6defa98

Browse files
committed
doc: Add codex32 application (93') to BIP-0085
1 parent eabb63c commit 6defa98

File tree

1 file changed

+240
-2
lines changed

1 file changed

+240
-2
lines changed

bip-0085.mediawiki

Lines changed: 240 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,237 @@ OUTPUT:
225225
* DERIVED ENTROPY=ae131e2312cdc61331542efe0d1077bac5ea803adf24b313a4f0e48e9c51f37f
226226
* DERIVED BIP39 MNEMONIC=puppy ocean match cereal symbol another shed magic wrap hammer bulb intact gadget divorce twin tonight reason outdoor destroy simple truth cigar social volcano
227227
228+
===BIP93 (codex32)===
229+
Application Number: 93'
230+
231+
The derivation path format is: <code>m/83696968'/93'/{hrp}'/{threshold}'/{n}'/{byte_length}'/{id0}'/{id1}'/{id2}'/{id3}'/{index}'</code>
232+
233+
Use this application to generate fresh codex32 strings (as defined in BIP-0093) for Shamir's Secret Sharing backups of BIP-0032 HD master seeds. Each codex32 string encodes a share or secret with a human-readable prefix (hrp), and a data part consisting of a threshold, identifier, share index, payload, and checksum.
234+
235+
Create a BIP85 DRNG whose seed is the derived entropy. Read 1 byte from the DRNG and trim to the 5 most significant bits to obtain an integer (0–31), representing a bech32 character.
236+
237+
Pseudocode: <code>character_value = int.from_bytes(drng.read(1), "big") >> 3</code>
238+
239+
Repeat until all required data characters are validly chosen.
240+
241+
Example: a codex32 secret with <code>hrp = "ms"</code> (first index), <code>threshold = "0"</code>, <code>n = 1</code>, <code>byte_length = 16</code>, identifier <code>"c0??"</code> would have the path <code>m/83696968'/93'/0'/0'/1'/16'/24'/15'/32'/32'/0'</code>, the next secret would be <code>m/83696968'/93'/0'/0'/1'/16'/24'/15'/32'/32'/1'</code> (identifier <code>"c0zc"</code>) etc.
242+
243+
Human-readable Prefix Table
244+
245+
{|
246+
!hrp
247+
!Code
248+
|-
249+
| "ms"
250+
| 0'
251+
|-
252+
| "cl"
253+
| 1'
254+
|-
255+
|}
256+
257+
Threshold Table
258+
259+
{|
260+
!Threshold
261+
!Code
262+
|-
263+
| "0"
264+
| 0'
265+
|-
266+
| "2"
267+
| 2'
268+
|-
269+
| "3"
270+
| 3'
271+
|-
272+
| "4"
273+
| 4'
274+
|-
275+
| "5"
276+
| 5'
277+
|-
278+
| "6"
279+
| 6'
280+
|-
281+
| "7"
282+
| 7'
283+
|-
284+
| "8"
285+
| 8'
286+
|-
287+
| "9"
288+
| 9'
289+
|-
290+
|}
291+
292+
Share Count Table
293+
294+
{|
295+
!Threshold code
296+
!Number of Shares
297+
!Code
298+
|-
299+
| 0'
300+
| n = 1
301+
| 1'
302+
|-
303+
| not 0'
304+
| n (from 1 to 31)
305+
| n'
306+
|}
307+
308+
Bytes Length Table
309+
310+
{|
311+
! Bytes
312+
! Data Length (Characters)
313+
!Code
314+
|-
315+
| 16
316+
| 45
317+
| 16'
318+
|-
319+
| 32
320+
| 71
321+
| 32'
322+
|-
323+
| 64
324+
| 124
325+
| 64'
326+
|}
327+
Note: Other lengths between 16 and 64 are valid but not recommended, using corresponding hardened indices.
328+
329+
Identifier Table
330+
331+
{|
332+
! Identifier
333+
!Code
334+
|-
335+
| id0, id1, id2, id3
336+
| id0'/id1'/id2'/id3'
337+
|-
338+
| Default (BIP-0032 fingerprint)
339+
| 32'/32'/32'/32'
340+
|}
341+
The identifier is four bech32 characters converted to four integers using the character table from BIP-0173. Each identifier hardened index (idX) used in the derivation path affects the derived entropy; if idX = 32 then the character emitted at that position in the encoded identifier MUST be the bech32 character for the corresponding 5-bit chunk of the 20 most significant bits of the relevant seed's BIP-0032 fingerprint (master seed, else seed recovered at t = n, else share "a" if n = 1).
342+
343+
Rationale: This default assists users in locating the correct codex32 backup for their wallets, should be distinct for hundreds of backups users may need to disambiguate and, as it is widely stored, improves overall error correction.
344+
345+
====Unshared Secret====
346+
347+
When <code>threshold == "0"</code>, <code>n</code> MUST be ''1'' and the output is a codex32 secret. The payload in a codex32 secret is a direct encoding of a BIP-0032 HD master seed.
348+
349+
Examples:
350+
351+
Generate a "ms" prefixed codex32 secret, 16-byte payload, with identifier <code>"c0??"</code>.
352+
353+
INPUT:
354+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
355+
* PATH: m/83696968'/93'/0'/0'/1'/16'/24'/15'/32'/32'/0'
356+
OUTPUT:
357+
* DERIVED ENTROPY=bf89dc8a7caeba703bbba213cd092800c4dd42b3efa55dc50f52f17e4000057e727512c05cdc3856d8def0eaf0d877714e18c1d74364911e8a438bcc0373e8a3
358+
* DERIVED BIP93 identifier=c0ny
359+
* DERIVED BIP93 codex32=ms10c0nys4xklclp0lneyfjmyp9uhlfdzqfwwengqaduatsw
360+
361+
Generate a "cl" prefixed Core Lightning HSM secret, 32-bytes with default identifier.
362+
363+
INPUT:
364+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
365+
* PATH: m/83696968'/93'/1'/0'/1'/32'/32'/32'/32'/32'/0'
366+
OUTPUT:
367+
* DERIVED ENTROPY=d5d81425b6352225c002cc31002e721e93c08dbc742eefbf480d14ca788c544df912ef67f8927b3456a56dd7f6285c7642f17370154524dad3bfe294cb507242
368+
* DERIVED BIP93 identifier=wwak
369+
* DERIVED BIP93 codex32=cl10wwakss63h2vh43mjdk9sjjendkyy2mvt2n6frt83sly7afjh85xl3l9qlp63pyuukcyqyf
370+
371+
====Share Generation====
372+
373+
If we already have a valid set of ''t'' initial codex32 strings, use BIP-0093 to derive ''n'' shares. The BIP85 dice application may be used to randomly select ''n'' share indices.
374+
375+
Otherwise, for each initial share needed:
376+
377+
1. Take the next available letter from the bech32 alphabet, in alphabetical order, as <code>a</code>, <code>c</code>, <code>d</code>, ..., to be the share index.
378+
* Valid share-index characters: "acdefghjklmnpqrtuvwxyz023456789"
379+
2. Generate ceil(''<code>byte_length</code> * 8 / 5'') random payload characters using the BIP85 DRNG.
380+
* Recover secret at "s", if needed, for the default identifier.
381+
3. Prepend the <code>threshold</code> and identifier.
382+
383+
4. Compute and append the codex32 checksum.
384+
385+
5. Translate the data part to characters using the table from BIP-0173 and prepend <code>hrp</code>1.
386+
{|
387+
! Fresh master seeds
388+
!Existing master seeds
389+
|-
390+
| ''n'' >= ''t''
391+
| ''n'' < ''t''
392+
|}
393+
There are two ways to create an initial set of ''t'' valid codex32 strings, depending on whether the user is creating a fresh master seed or using an existing master seed.
394+
The following steps outline the process for each case.
395+
396+
=====For a fresh master seed=====
397+
398+
Generate ''t'' initial random shares as above, then:
399+
* Derive the remaining 31 - ''t'' possible shares by interpolating from these initial ''t'' shares.
400+
* Use the DRNG to deterministically select ''n'' unique indices (excluding "s").
401+
* Output the shares with these indices.
402+
* The secret can be recovered by interpolating any ''t'' shares at index "s".
403+
404+
Examples:
405+
406+
Generate 3 codex32 shares with a threshold of 2 for a 16-byte seed, identifier <code>"c00l"</code>.
407+
408+
INPUT:
409+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
410+
* PATH: m/83696968'/93'/0'/2'/3'/16'/24'/15'/15'/31'/0'
411+
OUTPUT:
412+
* DERIVED ENTROPY=08d7bfdb5bb43e00046af47b31063def05ea70afed5e8c3ab88a80213efe548da0171c8ba30501844ea2cee9e830138306f8a9c429acdba6e1d050b2b50fad3f
413+
* DERIVED BIP93 identifier=c00l
414+
* DERIVED BIP93 codex32=ms12c00ln4kx8hawgstmrky88szf0qc7p9snrryzwl06tay6, ms12c00lpc9sddr6j0kl48m8j7n9sfg4p39ajmq4xx40xwvt, ms12c00lyj8fjetdxqhrvt58zalgllrdpx477puthmplvva8
415+
416+
Generate 9 codex32 shares for a 16-byte seed, threshold 3, default identifier.
417+
418+
INPUT:
419+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
420+
* PATH: m/83696968'/93'/0'/3'/9'/16'/32'/32'/32'/32'/0'
421+
OUTPUT:
422+
* DERIVED ENTROPY= c18b7dd81fb08b55b3cd16070fa625a0436db43186ab5f7d636b58e73decc5539b59ab93d65e932448933637241e17933d97f37c541a3319148a25e8e306cf10
423+
* DERIVED BIP93 identifier=ms8t
424+
* DERIVED BIP93 codex32=ms13ms8tu5dtz5c6d7lfg7l48mmewvhdu0z6q6eav29umjhl, ms13ms8tneyjzext4y7cd0s6c2gwn92smyldywhfrzc2xmhq, ms13ms8tz6nt2nvekkjyqn2lqdszm8pfydmmttfytvg28fcv, ms13ms8tdh6j27jgwvn49z9slur4xwu5rxxv0l8syy4u6qcn, ms13ms8tp85zuyk2ct2msvjjtvwxljg52fza02ln8plkfegf, ms13ms8tcfk9nlh8e6uhaqrxrk9pa8djsquk4xhs4zv87jnv, ms13ms8tenrpvzdmjtxkuputf72p4xy422s8n2dryeva3yk2, ms13ms8tjr3kayuh74yevw0hjz8wmyrhpwnuzzd6jecsfdjx, ms13ms8tf2pum4a46gstsuerm3ad49xt0fcq6rfaavu8lquq
425+
426+
=====For an existing master seed=====
427+
428+
Generate ''n'' = ''t'' - 1 initial random shares as above, then:
429+
* Output these shares with the alphabetized indices.
430+
* The existing master seed is treated as the ''t''-th share (encoded as codex32 secret with index "s").
431+
* To generate additional shares, interpolate using the ''t'' points (''t''-1 generated shares + secret).
432+
433+
Examples:
434+
435+
Generate 2 codex32 shares, 16-byte existing master seed, threshold 3, identifier <code>"g0??"</code>.
436+
437+
Note: The share indices are alphabetized. The default identifier is the fingerprint of payload bytes of "s" had the <code>threshold</code been <code>n</code> (2 in this example).
438+
439+
INPUT:
440+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
441+
* PATH: m/83696968'/93'/0'/3'/2'/16'/8'/15'/32'/32'/0'
442+
OUTPUT:
443+
* DERIVED ENTROPY=c23f717c2d3f124ea5596aa23449ba91a9b189953aaa925f33dfd16f35b6ca86000a1c11e6080f20ae6470019ee8f585a11af483a59b15b2827b5605ad61772b
444+
* DERIVED BIP93 identifier=g0fy
445+
* DERIVED BIP93 codex32=ms13g0fyarrwyawuktl8qptwqy3np7jx3xfv992ytz5kcq8h, ms13g0fyc4e379zymy6tzdhgzwfeq6ymwlr36qext53v2vp4
446+
447+
Generate 1 codex32 share for a 64-byte existing master seed, threshold 2, identifier <code>"?ann"</code>.
448+
449+
Note: Indices will be alphabetical. The default identifier is the fingerprint of payload bytes of share "a".
450+
451+
INPUT:
452+
* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb
453+
* PATH: m/83696968'/93'/0'/2'/1'/64'/32'/29'/19'/19'/0'
454+
OUTPUT:
455+
* DERIVED ENTROPY=bb4fb0e144930d545836177820d173cc250b9084ac50ce3aa6816efaed2dc750cc687b71c9c95a372009427ced155e78622a81defed03321aea49f4d4fdb688b
456+
* DERIVED BIP93 identifier=mann
457+
* DERIVED BIP93 codex32=ms12mannaczq4kkph3gtppqu5ehjes6fvsyh09m0tk3ag5z3tkq5p5menyjpukyy2dvddk4yu979949g08jlfdt4w946we8dynamcu22c0tr6s2rndpnrmqac6z23nd
458+
228459
===HD-Seed WIF===
229460
Application number: 2'
230461
@@ -429,20 +660,27 @@ OUTPUT
429660
430661
This specification is not backwards compatible with any other existing specification.
431662
432-
This specification relies on BIP32 but is agnostic to how the BIP32 root key is derived. As such, this standard is able to derive wallets with initialization schemes like BIP39 or Electrum wallet style mnemonics.
663+
This specification relies on BIP32 but is agnostic to how the BIP32 root key is derived. As such, this standard is able to derive wallets with initialization schemes like BIP39, codex32 or Electrum wallet style mnemonics.
433664
434665
==References==
435666
436-
BIP32, BIP39
667+
BIP32, BIP39, BIP93
437668
438669
==Reference Implementations==
439670
671+
* 1.4.0 Python 3.x library implementation: [https://github.com/benwestgate/bip85]
440672
* 1.3.0 Python 3.x library implementation: [https://github.com/akarve/bipsea]
441673
* 1.1.0 Python 2.x library implementation: [https://github.com/ethankosakovsky/bip85]
442674
* 1.0.0 JavaScript library implementation: [https://github.com/hoganri/bip85-js]
443675
444676
==Changelog==
445677
678+
===1.4.0 (2025-9-01)===
679+
680+
====Added====
681+
682+
* Codex32 application 93'
683+
446684
===1.3.0 (2024-10-22)===
447685
448686
====Added====

0 commit comments

Comments
 (0)