Skip to content

fix(key-wallet): zeroize ExtendedBLSPrivKey and ExtendedEd25519PrivKey on drop#859

Merged
QuantumExplorer merged 1 commit into
devfrom
fix/zeroize-bls-ed25519-xpriv
Jul 10, 2026
Merged

fix(key-wallet): zeroize ExtendedBLSPrivKey and ExtendedEd25519PrivKey on drop#859
QuantumExplorer merged 1 commit into
devfrom
fix/zeroize-bls-ed25519-xpriv

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

Fixes #858

Problem

ExtendedBLSPrivKey (key-wallet/src/derivation_bls_bip32.rs) and ExtendedEd25519PrivKey (key-wallet/src/derivation_slip10.rs) hold raw secret key material but had no Zeroize/Drop implementations, so their secret bytes were left behind in freed heap memory when dropped. Their secp256k1 siblings (ExtendedPrivKey, RootExtendedPrivKey) already zeroize on drop, so intermediate BLS operator / Ed25519 platform-node keys created during path derivation were the odd ones out.

Changes

  • ExtendedBLSPrivKey: hand-written Zeroize (wipes the inner scalar via its public field — blstrs_plus::Scalar implements DefaultIsZeroes, and blsful's SecretKey itself has no Zeroize impl — plus the chain code and derivation metadata) and a Drop impl calling it, mirroring ExtendedPrivKey in bip32.rs.
  • ExtendedEd25519PrivKey: same pattern — Zeroize wiping the [u8; 32] secret, chain code, and metadata, plus Drop.
  • Fingerprint: added a Zeroize impl in bip32.rs (its inner field is private outside that module) so the new impls can wipe derivation metadata the same way the secp256k1 types do.
  • Constant-time Eq for ExtendedEd25519PrivKey (secondary issue from the report): the derived PartialEq short-circuited byte-by-byte over the raw secret; replaced with a constant-time fold over the secret bytes (metadata still compared normally).

No caller changes needed: all existing field accesses are borrows or Copy-field reads, so adding Drop breaks no moves.

Testing

  • New tests: test_zeroize_clears_key_material in both modules, and test_partial_eq_matches_field_equality for the hand-written Eq.
  • cargo test -p key-wallet --all-features: 524 passed; the only failures are pre-existing wall-clock performance tests that also fail (worse) on unmodified dev on this machine.
  • cargo clippy -p key-wallet --all-features --all-targets and cargo fmt --check: clean.
  • cargo check -p key-wallet-ffi -p dash-spv --all-features: clean.

🤖 Generated with Claude Code

…y on drop

The BLS and Ed25519 extended private key types held raw secret material
but had no Zeroize/Drop implementations, so their secret bytes were left
in freed heap memory when dropped. Their secp256k1 siblings
(ExtendedPrivKey, RootExtendedPrivKey) already wipe themselves on drop.

Mirror the secp256k1 pattern for both types: a hand-written Zeroize that
wipes the secret key, chain code, and derivation metadata, plus a Drop
impl that calls it. Add a Zeroize impl for Fingerprint so modules outside
bip32 can wipe it too.

Also replace the derived PartialEq on ExtendedEd25519PrivKey, which
short-circuited over the raw 32-byte secret, with a constant-time
comparison of the secret bytes.

Fixes #858

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e4b0c25c-e800-4a59-8ef8-63e4c48b5549

📥 Commits

Reviewing files that changed from the base of the PR and between 1860089 and 7826a14.

📒 Files selected for processing (3)
  • key-wallet/src/bip32.rs
  • key-wallet/src/derivation_bls_bip32.rs
  • key-wallet/src/derivation_slip10.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/zeroize-bls-ed25519-xpriv

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.66%. Comparing base (1860089) to head (7826a14).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #859      +/-   ##
==========================================
+ Coverage   73.62%   73.66%   +0.03%     
==========================================
  Files         324      324              
  Lines       73195    73268      +73     
==========================================
+ Hits        53888    53970      +82     
+ Misses      19307    19298       -9     
Flag Coverage Δ
core 77.08% <ø> (ø)
ffi 46.07% <ø> (-0.02%) ⬇️
rpc 20.00% <ø> (ø)
spv 91.13% <ø> (+0.05%) ⬆️
wallet 73.15% <100.00%> (+0.09%) ⬆️
Files with missing lines Coverage Δ
key-wallet/src/bip32.rs 80.74% <100.00%> (+0.03%) ⬆️
key-wallet/src/derivation_bls_bip32.rs 92.87% <100.00%> (+0.24%) ⬆️
key-wallet/src/derivation_slip10.rs 51.06% <100.00%> (+6.00%) ⬆️

... and 5 files with indirect coverage changes

@QuantumExplorer
QuantumExplorer merged commit 66f0873 into dev Jul 10, 2026
35 checks passed
@QuantumExplorer
QuantumExplorer deleted the fix/zeroize-bls-ed25519-xpriv branch July 10, 2026 11:53
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.

key-wallet: ExtendedBLSPrivKey and ExtendedEd25519PrivKey are not zeroized on drop

2 participants