BIP340 Schnorr Signatures for Verifiable Credentials: The bip340-jcs-2025 Cryptosuite

May 15, 2026

BIP340 Schnorr Signatures for Verifiable Credentials: The bip340-jcs-2025 Cryptosuite

Introduction

Every DID method needs a way to sign and verify data — DID document updates, Verifiable Credentials, authentication challenges. The W3C-recommended Data Integrity cryptosuites cover Ed25519 and ECDSA over NIST P-256/P-384 — neither of which is what Bitcoin signs with. For a Bitcoin-native DID method, that lineup is a missed opportunity. btcr2 uses BIP-340 Schnorr signatures — the scheme Bitcoin uses for Taproot (BIP-341) outputs — and packages them as a W3C Data Integrity cryptosuite: bip340-jcs-2025.

Why a Custom Cryptosuite?

W3C VC Data Integrity is one of two W3C-track frameworks for attaching cryptographic proofs to credentials (the other being VC-JOSE-COSE, which envelopes credentials with JWS for JSON or COSE for CBOR rather than embedding a proof). Data Integrity defines how proofs are structured, how documents are canonicalized, and how verification works — but it's algorithm-agnostic. You need a cryptosuite that specifies the concrete signature scheme.

Existing cryptosuites cover:

  • eddsa-jcs-2022 — Ed25519 (W3C Recommendation, May 2025)
  • ecdsa-jcs-2019 — ECDSA scoped to NIST P-256 / P-384 only; the W3C Recommendation explicitly notes secp256k1 "is not used by this specification"
  • EcdsaSecp256k1Signature2019 — an older CCG draft that does cover secp256k1, but uses ECDSA, not Schnorr, and isn't on the Recommendation track

Nothing in the existing W3C lineup uses BIP-340 Schnorr. btcr2 needed a cryptosuite that:

  • Uses the exact same signature algorithm as Bitcoin Taproot
  • Signs with BIP-340's 32-byte x-only public keys (the form Bitcoin uses for Taproot)
  • Embeds verification keys in DID documents via the W3C Multikey format
  • Composes with MuSig2 (BIP-327) for multi-party signatures

So one was built.

How bip340-jcs-2025 Works

Document Canonicalization

Before signing, the document must be serialized deterministically. Two logically identical JSON objects might have different byte representations (key ordering, whitespace). The bip340-jcs-2025 variant uses JSON Canonicalization Scheme (JCS, RFC 8785) to produce a canonical byte sequence; a companion bip340-rdfc-2025 variant uses RDF Dataset Canonicalization for JSON-LD-heavy stacks.

JCS is the focus of this post because:

  • It works on plain JSON — no JSON-LD context resolution required
  • It's simpler to implement and audit
  • It doesn't introduce external dependencies on context documents

Hashing

The cryptosuite follows the W3C Data Integrity hashing pattern up to the concatenation step: SHA-256 the canonicalized document; SHA-256 the canonicalized proof configuration (the proof options minus proofValue); concatenate the two 32-byte digests. Where eddsa-jcs-2022 and ecdsa-jcs-2019 sign that 64-byte concatenation directly, bip340-jcs-2025 applies one more SHA-256 to reduce it to 32 bytes — because BIP-340 signs 32-byte messages. The final 32-byte hash is what gets signed. (This is not the same as Bitcoin's double-SHA-256 used for transaction hashing — it's three independent single-round SHA-256 calls, not SHA-256(SHA-256(x)) over the same input.)

Signing

The 32-byte hash is signed using BIP-340 Schnorr:

  • The signing key is a standard secp256k1 private key (32 bytes)
  • The corresponding public key, in BIP-340's algorithm form, is 32 bytes — the x-coordinate alone, with implicit even y (see the Multikey section below for how that key is published in DID documents, where the wire format is the 33-byte SEC-compressed form)
  • The signature is 64 bytes per BIP-340: 32 bytes encoding the x-coordinate of the nonce point R, followed by the 32-byte scalar s
  • BIP-340 recommends an auxiliary 32-byte random input at signing time as protection against fault-injection and side-channel attacks; if randomness is unavailable, the spec permits constants or counters in its place — the security of the signature itself does not depend on the auxiliary value

Proof Structure

The resulting proof follows W3C Data Integrity conventions. For a btcr2 DID update, the proof object looks like:

{
  "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..."
}

The required fields here — type, cryptosuite, verificationMethod, proofPurpose, and proofValue — are inherited from W3C VC Data Integrity, not added by the cryptosuite. The bip340-jcs-2025 spec's job is to define the encoding of those values (notably: the proofValue is the 64-byte BIP-340 signature, base58-btc multibase-encoded — hence the leading z). The capability and capabilityAction fields aren't part of the cryptosuite at all; they're added on top by btcr2's update algorithm, which layers ZCAP-LD authorization onto the proof. Together they mean the proof doesn't just demonstrate that a key signed the document — it demonstrates that the key was authorized to perform the specific action (Write, in this case) against a specific target capability URN.

Key Representation: Multikey

BIP-340 signs and verifies with 32-byte x-only public keys — a departure from the 33-byte SEC-compressed form typical of secp256k1 ECDSA. The cryptosuite still publishes verification keys via the standard W3C Multikey format, with one practical wrinkle worth knowing about: the spec mandates the 0xe701 multicodec prefix (the varint encoding of 0xe7, the existing secp256k1-pub codec) followed by the 33-byte SEC-compressed key, then multibase base58-btc encoded with a leading z. The multicodec table also lists a draft bip340-pub codec (0x1340) for native 32-byte x-only keys, but bip340-jcs-2025 deliberately reuses the compressed-key codec — letting the same Multikey carry material usable by both BIP-340 Schnorr and traditional secp256k1 ECDSA tooling. Implementations recover the 32-byte x-coordinate from the 33-byte form for the BIP-340 algorithm, handling y-parity per the BIP-340 specification.

The Multikey can be embedded in DID documents as a verificationMethod, referenced from Verifiable Credential proofs, and resolved during verification.

A practical implementation note: the same secp256k1 private-key bytes can drive both BIP-340 Schnorr signing and traditional secp256k1 ECDSA — the curve is the same, and the Multikey form (33-byte compressed) round-trips across both schemes. There's a subtlety worth knowing about, though: BIP-340 normalizes its keys to even y-parity, so if a key derives a public point with odd y, the BIP-340 algorithm internally negates the scalar to produce the canonical even-y form. Libraries like @did-btcr2/cryptosuite handle that transparently and expose both signers, which is useful when interoperating with systems that haven't adopted Schnorr yet.

Verification Flow

  1. Extract the proof from the document
  2. Resolve the verificationMethod DID to obtain the public key (Multikey)
  3. (For a btcr2 update) verify the ZCAP-LD capability invocation — the capability URN points at a root capability whose controller should authorize this verificationMethod for the declared capabilityAction
  4. Reconstruct the canonical document and the canonical proof configuration via JCS
  5. Apply the same hash construction as signing (SHA-256 each, concatenate, SHA-256 the concatenation)
  6. Verify the 64-byte BIP-340 Schnorr signature in proofValue against the resolved public key over that 32-byte hash

If any step fails, the proof is invalid. The verification is fully deterministic — any implementation that follows the spec will reach the same conclusion.

Standardization Status

The cryptosuite is published as a public draft at dcdpr.github.io/data-integrity-schnorr-secp256k1, with an accompanying test-vector suite and reference implementations. As of this writing, work continues in the open under the W3C Credentials Community Group's public-credentials mailing list; track the W3C CCG work-items page for formal adoption status.

The point of taking it through this process is so BIP-340 Schnorr signatures aren't locked into btcr2 — any DID method or credential issuer can use this cryptosuite to align their cryptography with Bitcoin's.

Conclusion

The bip340-jcs-2025 cryptosuite brings Bitcoin's signature scheme into the W3C verifiable data ecosystem. By using the same algorithm that secures Bitcoin transactions, btcr2 avoids introducing a parallel cryptographic system with its own assumptions and attack surface. One curve, one signature scheme, one security model — from Bitcoin transactions to DID updates to Verifiable Credentials.

Jintek LLC