Bitcoin Development Mailinglist
 help / color / mirror / Atom feed
From: Sergei Semenov <mrssv2022@gmail.com>
To: Bitcoin Development Mailing List <bitcoindev@googlegroups.com>
Subject: [bitcoindev] MHFE: memory-hard encryption of BIP39 backups into 24 words — request for review
Date: Thu, 1 Oct 2026 09:46:00 -0700 (PDT)	[thread overview]
Message-ID: <7917c5ea-82f2-4ce5-a5e4-b7415cca7441n@googlegroups.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 5622 bytes --]



Hi everyone,

I’m sharing *MHFE (Memory-Hard Feistel Encryption)*, an experimental 
specification for encrypting an existing English BIP39 mnemonic with a 
password into another checksum-valid, 24-word BIP39 mnemonic—the *container*
.

It is designed for *offline cold-storage backups*, particularly existing 
metal plates and capsules. Recovery restores the exact original phrase: no 
funds move, and the wallet remains unchanged. An existing BIP39 passphrase 
stays separate and is applied after recovery as before.

   - Specification, design analysis and test vectors 
   <https://github.com/hobby-eng/mhfe-spec>
   - Reference implementation: Rust library, CLI and WebAssembly 
   <https://github.com/hobby-eng/mhfe>

A reference implementation is available as a Rust library, CLI and 
WebAssembly package, alongside public test vectors and an independent 
OpenSSL-based verification script. An offline HTML interface is also 
available in the MHFE tab of Wallet Deriver, maintained in my separate 
Multi-Chain Wallet Tools repository on Github.

One aspect I find particularly elegant is how the construction uses the 
space left by shorter mnemonics. Their entropy occupies less than the 
container’s 256-bit state. MHFE fills the remaining space with a recovery 
verifier derived from SHA-256. Its leading bits are exactly the original 
BIP39 checksum; the rest extend that same digest:
Original mnemonic -> source entropy + recovery verifier:

12 words -> 128 bits + 128 bits
15 words -> 160 bits +  96 bits
18 words -> 192 bits +  64 bits
21 words -> 224 bits +  32 bits
24 words -> 256 bits + no recovery verifier

The entire state is then encrypted and encoded as 24 BIP39 words with the 
container’s own checksum. *The recovery check therefore requires no 
additional backup words.* This verifier is distinct from a BIP32 wallet 
fingerprint.

For someone creating a new wallet, this provides an explicit choice: *a 
shorter original with an internal recovery check, or a 24-word original 
with all 256 bits devoted to entropy and no internal password confirmation.* 
For an existing wallet, its original length determines the layout. Verifier 
matches can occur by chance and do not authenticate the container or 
establish wallet identity; a trusted receiving address can check the 
recovered wallet for either layout.

There is also *plausible deniability through prepared decoy wallets*. The 
container itself opens as an ordinary BIP39 wallet. Additionally, 
decrypting it with a different password and selecting 24 words produces 
another valid mnemonic; the permutation under that password maps it back to 
the same container. That alternative wallet can be funded and used 
beforehand, allowing a working disclosure even when MHFE use is known.

The supplement 
<https://github.com/hobby-eng/mhfe-spec/blob/main/docs/DESIGN-NOTES.md#deniability> 
includes formal experiments and proofs for this deniability claim within 
its stated model, including an adversary-advantage bound in the 
random-oracle model. These depend on assumptions about password selection, 
wallet history and external evidence. In particular, knowing that the real 
original was shorter than 24 words defeats this alternative disclosure. The 
proof has not received independent expert review and does not guarantee 
that a coercer will believe the response or stop.

The construction uses a *12-round balanced Feistel permutation*. Each round 
performs Argon2id with a state-derived salt. Defaults are *2 GiB, 12 passes 
and four lanes per call*, with twelve sequential calls reusing memory. 
Recovery takes roughly one to two minutes on the reference 
laptop—deliberately expensive for an operation performed rarely. A strong, 
independently generated password remains essential.

The salts aim to prevent reuse of expensive password computations across 
independently generated source phrases. The analysis discusses SLIP-0039 
and other related constructions, and documents an eleven-call password 
filter when both source and container are known. Claims about the cheapest 
attacks remain conjectures.

The fixed-size format has costs: it is deterministic, unauthenticated, and 
carries no salt, version or settings fields. Long-term recovery therefore 
needs compatible software and knowledge of any non-default settings. 
Entering the container directly into a normal wallet opens an unrelated 
wallet; MHFE recovery must come first.

I would especially welcome feedback on:

   - *Cryptanalysis:* cheaper password filters, amortized attacks or 
   overlooked related constructions.
   - *Deniability:* weaknesses or missing assumptions in the formal model.
   - *Recovery and interoperability:* whether preserving exactly 24 backup 
   words justifies the tradeoffs, and what wallet developers would need 
   clarified.

The specification was developed with substantial ChatGPT and Claude 
assistance, as disclosed in the document. It remains experimental and has 
not received independent expert cryptographic review.

I would appreciate any technical feedback.  Thank you for your time. 

Best regards, 

Sergei Semenov

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/7917c5ea-82f2-4ce5-a5e4-b7415cca7441n%40googlegroups.com.

[-- Attachment #1.2: Type: text/html, Size: 6123 bytes --]

                 reply	other threads:[~2026-10-01 17:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7917c5ea-82f2-4ce5-a5e4-b7415cca7441n@googlegroups.com \
    --to=mrssv2022@gmail.com \
    --cc=bitcoindev@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox