Skip to content

Reduce secp256k1 supply-chain trust in backup/recovery path #3

Description

@BenWestgate

Problem

On reviewability-v1, the documented CLI install path is substantially hardened: bip32 is pinned to a specific Git commit and hash, and coincurve==21.0.0 is installed with --require-hashes. That protects users who follow the reviewed installation procedure from silently receiving a later malicious upstream release.

However, the runtime/package architecture still has a concentrated trust point:

codex32bip32coincurve → libsecp256k1

src/codex32/profiles/ms32.py imports bip32.BIP32, and _bip32_node() calls BIP32.from_seed(). The security model explicitly treats BIP32 and Coincurve as trusted cryptographic dependencies.

There are two related concerns:

  1. A normal package installation resolves the declared metadata ranges (bip32>=5,<6, with bip32 allowing a Coincurve range) rather than the repository's hash-pinned lockfiles. A malicious future version inside those ranges could therefore enter an environment without any change to codex32 source.
  2. Coincurve is native code loaded into the same Python process that handles master seeds. A malicious native dependency is not limited to returning incorrect EC results; it can inspect process memory or otherwise violate the process boundary.

The hash-pinned install procedure mitigates the first concern for the prescribed CLI installation, but it does not remove the architectural trust chokepoint.

Proposed direction

Make the codex32 backup/recovery core independent of secp256k1-native dependencies, and move wallet derivation / descriptor functionality behind an explicit wallet-integration boundary.

In particular, BIP32 root validity does not require public-key point multiplication. Root validation can be implemented using stdlib primitives:

  • HMAC-SHA512 with key Bitcoin seed;
  • parse IL as an integer;
  • reject IL == 0 or IL >= n.

That would allow creation, parsing, sharing, recovery, correction, and validation of master-seed backups without importing Coincurve at all.

Wallet-specific operations that need fingerprints, xpubs, or descriptors could continue to use a secp256k1 implementation, but only when the user explicitly invokes that functionality.

Desired security property

A user should be able to create, verify, split, recover, and correct a codex32 master-seed backup without loading third-party native cryptographic code into the secret-handling process.

The remaining secp256k1 trust boundary should be limited to wallet interoperability/derivation, where it is actually required.

Possible implementation shape

  • Replace the current BIP32 dependency in master-seed validity checks with a small internal stdlib-only root validator.
  • Avoid importing bip32/coincurve from modules needed by backup/recovery operations.
  • Move BIP32/xpub/fingerprint/descriptor code into the wallet integration layer or an optional dependency path.
  • Add a test asserting that core backup/recovery operations work in an environment with no bip32 or coincurve installed.
  • Keep the existing hash-pinned installation path for wallet-enabled CLI use.

This would improve both reviewability and resistance to a maintainer/package-registry compromise without requiring codex32 to reimplement general secp256k1 arithmetic.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions