Skip to content

Codex32 (BIP93) BIP85 Application reference implementation - #68

Open
BenWestgate wants to merge 1 commit into
akarve:mainfrom
BenWestgate:patch-1
Open

BenWestgate wants to merge 1 commit into
akarve:mainfrom
BenWestgate:patch-1

Conversation

@BenWestgate

@BenWestgate BenWestgate commented Aug 19, 2025

Copy link
Copy Markdown

Closes #67

Deterministically generates codex32 share sets from entropy using the BIP85-DRNG instead of physical dice rolls.

The BIP85 pull request diff (also draft) can be viewed here:
bitcoin/bips@master...BenWestgate:bips:codex32

@BenWestgate
BenWestgate marked this pull request as draft August 19, 2025 19:59
@BenWestgate BenWestgate closed this Sep 2, 2025
@akarve

akarve commented Sep 2, 2025

Copy link
Copy Markdown
Owner

@BenWestgate howdy i didn't see this until now. contributions are welcome. mentioning this because it's now closed and i was not sure if you closed because it wasn't reviewed? in any case, that was not a silent no.

@BenWestgate

BenWestgate commented Sep 2, 2025

Copy link
Copy Markdown
Author

@akarve I closed this because I ended up forking ethankosakovsky/bip85@master...BenWestgate:bip85:master to create a reference implementation of #67 so merging this is no longer necessary. It should save you a few minutes updating bipsea by reopening this if it appears likely bip85 application 93' (codex32) will merge to bips/master

@akarve

akarve commented Sep 2, 2025

Copy link
Copy Markdown
Owner

@BenWestgate copy. idk if ethan will ever review your PR tho as we were unable to get a hold of him for recent BIP-85 changes. in any case i'm open to a new app (still grokking details though). did you look at and/or consider the dice application? it can generate passwords of any length over any character set (e.g. bech32)?

@BenWestgate

BenWestgate commented Sep 3, 2025

Copy link
Copy Markdown
Author

@akarve I don't expect ethan to ever review ethankosakovsky/bip85@master...BenWestgate:bip85:master, in the BIP-0085 text PR I linked to benwestgate/bip85 as the v1.4.0 reference.

Yes, I did consider using the dice application. However that could have lead to some differences between implementations. Also we need derivation path indexing to make sure the DRNG is seeded with a unique entropy when the identifier, threshold, n, bitlength or hrp parameters change. Using dice application would mean having to store which index' indices were already used, rather feeding the entire header and payload length to the derivation path. This would be a huge security flaw if you generated two child backups that were the same unintentionally.

And also a codex32 secret is analogous to bip39 mnemonic. Same objective: so if both are BIPs they both belong in BIP85 it seems.

@BenWestgate

This comment was marked as outdated.

@akarve

akarve commented Sep 13, 2025

Copy link
Copy Markdown
Owner

@BenWestgate

So what would help me most is you adapt the cli to accept more parameters

easiest thing to do is probably take raw paths (arbitrary length and structure) with a new escape hatch cli switch. it'll be a while before i can get to this; lots to do at day job :/

Regarding path simplification:

no need to retrofit the spec to the CLI. i just want to make sure that we have exactly as many segments as needed and no more? if it's already at a minimum, yolo.

i had some comments on byte draws and unpacking as well, wdyt?

Drawing and truncating a single byte per character is certainly clear to understand but I keep wondering > if implementers shouldn't draw ((chars * 5) // 8) bytes in one shot? These bytes aren't expensive or
anything but it's less iterations, less total reads, etc. If my suggestion becomes hard to read or write
then feel free to keep as is.

@BenWestgate

BenWestgate commented Sep 14, 2025

Copy link
Copy Markdown
Author

just want to make sure that we have exactly as many segments as needed and no more? if it's already at a minimum, yolo.

The only segment that could be dropped is the identifier:

  1. It SHOULD be unique across different seeds like the bip85 {index} and we could encode the bip85 index to 4 bech32 characters and use it as the identifier. Then default to a fingerprint as identifier after index 32^4.
  2. Doesn't require 4 paths to encode 20 bits, a single path can do.

My other consolidation was to combine threshold, n and byte_length into a single path segment, by concatenating them as decimals. I don't see the downside of this versus separate path depths for each.

Give me your thoughts on encoding the bip85 index into the codex32 identifier.

It's 4 characters intended to disambiguate different backups. You want them to all have unique identifiers, so an identifier in the derivation path seems to enable risky behavior (different backups with the same identifier) when the bip85 index is incremented.

My original idea dropped the index for this reason but that breaks bip85 conventions.

i had some comments on byte draws and unpacking as well, wdyt?

I prefer your suggestion to draw threshold * byte_length bytes in one shot, because then our initial t byte strings can be padded to a multiple of 5 bits with a CRC for more error detection.

@akarve

akarve commented Oct 6, 2025

Copy link
Copy Markdown
Owner

@BenWestgate howdy i didn't forget about this and hoping to get to it later this quarter

@BenWestgate

Copy link
Copy Markdown
Author

@akarve I haven't forgotten about it either. I will adapt your feedback into a bipsea pull request this month.

@BenWestgate

Copy link
Copy Markdown
Author

I got a start on it, added a codex32 application

ben@zenbook15:~/Documents/GitHub/bipsea$ poetry run bipsea codex32 --help
Usage: bipsea codex32 [OPTIONS]

  Generate a BIP-93 codex32 backup from `secrets.randbits`.

Options:
  -h, --hrp TEXT                  Codex32 human-readable prefix.
  -l, --length INTEGER RANGE      Number of secret bytes.  [16<=x<=64]
  -t, --threshold INTEGER RANGE   Number of shares required to reconstruct the
                                  secret.  [0<=x<=9]
  -n, --num-shares INTEGER RANGE  Total number of shares to generate.
                                  [1<=x<=31]
  -i, --identifier TEXT           Optional identifier to include in each
                                  share.
  -p, --indices TEXT              String of unique characters to use as share
                                  indices.
  --pretty / --not-pretty         Print a number before, and a newline after,
                                  each codex32 share.
  --help                          Show this message and exit.
image

While this grabs from /dev/urandom and not bip85 entropy it's directly applying the byte_length bytes rather than drawing characters. Most of it will be reused when I do the bip85 app.

@akarve

akarve commented Oct 6, 2025

Copy link
Copy Markdown
Owner

one thing to consider especially if it makes your life easier: what about just implementing:

bipsea apply -a arbitrary -p "what/ever/derivation/path/the/user/wants"

i mention this because 1-2 other new applications are in PR now and i plan to implement the same (but you are welcome to tackle it) because it basically makes all future apps just work. and then we don't need to even touch the reference app for most cases.

i have not thought carefully about other params and switches per application so there might be more to plan here. we could possibly soft warn if it's not a recognized application code.

@akarve

akarve commented Oct 6, 2025

Copy link
Copy Markdown
Owner

there might be more to plan here

maybe we need a python protocol or something and then new implementations just have their own path handlers under arbitrary? and they could even register proper apps if they want to. just thinking out loud, do whatever is best for codex32.

@BenWestgate

BenWestgate commented Oct 7, 2025

Copy link
Copy Markdown
Author

one thing to consider especially if it makes your life easier: what about just implementing:

bipsea apply -a arbitrary -p "what/ever/derivation/path/the/user/wants"
...and then we don't need to even touch the reference app for most cases.

That sounds nice for bipsea maintenance but the point of applications is they standardize how the derived is encoded.

The derivation itself is not useful, any BIP32 library will provide that.

@BenWestgate

BenWestgate commented Oct 7, 2025

Copy link
Copy Markdown
Author

do whatever is best for codex32.

I published a codex32 project on PyPI so Bipsea can import it for the proposed bip85 application 93'.

@BenWestgate

This comment was marked as outdated.

@akarve

akarve commented Oct 14, 2025

Copy link
Copy Markdown
Owner

haven't looked at this yet what i'm hoping to do is create some kind of python protocol for apps and you just register callbacks. it might be easier if yours is just a PyPI package that bipsea depends on but I haven't thought about that yet. the protocol would then call into your module.

more importantly did you see these comments on your PR? that's a more fundamental bridge for us to cross first.

Comment thread src/bipsea/bip93.py Outdated
@BenWestgate

This comment was marked as outdated.

Comment thread src/bipsea/bip85.py Outdated
@BenWestgate

This comment was marked as outdated.

@akarve

akarve commented Apr 4, 2026

Copy link
Copy Markdown
Owner

App protocol is live, I will also comment on GH on your BIP PR:
https://github.com/akarve/bipsea/blob/main/src/bipsea/apps/README.md

@BenWestgate
BenWestgate marked this pull request as ready for review August 21, 2026 14:12
@BenWestgate
BenWestgate requested a review from akarve August 22, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Add Codex32 (BIP93) as a BIP85 Application

2 participants