Introduction
Each DID method needs a way to sign and verify data: DID document updates, Verifiable Credentials, and authentication challenges. As of September 2026, the Data Integrity cryptosuites that are W3C Recommendations use Ed25519 and ECDSA over NIST P-256 and P-384. Bitcoin does not sign with these algorithms. Thus, a Bitcoin-native DID method had no W3C cryptosuite for the signature scheme of Bitcoin.
The btcr2 method uses BIP-340 Schnorr signatures, which Bitcoin uses for Taproot (BIP-341) outputs. The method packages them as a W3C Data Integrity cryptosuite: bip340-jcs-2025.
Why btcr2 Needs a Custom Cryptosuite
The VC Data Model 2.0 recommends two mechanisms to secure credentials. The embedded proof mechanism is W3C VC Data Integrity. The enveloping proof mechanism is VC-JOSE-COSE, which wraps credentials with JOSE, SD-JWT, or COSE instead of an embedded proof. Data Integrity defines the structure of proofs, the canonicalization of documents, and the verification process. But Data Integrity does not specify a signature algorithm. A cryptosuite specifies the concrete signature scheme.
Other cryptosuites cover these algorithms:
eddsa-jcs-2022: Ed25519 (W3C Recommendation, May 2025)ecdsa-jcs-2019: ECDSA only for NIST P-256 and P-384. The W3C Recommendation says that secp256k1 "is not used by this specification".EcdsaSecp256k1Signature2019: an older CCG draft for secp256k1. It uses ECDSA, not Schnorr, and it is not on the Recommendation track.
As of September 2026, no W3C Recommendation cryptosuite uses BIP-340 Schnorr. btcr2 needed a cryptosuite with these properties:
- It uses the same signature algorithm as Bitcoin Taproot.
- It signs and verifies with the 32-byte x-only public keys of BIP-340 (the form that Bitcoin uses for Taproot).
- It puts verification keys in DID documents in the W3C Multikey format.
- It works with MuSig2 (BIP-327) for multi-party signatures (multi-signature section).
Thus, the spec editors wrote a new cryptosuite.
How bip340-jcs-2025 Works
Document Canonicalization
Before the signature, the signer must serialize the document deterministically. Two JSON objects with the same logical content can have different bytes (key order, whitespace). The bip340-jcs-2025 variant uses the JSON Canonicalization Scheme (JCS, RFC 8785) to make one canonical byte sequence. A companion variant, bip340-rdfc-2025, uses RDF Dataset Canonicalization for systems that use JSON-LD extensively.
This post focuses on JCS for these reasons:
- JCS works on plain JSON. It does not need JSON-LD context resolution.
- It does not need an RDF canonicalization library.
- It does not depend on external context documents.
Hash Construction
The cryptosuite follows the hash pattern of the W3C Data Integrity cryptosuites up to the concatenation step (hash algorithm):
- Calculate the SHA-256 hash of the canonical proof configuration (the proof options without
proofValue). - Calculate the SHA-256 hash of the canonical document.
- Concatenate the two 32-byte digests, with the proof configuration hash first.
eddsa-jcs-2022 and ecdsa-jcs-2019 sign this concatenation directly (EdDSA hash step, ECDSA hash step). bip340-jcs-2025 applies one more SHA-256 to get one 32-byte digest. Earlier revisions of BIP-340 accepted only 32-byte messages. The BIP-340 changelog shows that the authors removed this restriction in April 2023.
The cryptosuite still hashes to a fixed 32-byte value before the signature. The signer signs this final 32-byte hash. (This is not the double SHA-256 of Bitcoin transaction IDs. The cryptosuite makes three separate single SHA-256 calls, not SHA-256(SHA-256(x)) over the same input.)
Signature Creation
The signer signs the 32-byte hash with BIP-340 Schnorr:
- The secret key is a standard secp256k1 private key (32 bytes).
- In the BIP-340 algorithm, the public key is 32 bytes: only the x-coordinate, with an implicit even y. (The Multikey section below shows how a DID document publishes this key. There, the wire format is the 33-byte SEC-compressed form.)
- Per BIP-340, the signature is 64 bytes: 32 bytes for the x-coordinate of the nonce point
R, and then the 32-byte scalars. - BIP-340 recommends 32 bytes of fresh auxiliary random data for each signature, as protection against fault injection and side-channel attacks. If randomness is not available, BIP-340 permits a counter or a constant. The normal security properties of the signature (other than side-channel resistance) do not depend on this value.
Proof Structure
The proof follows W3C Data Integrity conventions. For a btcr2 DID update, the proof object has this form (Data Integrity Proof):
{
"@context": [
"https://w3id.org/json-ld-patch/v1",
"https://w3id.org/zcap/v1",
"https://w3id.org/security/data-integrity/v2",
"https://btcr2.dev/context/v1"
],
"type": "DataIntegrityProof",
"cryptosuite": "bip340-jcs-2025",
"verificationMethod": "did:btcr2:k1...#key-0",
"proofPurpose": "capabilityInvocation",
"capability": "urn:zcap:root:did%3Abtcr2%3Ak1...",
"capabilityAction": "Write",
"proofValue": "z..."
}
Most of these fields come from W3C VC Data Integrity (Proofs). Data Integrity requires type and proofPurpose, and it requires cryptosuite when the type is DataIntegrityProof. The btcr2 Data Integrity Proof data structure also requires @context, verificationMethod, capability, capabilityAction, and proofValue. The cryptosuite spec defines how to encode the values. For example, proofValue is the 64-byte BIP-340 signature in base58-btc multibase, which starts with z (Create Proof).
The capability and capabilityAction fields are not part of the cryptosuite. The btcr2 update algorithm adds them to put ZCAP-LD authorization on the proof. Together, these fields show two facts. A key signed the document, and the key had authorization for a specific action (Write) on a specific root capability URN.
Key Representation: Multikey
BIP-340 signs and verifies with 32-byte x-only public keys. Traditional secp256k1 ECDSA usually uses the 33-byte SEC-compressed form. The cryptosuite publishes verification keys in the standard W3C Multikey format, with one important detail.
The spec requires the 0xe701 multicodec prefix, which is 0xe7 (secp256k1-pub) as a varint. The 33-byte SEC-compressed key follows the prefix. The cryptosuite then encodes the result in multibase base58-btc, with the z prefix (Multikey). The multicodec table also lists a bip340-pub codec (0x1340) for BIP-340 public keys, and both codecs have the status draft.
bip340-jcs-2025 does not use bip340-pub. The spec editor wrote that it was simpler to support the 33-byte form with the header that already existed (CCG issue #254, spec issue #7). Thus, the same Multikey holds key material that BIP-340 Schnorr tools and traditional secp256k1 ECDSA tools can use. For the BIP-340 algorithm, implementations drop the first byte of the 33-byte form to get the 32-byte x-coordinate. BIP-340 then uses the even y-coordinate for that x (BIP-340).
A DID document can include the Multikey as a verificationMethod. A Verifiable Credential proof can refer to it, and a verifier resolves it at verification time.
An implementation note: the same secp256k1 private-key bytes can make BIP-340 Schnorr signatures and traditional secp256k1 ECDSA signatures. The curve is the same, and the 33-byte compressed Multikey form works with both schemes. The btcr2 spec says that "the same keypairs can be used to produce both Schnorr Signatures and ECDSA signatures" (Schnorr Signature). But BIP-340 gives a caution about nonce reuse across schemes. It says that the most reliable prevention is to not reuse the same private key across different signature schemes.
BIP-340 also normalizes keys to an even y-coordinate. A key can give a public point with an odd y. In that case, the BIP-340 signature algorithm negates the secret scalar internally, so callers do not do this step. The reference code calls the @noble/curves Schnorr implementation, which does this step.
In the reference implementation, @did-btcr2/keypair has a Signer that accepts an ecdsa, bip340, or bip341 scheme. @did-btcr2/cryptosuite wraps a key as a SchnorrMultikey that makes only BIP-340 Schnorr signatures. The shared curve makes interoperation practical with systems that do not use Schnorr yet.
Verification Flow
- Take the proof from the document.
- Resolve the
verificationMethodto get the public key (Multikey). For a btcr2 update, the resolver reads the key from the current DID document, which is the state before the update (Check update.proof). - (For a btcr2 update) Check the capability invocation.
proofPurposemust becapabilityInvocation,capabilityActionmust beWrite, andcapabilitymust be the root capability URN of the DID. TheverificationMethodmust be in thecapabilityInvocationlist of the current DID document. The spec permits implementations to derive the root capability and invoke it per ZCAP-LD. - If the proof has an
@context, make sure that the@contextof the document starts with the same values. Then make the canonical document and the canonical proof configuration again with JCS (Verify Proof). - Apply the same hash construction as the signer (SHA-256 of each, concatenation, SHA-256 of the concatenation).
- Verify the 64-byte BIP-340 Schnorr signature in
proofValueagainst the public key and the 32-byte hash.
If a step fails, the proof is invalid. The verification is deterministic: each implementation that follows the spec gets the same result.
Standardization Status
The cryptosuite is a public draft at dcdpr.github.io/data-integrity-schnorr-secp256k1. The spec page shows the status "Unofficial Draft" and contains test vectors. Two implementations support it: did-btcr2-js (TypeScript) and data-integrity-java (Java).
In July 2025, the spec editor proposed the cryptosuite as a W3C Credentials Community Group work item on the public-credentials mailing list. As of September 2026, the proposal issue is open with the labels "proposed work items" and "On Hold". The cryptosuite is not on the CCG work items page.
The goal of this process is to make BIP-340 Schnorr signatures available outside btcr2. Any DID method or credential issuer can use this cryptosuite to align its cryptography with the cryptography of Bitcoin.
Conclusion
The bip340-jcs-2025 cryptosuite brings the signature scheme of Bitcoin into the W3C verifiable data ecosystem. btcr2 uses the same algorithm that secures Bitcoin transactions. Thus, it does not add a second cryptographic system with its own assumptions and attack surface. One curve, one signature scheme, and one security model apply from Bitcoin transactions to DID updates to Verifiable Credentials. This choice has a tradeoff. The btcr2 spec says that if Schnorr over secp256k1 fails (for example, because of quantum computers), did:btcr2 "would become obsolete" (Cryptographic Compromise).
