Skip to content

Support BIP48 multisig derivation paths for message signing#874

Open
AusDavo wants to merge 2 commits into
SeedSigner:devfrom
AusDavo:feature/bip48-multisig-message-signing
Open

Support BIP48 multisig derivation paths for message signing#874
AusDavo wants to merge 2 commits into
SeedSigner:devfrom
AusDavo:feature/bip48-multisig-message-signing

Conversation

@AusDavo
Copy link
Copy Markdown

@AusDavo AusDavo commented Feb 9, 2026

Summary

  • Removes the raise Exception("Not implemented") block for m/48' paths in parse_derivation_path()
  • Adds BIP48 path parsing: reads the script type from the 4th derivation level (1h = nested segwit, 2h = native segwit)
  • The underlying sign_message() function already supports any derivation path — this was purely a parser restriction

Context

Message signing currently only works for single-sig derivation paths (m/44', m/49', m/84', m/86'). Attempting to sign with a multisig path like m/48'/0'/0'/2'/0/0 raises "Not implemented" from parse_derivation_path().

This is needed for key ownership and control verification in multisig setups — e.g. proving to an auditor that you control a specific cosigner key in a multisig wallet, without needing to construct a transaction.

The address displayed on the SeedSigner confirmation screen will be the individual cosigner's single-key address (not the full multisig address, which would require all cosigner xpubs). This is sufficient for verification — the auditor can independently confirm the signing public key matches an xpub in the multisig wallet descriptor.

Tested on a Pi Zero W with a custom build, signing at m/48'/0'/0'/2'/0/0 and verifying the signature externally.

Fixes #519

Test plan

  • Sign a message with m/48'/0'/0'/2'/0/0 (native segwit multisig) — should succeed
  • Sign a message with m/48'/0'/0'/1'/0/0 (nested segwit multisig) — should succeed
  • Sign a message with m/84'/0'/0'/0/0 (single-sig) — should still work as before
  • Verify signatures externally match the expected public key at the derivation path

parse_derivation_path() previously raised "Not implemented" for m/48'
paths, blocking message signing for multisig keys. The underlying
sign_message() function already works with any derivation path — the
restriction was only in the path parser.

This extends parse_derivation_path() to handle BIP48 multisig paths
by mapping the script type index at the 4th level (1h = nested segwit,
2h = native segwit) to the correct SettingsConstants value.

The address shown during signing confirmation is the individual
cosigner's single-key address, which is sufficient for key ownership
verification.

Fixes SeedSigner#519
@AusDavo
Copy link
Copy Markdown
Author

AusDavo commented Feb 12, 2026

@newtonick @kdmukai — this is a small change that unblocks message signing for multisig derivation paths (fixes #519). Happy to address any feedback.

@mineracks
Copy link
Copy Markdown

Wow - well done @AusDavo - this is an awesome enhancement - would really elevate some of the custody services we provide via the SeedSigner platform if something like this could get merged.

@mineracks
Copy link
Copy Markdown

Screenshot 2026-02-12 at 6 32 24 pm

@kdmukai
Copy link
Copy Markdown
Contributor

kdmukai commented Feb 12, 2026

newtonick kdmukai — this is a small change that unblocks message signing for multisig derivation paths (fixes #519). Happy to address any feedback.

This is a project run by volunteers who are contributing in their free time. By creating a PR you are inherently asking for contributors' attention. We see there's an open PR. Obviously we already know it wants eyeballs. But if you look at the dates of other PRs, you'll see that PR review is almost always a very slow process (see my own PR #747, for example).

So I consider it rude to directly "@" reference any of us just to call for our attention. Notice that your "@" message adds nothing that is not already stated in the PR description. Reserve "@" call outs for when there are specific questions that the targeted person is the best resource and the discussion may be stalled until they weigh in.

If this sounds harsh, well, understand that I am fiercely protective of our volunteers' time. If you had just tagged me, I would have been mildly annoyed. But tagging Nick or anyone else in this way simply because of impatience aggravates me.

Setting this all aside, more specific / constructive comments will follow.

@kdmukai
Copy link
Copy Markdown
Contributor

kdmukai commented Feb 12, 2026

Any new feature or altered behavior needs new tests. In the PR description you list a series of tests. These should be written into actual test cases and included in this PR.

Since those tests are still yet to be included, this PR should be in the DRAFT state. DRAFT signals that it is not yet ready for review. This is an act of courtesy so that others will not spend time reviewing a PR that is not yet complete.

This PR would also ideally include a new FlowTest that steps through the procedure to ensure that the screen-to-screen sequencing behaves as expected.

@kdmukai
Copy link
Copy Markdown
Contributor

kdmukai commented Feb 12, 2026

It would help to list some of the services that use this sort of verification. I have not encountered this approach to verification for a multisig key, but I have not kept up with all the services out there. I'm only familiar with Unchained which just verifies via a wallet export json format (or direct usb hww connection) that is just checking for, I believe, an xpub match.

@AusDavo
Copy link
Copy Markdown
Author

AusDavo commented Feb 12, 2026

Thanks for the feedback, and apologies for the unnecessary @-mentions — I understand, and I'll keep that in mind going forward.
I'll convert this to DRAFT and add proper test cases including a FlowTest. Will push those updates soon.
On the use case question, the FOSS offering, Gatekeeper, has been around for two years and uses message signing to validate that key holders are still able to sign. A newer service based on this, CertainKey, produces third party reports for retirement account holders to validate ownership and control and satisfy audit requirements.

@AusDavo AusDavo marked this pull request as draft February 12, 2026 21:08
Unit tests: 13 BIP48 vectors for parse_derivation_path() covering native
segwit (2h), nested segwit (1h), and unrecognised script type fallback
across mainnet/testnet/regtest with change flag variations.

FlowTest: end-to-end message signing flow for both BIP48 native segwit
and nested segwit derivation paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AusDavo
Copy link
Copy Markdown
Author

AusDavo commented Feb 13, 2026

Thanks for the guidance on test expectations — really helpful for getting up to speed with the project's standards.

Tests added in f5ca0a3:

  • 13 unit test vectors for parse_derivation_path() covering BIP48 native segwit (2h), nested segwit (1h), and unrecognised script type fallback across mainnet/testnet/regtest
  • FlowTest (test_sign_message_bip48_multisig_flow) stepping through the full message signing flow for both BIP48 script types

@AusDavo AusDavo marked this pull request as ready for review February 13, 2026 00:00
@brendio
Copy link
Copy Markdown

brendio commented Feb 13, 2026

Thanks for the feedback, and apologies for the unnecessary @-mentions — I understand, and I'll keep that in mind going forward. I'll convert this to DRAFT and add proper test cases including a FlowTest. Will push those updates soon. On the use case question, the FOSS offering, Gatekeeper, has been around for two years and uses message signing to validate that key holders are still able to sign. A newer service based on this, CertainKey, produces third party reports for retirement account holders to validate ownership and control and satisfy audit requirements.

I'll add weight to the use case. I was asked by an auditor to prove ownership and control of a fund's bitcoin holdings. The suggested mechanism was signing a message with the associated keys. This is not possible by default with a multisig wallet structure. I built an image with AusDavo's patch as was able to use it to sign the challenge by the CertainKey service and they were able to provide a report for my auditor. (I was previously getting a System Error: embit_utils.py, 130, in parse_derivation_path Not implemented"; this patch fixes that error)

Stories in discussion groups here are pointing to more auditors now demanding cryptographic proof of control.

@mineracks
Copy link
Copy Markdown

Just adding some context from our side as a custody services provider in Australia using the combination of SeedSigner, SeedHammer and SeedSleeve in real-world multisig deployments for SMSF (the Australian equivalent of a pension fund or retirement savings account).

Fully appreciate that this is a volunteer-run project and that review bandwidth is limited - that's why every SeedSigner we get made and sell sees a portion of our revenue sent as a donation to the project.

Not trying to rush anything here, just explaining why this truly matters now operationally.

At mineracks, we help clients take and maintain secure physical possession of their keys. Most of those setups are BIP48 native segwit multisig. Increasingly, auditors and fund administrators are requiring cryptographic proof of control — i.e., signing a challenge message — rather than relying solely on wallet exports or screenshots that have historically been sufficient.

In singlesig that’s easy. In multisig, it’s awkward unless the device supports signing at the BIP48 derivation path. That parser restriction has been one of the few friction points when deploying SeedSigner in structured custody environments.

From our perspective, what’s nice about this PR is that it doesn’t introduce new signing behavior — it just removes a path restriction. The device still signs with the derived single-key path, and verification can be done independently by matching the pubkey to the descriptor xpub. That aligns well with how cosigner verification already works.

We’re seeing a broader trend of auditors explicitly asking for cryptographic challenge signatures to demonstrate continued key control. Having parity between singlesig and multisig derivations makes SeedSigner much easier to use in those contexts.

The alternative more auditors are offering is to insecurely share xpubs and blockchain addresses that then significantly impact on safety and security for key holders.

Appreciate the thoughtful review process and the emphasis on proper tests and flow coverage — that rigor is exactly why we’re comfortable using and recommending SeedSigner in custody settings where it really counts.

@kdmukai
Copy link
Copy Markdown
Contributor

kdmukai commented Feb 13, 2026

Thank you to everyone above for understanding my reaction, adding the tests, and providing the fuller real-world context.

I have not yet reviewed the changes but I'm onboard with a basic concept ACK.

And since I have no privileges in our repo, here I will invoke necessary "@" mentions: @newtonick or @SeedSigner can you approve the workflow to run the CI tests on this PR?

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

Labels

None yet

Projects

Status: 0.9.0 Needs Code Review

Development

Successfully merging this pull request may close these issues.

Message signing from keys at custom derivation paths

5 participants