Conversation
- Add exemption for chacha20 0.10.2 (published via trusted publishing, so no publisher identity exists for trust entries to cover) - Refresh imports.lock: rustls 0.23.45 / rustls-webpki 0.103.15 publisher records and upstream vendor audit updates
- dns-server: migrate hickory-client/server 0.24 -> hickory-proto/server 0.26.3. hickory-client no longer exists in the 0.26 family, its types moved to hickory-proto; the Authority trait was replaced by ZoneHandler (fixes RUSTSEC-2026-0119, Dependabot #62) - utils: replace the abandoned probabilistic-collections crate (last release 2020) with an in-house bloom filter implementation, removing the vulnerable rand 0.7 from the dependency tree (fixes RUSTSEC-2026-0097, Dependabot #54) - node-gui: consume a patched iced_glyphon fork with lru upgraded to 0.16.3 via [patch.crates-io] (fixes RUSTSEC-2026-0002, Dependabot #44); no upstream iced release carries the fix yet
- Propagate the hickory server termination error instead of logging it - Document that dynamic DNS updates stay rejected (ZoneHandler default) - Remove the per-insert allocation in the bloom filter hot path - Import TSigResponseContext instead of an inline path - Refresh imports.lock and prune 7 exemptions that vendor audits now cover
- Reword the bloom filter FPP guarantee (approximately, not at most) - Fix the misleading 'round down' comment (round() rounds to nearest) - Make the dynamic DNS update comment accurate (NotImplemented is a stricter rejection than the old indirect rejection) - Restore alphabetical ordering of utils dependencies
Add an optional BIP39 passphrase parameter (Option<String>, optional in JS) used when converting the mnemonic to a seed (salt = "mnemonic" + passphrase, PBKDF2-HMAC-SHA512, 2048 iterations via the bip39 crate). Passing None / undefined / null / "" preserves the legacy behavior byte-for-byte; the passphrase and derived seed are wrapped in Zeroizing on the Rust side. Also bumps the workspace (and npm package) version to 1.5.0 with changelog, README and generated WASM-API.md updates, regression tests pinning the pre-change output (empty passphrase, mainnet/testnet, receiving addresses 0/1), official Trezor BIP39 vectors, non-ASCII normalization vectors, a wasm-vs-Core key-chain parity test, and JS bindings tests.
- Remove the accidentally committed local wrangler cache and ignore .wrangler/ - Disable default features of the wallet dev-dependency (avoids pulling the trezor/ledger device stacks into the wasm-wrappers test build) - Best-effort wording for the zeroization comment - Strict equality in the JS bindings test - Pin non-ASCII BIP39 passphrase normalization (NFKD) with vectors verified by an independent implementation
erubboli
force-pushed
the
feat/wasm-bip39-passphrase
branch
from
September 15, 2026 07:00
8a8b2f6 to
b85035d
Compare
The workspace/npm version upgrade to 1.5.0 will be coordinated separately in a dedicated release PR; this change keeps the passphrase feature version-neutral. Reverts Cargo.toml, Cargo.lock, the regenerated RPC docs, and moves the changelog entry back under [Unreleased].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the Mojito mobile wallet blocker (High, CWE-325): the wasm API had no way to pass a BIP39 passphrase to key derivation.
Stacked on #2112 (supply-chain/lockfile context needed for cargo-deny/vet).
API shape
Chose the single-entry-point form over a new export:
MasterKeyChain::mnemonic_to_root_key(mnemonic, Option<&str>)signaturepassphrase?: string | nullin the generated TS bindings — an optional third argument, so all existing 2-argument JS callers keep working unchangedSemantics
seed = PBKDF2-HMAC-SHA512(mnemonic, salt = "mnemonic" + passphrase, 2048 iterations, 64 bytes)viabip39'sto_seed(which performs the required NFKD normalization) — same call pattern as Core desktop (to_seed(passphrase.unwrap_or(""))).None/undefined/null/""are all byte-identical to the old behavior. Passphrase and seed are wrapped inZeroizing(best-effort; see comment in code).Backward compatibility (regression-tested)
Pinned vectors captured from the pre-change implementation and asserted in
legacy_derivations_unchanged: empty-passphrase derivations on mainnet and testnet, plus receiving keys at index 0 and 1 for both networks. The existing JSpredefined_address_test(2-argument call, pinned address) continues to pass unchanged.Tests
bip39_trezor_test_vectors— 5 official BIP39 Trezor vectors ("TREZOR" passphrase), cross-checked against an independent PBKDF2 implementationnon_ascii_passphrase_normalization— NFKD normalization pinned with independently computed vectors (non-ASCII/Unicode-separator passphrases), the interop concern for arbitrary JS stringsdifferent_passphrases_produce_different_keys— same mnemonic, different passphrases → different extended keys and different receiving addresseswasm_matches_core_key_chain— acceptance gate:MasterKeyChain::mnemonic_to_root_key(Core desktop key-management) and the wasm export derive identical account keys and identical addresses for the same mnemonic + passphraseCall-path audit (requirement 5)
make_receiving_address/make_change_address/make_receiving_address_public_key/make_change_address_public_key: consume the already-extended account key — no change needed ✅encode_witness/sign_message_for_spending: consume raw private keys derived downstream — no mnemonic involved ✅sign_challenge/verify_challenge: consume a private key / address, no mnemonic ✅wallet'sMasterKeyChain::mnemonic_to_root_key, which already takes the passphrase (and is the interop reference for this PR) ✅Versioning
This PR is version-neutral (no workspace/npm version change); the changelog entry lives under
[Unreleased]. The version upgrade to 1.5.0 will be coordinated separately in a dedicated release PR. README documents the new parameter; generatedWASM-API.mdandwasm_wrappers.d.tsupdated (passphrase?: string | null).Compatibility note
Affected wallets: only wallets created from a mnemonic with a user passphrase (currently impossible via wasm — that's the bug). Legacy wallets (no passphrase) must keep deriving with
None/undefined; mixing them up produces different keys. Migration for the mobile wallet: re-vendor the wasm package; for new wallets pass the user's passphrase; for existing (legacy) wallets pass nothing.Verification
./do_checks.shgreen locally under the CI toolchain (1.92.0): fmt, cargo-deny, cargo-vet, clippy (all targets), codecheck, wasm-doc checkcargo test --workspace(all 202 test binaries) green locally — includes the node-daemon / wallet-rpc-daemon RPC doc expect-testscargo test -p wasm-wrappers: 7/7 pass; full JS bindings suite via wasm-pack build + node: all pass