<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" version="3" ipr="trust200902" docName="draft-bormann-jwp-modular-bbs-00" submissionType="IETF" category="std" xml:lang="en" indexInclude="true">

<front>
<title abbrev="JWP-BBS">BBS and Modular Sub-proofs with JSON Web Proofs</title><seriesInfo value="draft-bormann-jwp-modular-bbs-00" stream="IETF" status="standard" name="Internet-Draft"/>
<author initials="C." surname="Bormann" fullname="Christian Bormann"><organization>SPRIND GmbH</organization><address><postal><street/>
</postal><email>chris.bormann@gmx.de</email>
</address></author><date/>
<area>Security</area>
<workgroup>TODO Working Group</workgroup>
<keyword>zero-knowledge proofs</keyword>
<keyword>multi-message signatures</keyword>
<keyword>BBS</keyword>
<keyword>JWP</keyword>

<abstract>
<t>This document defines a digital credential format that uses JSON Web Proofs (JWP) as its container format and Blind BBS Signatures as its signature scheme combined with a modular framework for attaching zero-knowledge sub-proofs to signed but undisclosed attributes that allow a Holder to reveal some attributes directly while proving predicates such as range or equality over the ones they keeps hidden. A credential can additionally be bound to an ECDSA P-256 device key. The credential metadata and type model follow SD-JWT VC <xref target="I-D.ietf-oauth-sd-jwt-vc"/>.</t>
</abstract>

<note title="Discussion Venues" removeInRFC="true">
<t>Discussion of this document takes place on the
    JSON Web Proofs Working Group mailing list (jose@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/jose/"/>.</t>
<t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/c2bo/draft-bormann-jwp-modular-bbs"/>.</t>
</note>
</front>

<middle>

<section anchor="introduction"><name>Introduction</name>
<t>The BBS signature scheme <xref target="I-D.irtf-cfrg-bbs-signatures"/> is a multi-message signature (MMS) scheme where the signer produces a single signature over a vector of messages m<em>0 through m</em>(n-1), and the Holder can prove knowledge of the signature in zero knowledge while disclosing only a chosen subset of those messages.</t>
<t>The Blind BBS Signatures extension <xref target="I-D.irtf-cfrg-bbs-blind-signatures"/> adds Pedersen commitments to the scheme that allow the Holder to mark each message as disclosed, hidden, or committed at proof time, and the resulting proof carries a fresh Pedersen commitment for every committed message. Those commitments become public inputs to further proofs over the values they hide.</t>
<t>Building on those core building lbocks, this document defines a digital credential format that:</t>

<ul spacing="compact">
<li>Uses JSON Web Proofs <xref target="I-D.ietf-jose-json-web-proof"/> as the serialization/container format for both issuance and presentation, and defines a JSON Proof Algorithm <xref target="I-D.ietf-jose-json-proof-algorithms"/> profile based on Blind BBS Signatures.</li>
<li>Builds its core proof on <tt>CoreProofGen</tt> of <xref target="I-D.irtf-cfrg-bbs-blind-signatures"/>, exposing fresh Pedersen commitments to selected messages as public inputs for sub-proofs.</li>
<li>Defines a sub-proof container carrying optional sub-proofs, each bound to the core proof via a Pedersen commitment.</li>
<li>Optionally bind a credential to an ECDSA P-256 device key by encoding that key as messages in the BBS signature vector.</li>
</ul>
<t>This modular architecture builds on prior work <xref target="TS14"/> and <xref target="LSZ25"/>, and the credential type and metadata model are reused from SD-JWT VC <xref target="I-D.ietf-oauth-sd-jwt-vc"/>.</t>

<section anchor="requirements-notation-and-conventions"><name>Requirements Notation and Conventions</name>
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
when, and only when, they appear in all capitals, as shown here.</t>
</section>

<section anchor="notational-conventions"><name>Notational Conventions</name>
<t>All examples in this document are non-normative.</t>
<t>Indexing into vectors is 0-based. The notation <tt>m_i</tt> denotes the i-th element of the message vector: <tt>m_0</tt> is the first element. Ranges are written <tt>[a, b]</tt> for inclusive endpoints and <tt>[a, b)</tt> for a half-open interval.</t>
</section>

<section anchor="terms-and-definitions"><name>Terms and Definitions</name>
<t>This document uses the Issuer-Holder-Verifier model and terminology of <xref target="I-D.ietf-oauth-sd-jwt-vc"/>.</t>
<t>Additional terminology used are:</t>

<dl spacing="compact">
<dt>Core proof:</dt>
<dd>A zero-knowledge proof of knowledge of a BBS signature on a message vector, where some messages are disclosed and others are exposed only as commitments.</dd>
<dt>Sub-proof:</dt>
<dd>A zero-knowledge proof attached to a core proof, asserting a predicate over a message whose Pedersen commitment that core proof exposes.</dd>
<dt>Committed disclosure:</dt>
<dd>Exposing a Pedersen commitment to a signed message in place of the value itself that is used as an input for sub-proofs.</dd>
<dt>Device binding:</dt>
<dd>Tying a credential presentation to control of a Holder-held private key, by carrying a fresh proof of possession in every presentation.</dd>
</dl>
</section>
</section>

<section anchor="data-model"><name>Data Model</name>
<t>A credential exists in two forms: the Issued Form an Issuer transmits to a Holder, and the Presented Form a Holder derives from it for a Verifier (see <xref target="presentation"/>).</t>

<section anchor="issued-credential"><name>Issued Credential</name>
<t>A credential is issued in the Issued Form (see Section 6.1 of <xref target="I-D.ietf-jose-json-web-proof"/>) consisting of:</t>

<ul spacing="compact">
<li>An Issuer Header (Section 6.1.1 of <xref target="I-D.ietf-jose-json-web-proof"/>) with the contents specified in <xref target="issuer-header"/>.</li>
<li><tt>n</tt> Issuer Payloads (Section 6.1.2 of <xref target="I-D.ietf-jose-json-web-proof"/>), where <tt>n</tt> is the length of the BBS message vector (see <xref target="claims-mapping"/>). The Issuer Payload at position <tt>i</tt> is the octet string from which the scalar message <tt>m_i</tt> is derived per <xref target="message-derivation"/>.</li>
<li>An Issuer Proof (Section 6.1.3 of <xref target="I-D.ietf-jose-json-web-proof"/>) carrying the blind BBS signature over <tt>header_octets</tt> and the message vector <tt>(m_0, ..., m_(n-1))</tt>.</li>
</ul>
<t><tt>header_octets</tt> is the Issuer Header as transmitted, i.e., the octets obtained by base64url-decoding the Issuer Header component of the Compact Serialization. All parties MUST use those octets as received and MUST NOT alter the header (e.g., re-encode).</t>
<t>The Issued Form is serialized using the Compact Serialization (Section 7.1 of <xref target="I-D.ietf-jose-json-web-proof"/>). CBOR Serialization is (currently) out of scope for this document.</t>
</section>

<section anchor="issuer-header"><name>Issuer Header</name>
<t>The Issuer Header is a JSON object with the following Header Parameters.</t>

<dl spacing="compact">
<dt><tt>alg</tt> (REQUIRED):</dt>
<dd>The Algorithm Header Parameter (Section 5.2.1 of <xref target="I-D.ietf-jose-json-web-proof"/>). This profile defines the JPA value <tt>BBS-MOD</tt> (see <xref target="cipher-suite"/>).</dd>
<dt><tt>vct</tt> (string, REQUIRED):</dt>
<dd>The credential type identifier as defined in Section 3.2.2.1 of <xref target="I-D.ietf-oauth-sd-jwt-vc"/>.</dd>
<dt><tt>claims</tt> (JSON object, REQUIRED):</dt>
<dd>The mapping from claim names to message-vector positions and per-message encoding - see <xref target="claims-mapping"/> for more details.</dd>
<dt><tt>kb</tt> (string, OPTIONAL):</dt>
<dd>The device-binding identifier - see <xref target="device-binding-header"/>. When absent, the credential is not device-bound, and a presentation MUST NOT include a device-binding sub-proof.</dd>
</dl>
<t>Temporal claims (<tt>exp</tt>, <tt>nbf</tt>, <tt>iat</tt>) MUST NOT appear as Issuer Header values - see <xref target="temporal-claims"/> for more details.</t>
<t>The JWP <tt>iek</tt>, <tt>hpk</tt>, and <tt>hpa</tt> Header Parameters (Sections 5.2.5–5.2.7 of <xref target="I-D.ietf-jose-json-web-proof"/>) MUST NOT appear in the Issuer Header.</t>
</section>

<section anchor="claims-mapping"><name>Claims Mapping</name>
<t><tt>claims</tt> mirrors the credential's JSON tree structurally. Each leaf is replaced by an index annotation: a two-element JSON array <tt>[i, scalar]</tt>, where:</t>

<ul spacing="compact">
<li><tt>i</tt> is the 0-based index of the leaf value in the message vector.</li>
<li><t><tt>scalar</tt> is a boolean selecting how the leaf becomes the BBS message m_i:</t>

<ul spacing="compact">
<li><tt>false</tt>: the leaf is encoded as octets and mapped to a scalar via the cipher suite's hash-to-scalar primitive (see <xref target="message-derivation"/>).</li>
<li><tt>true</tt>: the leaf MUST be a JSON integer in <tt>[0, r - 1]</tt> (where <tt>r</tt> is the order of the BBS scalar field) and is used directly as m_i (see <xref target="scalar-encoding"/>).</li>
</ul></li>
</ul>
<t>Let <tt>n</tt> be the length of the message vector, and <tt>N</tt> the number of payload slots reserved for the device-key encoding (see <xref target="device-binding-header"/>), with <tt>N = 0</tt> when <tt>kb</tt> is absent). Every index in <tt>[N, n-1]</tt> MUST appear in exactly one annotation in <tt>claims</tt>. Indices <tt>[0, N-1]</tt> MUST NOT appear in <tt>claims</tt>.</t>
<t>Payload slots defined by the credential type's structural layout (see <xref target="layout"/>) but not populated by a given credential MUST carry the decoy value defined in <xref target="decoys"/>.</t>
</section>

<section anchor="example-issuer-header"><name>Example: Issuance</name>
<t>Starting from an SD-JWT VC-style claim set <xref target="I-D.ietf-oauth-sd-jwt-vc"/>:</t>

<sourcecode type="json"><![CDATA[{
  "vct": "https://credentials.example.com/identity_credential",
  "given_name": "Erika",
  "family_name": "Mustermann",
  "email": "erika@example.com",
  "phone_number": "+49 123456789",
  "address": {
    "street_address": "Heidestraße 17",
    "locality": "Köln",
    "region": "Nordrhein-Westfalen",
    "country": "DE"
  },
  "birthdate": "19630812",
  "is_over_18": true,
  "is_over_21": true,
  "is_over_65": false,
  "iat": 1683000000,
  "exp": 1786000000
}
]]>
</sourcecode>
<t>The <tt>vct</tt> claim becomes a Header Parameter and the other 14 attributes become leaves in <tt>claims</tt>, with <tt>address</tt> mirrored as a nested object. No device binding is used, so <tt>N = 0</tt> and the leaves occupy indices 0 through 13. The temporal claims <tt>iat</tt> and <tt>exp</tt> are carried as <tt>scalar = true</tt> leaves (see <xref target="temporal-claims"/>) to allow range sub-proofs over them. The resulting Issuer Header is:</t>

<sourcecode type="json"><![CDATA[{
  "alg": "BBS-MOD",
  "vct": "https://credentials.example.com/identity_credential",
  "claims": {
    "given_name": [0, false],
    "family_name": [1, false],
    "email": [2, false],
    "phone_number": [3, false],
    "address": {
      "street_address": [4, false],
      "locality": [5, false],
      "region": [6, false],
      "country": [7, false]
    },
    "birthdate": [8, false],
    "is_over_18": [9, false],
    "is_over_21": [10, false],
    "is_over_65": [11, false],
    "iat": [12, true],
    "exp": [13, true]
  }
}
]]>
</sourcecode>
<t>Indices 0–11 use hash-to-scalar and indices 12–13 carry NumericDate integers (<xref target="RFC7519"/>) directly as scalars. A presentation can then mark <tt>iat</tt>/<tt>exp</tt> as <tt>COMMIT</tt> (see <xref target="core-proof"/>) and attach <tt>sigma-range</tt> sub-proofs (see <xref target="range-proof"/>) to prove validity without disclosing the timestamps.</t>
<t>A real deployment would define a structural layout covering all optional attributes and array slots up to their maximum length, with absent slots filled by decoys (see <xref target="decoys"/>).</t>
</section>

<section anchor="message-derivation"><name>Message Derivation</name>
<t>For an annotation <tt>[i, false]</tt> with leaf value <tt>v</tt>:</t>

<ol spacing="compact">
<li>The Issuer chooses an octet encoding <tt>o</tt> of <tt>v</tt> (e.g., the UTF-8 octets of a string) and carries it as Issuer Payload <tt>i</tt>. This profile does not mandate a specific encoding. Holders MUST use the received payload octets as-is.</li>
<li>m_i = <tt>hash_to_scalar(o, map_dst)</tt>, with <tt>map_dst = api_id || "MAP_MSG_TO_SCALAR_AS_HASH_"</tt> and <tt>api_id</tt> the Interface identifier of <xref target="cipher-suite"/>. This is the per-message derivation of <tt>BBS.messages_to_scalars</tt> (Section 4.1.2 of <xref target="I-D.irtf-cfrg-bbs-signatures"/>).</li>
</ol>
<t>For an annotation <tt>[i, true]</tt> with leaf value <tt>v</tt>:</t>

<ol spacing="compact">
<li><tt>o</tt> is the canonical decimal octet encoding of <tt>v</tt> (see <xref target="scalar-encoding"/>), carried as Issuer Payload <tt>i</tt>.</li>
<li>m_i is the integer denoted by <tt>o</tt>, interpreted as an element of the BBS scalar field.</li>
</ol>
</section>

<section anchor="scalar-encoding"><name>Scalar Encoding</name>
<t>A leaf with <tt>scalar = true</tt> MUST be a JSON integer in <tt>[0, r - 1]</tt>, where <tt>r</tt> is the order of the BBS scalar field. Implementations MUST reject any other value.</t>
<t>The Issuer Payload for such a leaf is the canonical decimal octet encoding of the integer. Future extensions MAY define additional scalar encodings provided they deterministically map a JSON value to an element of <tt>[0, r - 1]</tt>.</t>
</section>

<section anchor="temporal-claims"><name>Temporal Claims</name>
<t>The JWT temporal claims <tt>exp</tt>, <tt>nbf</tt>, and <tt>iat</tt> (Section 4.1 of <xref target="RFC7519"/>), when present in a credential, MUST be declared as <tt>scalar = true</tt> leaves in <tt>claims</tt> carrying their NumericDate values. They MUST NOT appear as Issuer Header values.</t>
</section>

<section anchor="device-binding-header"><name>Device Binding Header</name>
<t>When present, the <tt>kb</tt> Header Parameter is a string identifier selecting both the device public key type and its encoding into the BBS message vector. The reserved slots are always indices <tt>[0, N-1]</tt>, where <tt>N</tt> depends on the <tt>kb</tt> value. If <tt>kb</tt> is not present, no slots are reserved. This document defines a single value for <tt>kb</tt>: <tt>ecdsa-p256-db</tt>.</t>
<t>A <tt>kb</tt> value and its matching device-binding sub-proof algorithm (see <xref target="sub-proofs"/>) share the same algorithm identifier string.</t>
<t>For <tt>kb = "ecdsa-p256-db"</tt>, <tt>N = 4</tt> and:</t>

<ul spacing="compact">
<li>m_0..m_1 encode the x-coordinate of the device public key as two 128-bit little-endian limbs (m_0 least significant).</li>
<li>m_2..m_3 encode the y-coordinate the same way.</li>
</ul>
<t>Each limb is encoded as if <tt>scalar = true</tt>: the Issuer Payload is its canonical decimal octet encoding (see <xref target="scalar-encoding"/>).</t>
<t>The Issuer MUST make sure that <tt>(x, y)</tt> is a valid non-identity P-256 point <xref target="FIPS186-5"/> before computing the message vector.</t>
</section>

<section anchor="layout"><name>Structural Layout</name>
<t>For claims containing objects, the Issuer either mirrors the object structure within <tt>claims</tt> or treats the JSON-encoded object as a single leaf. This is a policy decision by the Issuer and allows some objects to be discloseable only as one object containing all values or not at all.</t>
<t>For bounded-length array claims, <tt>claims</tt> contains a JSON array of index annotations sized to the credential type's maximum array length. All entries in such an array SHOULD share the same <tt>scalar</tt> flag to guarantee a single decoy encoding (see <xref target="decoys"/>).</t>
<t>For optional claims, <tt>claims</tt> MUST contain the index entry regardless of whether the attribute is present in a given credential.</t>
</section>

<section anchor="decoys"><name>Decoys</name>
<t>Decoys fill payload slots that the credential type's layout defines, but a specific credential does not populate. They keep the message-vector length and <tt>claims</tt> identical across all credentials of a given <tt>vct</tt> to avoid correlation.</t>
<t>Every decoy slot carries the same fixed scalar:</t>

<artwork><![CDATA[m_decoy = hash_to_scalar("JWP-BBS-DECOY", map_dst)
]]>
</artwork>
<t>with <tt>hash_to_scalar</tt> and <tt>map_dst</tt> as defined in <xref target="message-derivation"/>.</t>
<t>The Issuer Payload for a decoy slot depends on the slot's <tt>scalar</tt> flag:</t>

<ul spacing="compact">
<li><tt>scalar = false</tt>: the ASCII octets of <tt>"JWP-BBS-DECOY"</tt>.</li>
<li><tt>scalar = true</tt>: the canonical decimal octet encoding of <tt>m_decoy</tt> (see <xref target="scalar-encoding"/>).</li>
</ul>
<t>A Verifier detects a disclosed decoy by comparing the disclosed Presentation Payload octets to the fixed decoy octets defined above. Decoys SHOULD NOT be disclosed unless required by the use case (for example, a proof over all members of a bounded-length array).</t>
</section>
</section>

<section anchor="issuance"><name>Issuance</name>

<section anchor="issuer-key-generation"><name>Issuer Key Generation</name>
<t>The Issuer key pair is a BBS key pair (Section 3.4 of <xref target="I-D.irtf-cfrg-bbs-signatures"/>) using the cipher suite of <xref target="cipher-suite"/>.</t>
</section>

<section anchor="credential-issuance"><name>Credential Issuance</name>
<t>To issue a credential, the issuer performs the following steps:</t>

<ol spacing="compact">
<li>Construct the Issuer Header per <xref target="issuer-header"/> and <xref target="claims-mapping"/>.</li>
<li>Derive the message vector <tt>(m_0, ..., m_(n-1))</tt> per <xref target="message-derivation"/> and <xref target="device-binding-header"/>, filling decoys per <xref target="decoys"/>.</li>
<li>Compute the blind BBS signature over <tt>header_octets</tt> and the message vector.</li>
<li>Assemble and serialize the Issued Form per <xref target="issued-credential"/>.</li>
</ol>
<t>A non-normative example of the Compact Serialization:</t>

<artwork><![CDATA[<base64url(Issuer Header)>
.
<m_0>~<m_1>~ ... ~<m_13>
.
<base64url(blind BBS signature)>
]]>
</artwork>
<t>Each <tt>&lt;m_i&gt;</tt> is the base64url-encoded Issuer Payload for index <tt>i</tt> (e.g., m_1 is "Mustermann", m_13 is <tt>1786000000</tt>).</t>
</section>

<section anchor="holder-verification"><name>Holder Verification</name>
<t>The Holder verifies an issued credential by:</t>

<ol spacing="compact">
<li>Parsing the Issued Form.</li>
<li>Verifying the blind BBS signature over <tt>header_octets</tt> and the message vector. Reject on failure.</li>
<li>For every <tt>scalar = true</tt> leaf, confirming the corresponding Issuer Payload decodes to an integer in <tt>[0, r - 1]</tt>.</li>
<li>If <tt>kb</tt> is present, confirming that the point reconstructed from the limb messages matches the Holder's device public key. How the Holder obtains the corresponding device key pair is out of scope.</li>
</ol>
</section>
</section>

<section anchor="presentation"><name>Presentation</name>

<section anchor="presented-form"><name>Presented Form</name>
<t>A presentation is a Presented Form (Section 6.2 of <xref target="I-D.ietf-jose-json-web-proof"/>) consisting of:</t>

<ol spacing="compact">
<li>A Presentation Header per <xref target="presentation-header"/>.</li>
<li>The Issuer Header from issuance, byte-identical to the issued form.</li>
<li><tt>n</tt> Presentation Payloads (Section 6.2.2 of <xref target="I-D.ietf-jose-json-web-proof"/>): disclosed positions carry the corresponding Issuer Payload and undisclosed positions are omitted (see Section 7.1 of <xref target="I-D.ietf-jose-json-web-proof"/>).</li>
<li>A Presentation Proof (Section 6.2.4 of <xref target="I-D.ietf-jose-json-web-proof"/>) consisting of one or more octet strings. The first octet string is the encoded core proof (see <xref target="core-proof"/>). Subsequent octet strings, if any, are UTF-8 JSON-serialized sub-proof objects (see <xref target="sub-proofs"/>) and MAY appear in any order. The Compact Serialization base64url-encodes each octet string.</li>
</ol>
</section>

<section anchor="presentation-header"><name>Presentation Header</name>
<t>The Presentation Header is a JSON object with the following Header Parameters.</t>

<dl spacing="compact">
<dt><tt>nonce</tt> (string, REQUIRED):</dt>
<dd>The Nonce Header Parameter (Section 5.2.10 of <xref target="I-D.ietf-jose-json-web-proof"/>).</dd>
<dt><tt>aud</tt> (string, REQUIRED):</dt>
<dd>The Audience Header Parameter (Section 5.2.9 of <xref target="I-D.ietf-jose-json-web-proof"/>).</dd>
</dl>
<t>Additional Header Parameters MAY be present, but their use is out of scope for this document.</t>
<t><tt>presentation_header_octets</tt> is the Presentation Header as transmitted, i.e., the octets obtained by base64url-decoding the Presentation Header component of the Compact Serialization. It is bound into the core proof challenge (see <xref target="core-proof"/>). Verifiers MUST use those octets as received.</t>
</section>

<section anchor="core-proof"><name>Core Proof</name>
<t>The Holder builds a per-message disclosure map assigning each index in <tt>[N, n-1]</tt> (where <tt>N</tt> is as in <xref target="claims-mapping"/>) one of <tt>DISCLOSE</tt>, <tt>HIDE</tt>, or <tt>COMMIT</tt>:</t>

<ul spacing="compact">
<li><tt>DISCLOSE</tt>: the message is revealed and its value MUST match the corresponding disclosed Presentation Payload.</li>
<li><tt>COMMIT</tt>: a fresh Pedersen commitment to the message is carried in the proof. Every index referenced by a sub-proof (see <xref target="sub-proofs"/>) MUST be marked <tt>COMMIT</tt>.</li>
<li><tt>HIDE</tt>: all other indices in <tt>[N, n-1]</tt>. Device-key indices <tt>[0, N-1]</tt> are implicitly hidden.</li>
</ul>
<t>The Holder generates the core proof by invoking <tt>CoreProofGen</tt> of <xref target="I-D.irtf-cfrg-bbs-blind-signatures"/> with:</t>

<ul spacing="compact">
<li><tt>PK</tt>: Issuer public key.</li>
<li><tt>signature</tt>: blind BBS signature from the Issuer Proof.</li>
<li><tt>header</tt>: <tt>header_octets</tt>.</li>
<li><tt>ph</tt>: <tt>presentation_header_octets</tt> (binds <tt>nonce</tt> and <tt>aud</tt> into the challenge).</li>
<li><tt>messages</tt>: <tt>(m_0, ..., m_(n-1))</tt>.</li>
<li><tt>disclosed_indexes</tt>: indices marked <tt>DISCLOSE</tt>.</li>
<li><tt>commits_indexes</tt>: indices marked <tt>COMMIT</tt>.</li>
<li><tt>api_id</tt>: the cipher suite identifier of <xref target="cipher-suite"/>.</li>
</ul>
<t><tt>CoreProofGen</tt> returns <tt>(proof, add_zkp_info)</tt>. <tt>add_zkp_info</tt> contains, per committed index, the Pedersen commitment <tt>C_i</tt> and the blinding scalar <tt>s_i</tt>. The Holder retains it locally to build sub-proofs and MUST NOT transmit it. Only <tt>proof</tt> is carried as the first octet string of the Presentation Proof.</t>
<t>The core proof establishes that the Holder knows a blind BBS signature under the Issuer's public key on a message vector whose disclosed-index values match the disclosed Presentation Payloads, and that each carried <tt>C_i</tt> commits to the message at index <tt>i</tt> of that vector.</t>
<t>The Verifier verifies the core proof with <tt>CoreProofVerify</tt>, passing <tt>PK</tt>, the core proof, <tt>header_octets</tt>, <tt>presentation_header_octets</tt>, the disclosed scalar messages, and <tt>api_id</tt>. The disclosed and committed indices are recovered from the proof octets, not passed separately. On success, the Verifier recovers the committed indices and the corresponding <tt>C_i</tt> from the proof octets which are used in the sub-proof verification (see <xref target="sub-proofs"/>).</t>
</section>

<section anchor="sub-proofs"><name>Sub-Proofs</name>
<t>A sub-proof is a JSON object carried as an additional octet string of the Presentation Proof (see <xref target="presented-form"/>) with the following members:</t>

<dl spacing="compact">
<dt><tt>alg</tt> (string, REQUIRED):</dt>
<dd>The sub-proof algorithm identifier from the Sub-Proof Algorithms registry (see <xref target="iana"/>).</dd>
<dt><tt>input</tt> (JSON object, REQUIRED):</dt>
<dd>Public inputs to the sub-proof. MUST contain <tt>i</tt> and MAY contain algorithm-specific members.</dd>
</dl>
<t><tt>i</tt> is a non-empty JSON array of message-vector indices, each of which MUST be a <tt>COMMIT</tt>-marked index of the core proof. Each algorithm fixes the length of <tt>i</tt> and the role of its entries.</t>

<dl spacing="compact">
<dt><tt>proof</tt> (string, REQUIRED):</dt>
<dd>The base64url <xref target="RFC4648"/> encoding of the sub-proof bytes specified by <tt>alg</tt>.</dd>
</dl>
<t>For each sub-proof, the Verifier MUST confirm that every value in <tt>i</tt> is among the committed indices recovered from the core proof, and MUST then run the algorithm-specific verification routine against the corresponding <tt>C_i</tt>, <tt>input</tt>, and <tt>proof</tt>.</t>
<t>Sub-proof freshness is inherited from the core proof: every <tt>C_i</tt> is randomized per presentation, and the core proof's challenge binds to <tt>presentation_header_octets</tt>. Sub-proof algorithms that include public material not derived from <tt>C_i</tt> (for example, the device ECDSA signature in <tt>ecdsa-p256-db</tt>) MUST bind that material to the current presentation by other means (<tt>ecdsa-p256-db</tt> does so via <tt>db_msg</tt> - see <xref target="ecdsa-db"/>).</t>
<t>Sub-proof transcripts use the BBS encoding primitives of Section 4.2.4.1 of <xref target="I-D.irtf-cfrg-bbs-signatures"/>: BLS12-381 G1 points are serialized in their compressed form (48 octets), scalars as 32-octet big-endian integers, and integer lengths are encoded as <tt>I2OSP(int, 8)</tt>. The <tt>serialize(...)</tt> notation used in <xref target="range-proof"/> and <xref target="equality-proof"/> denotes the concatenation of these per-element encodings.</t>
<t>[Editor's Note: Some of the following sub-proofs already make very concrete choices to make the construction more concrete - all of these are open for discussion and will very like see significant changes.]</t>

<section anchor="ecdsa-db"><name>ECDSA Device-Binding Sub-Proof</name>
<t>This sub-proof MUST be present whenever <tt>kb = "ecdsa-p256-db"</tt> and MUST NOT be present otherwise. The algorithm identifier deliberately matches the <tt>kb</tt> value it verifies (see <xref target="device-binding-header"/>).</t>

<dl spacing="compact">
<dt>Algorithm identifier:</dt>
<dd><tt>ecdsa-p256-db</tt></dd>
</dl>
<t>Inputs (beyond the base sub-proof fields): none. The <tt>i</tt> field MUST be <tt>[0, 1, 2, 3]</tt>, naming the four indices that carry the device public-key limbs (see <xref target="device-binding-header"/>).</t>
<t>The device-signed message is not transmitted, it is recomputed as:</t>

<artwork><![CDATA[db_msg = "JWP-BBS-DB-CHAL" || presentation_header_octets
]]>
</artwork>
<t>where <tt>"JWP-BBS-DB-CHAL"</tt> is the literal ASCII string. Binding <tt>db_msg</tt> to <tt>presentation_header_octets</tt> carries <tt>nonce</tt> and <tt>aud</tt> and is therefore sufficient for freshness.</t>
<t>The proof bytes encode a non-interactive zero-knowledge proof of knowledge of <tt>(dpk, (r, s))</tt> such that:</t>

<ol spacing="compact">
<li>The 4 commitments at the indices in <tt>i</tt> open to the 128-bit limbs of <tt>dpk</tt> (in the layout of <tt>kb</tt>) under <tt>(G, H)</tt> (see <xref target="cipher-suite"/>).</li>
<li><tt>(r, s)</tt> is a valid ECDSA P-256 signature on <tt>db_msg</tt> under <tt>dpk</tt>.</li>
</ol>
<t>[Editor's Note: TODO - select and describe concrete mechanism - expectation is that this will be described in another IETF draft]</t>
<t>The Verifier accepts if the 4 indices in <tt>i</tt> are all committed in the core proof and the sub-proof verifies against the 4 commitments and the locally recomputed <tt>db_msg</tt>.</t>
</section>

<section anchor="range-proof"><name>Range Proof Sub-Proof</name>

<dl spacing="compact">
<dt>Algorithm identifier:</dt>
<dd><tt>sigma-range</tt></dd>
</dl>
<t>Inputs (beyond the base sub-proof fields): bounds <tt>l</tt> and <tt>u</tt> as JSON integers. The <tt>i</tt> field MUST be a single-element array <tt>[idx]</tt>. The sub-proof attests that m_idx, the message committed in the core proof at index <tt>idx</tt>, satisfies <tt>l &lt;= m_idx &lt; u</tt>.</t>
<t><tt>l &lt; u</tt>, <tt>u - l &gt;= 2</tt>, and <tt>u - l &lt;= 2^64</tt> MUST hold. The <tt>2^64</tt> ceiling accommodates NumericDate values (Section 4.1 of <xref target="RFC7519"/>). The lower bound rules out single-value ranges, for which the construction is degenerate. Implementations MUST parse <tt>l</tt> and <tt>u</tt> as bigints. A deployment profile MAY permit a larger width.</t>
<t>The construction operates in BLS12-381 G1 against <tt>C_idx</tt> and follows the sigma-protocol range proof of Section 5.5 of <xref target="I-D.ietf-privacypass-arc-crypto"/>:</t>

<ul spacing="compact">
<li>Let <tt>k</tt> and <tt>(base[0], ..., base[k-1])</tt> be the outputs of <tt>ComputeBases(u - l)</tt> (Section 5.5 of <xref target="I-D.ietf-privacypass-arc-crypto"/>). The Holder writes <tt>m_idx - l</tt> as the sum over j in <tt>[0, k-1]</tt> of <tt>b[j] * base[j]</tt>, with each <tt>b[j]</tt> constrained to <tt>{0, 1}</tt>.</li>
<li>For each <tt>j</tt> in <tt>[0, k-1]</tt>, the Holder samples blinding scalars <tt>s[j]</tt> and <tt>s2[j]</tt> and forms the bit commitment <tt>D[j] = b[j] * G + s[j] * H</tt> over <tt>(G, H)</tt> of <xref target="cipher-suite"/>. The Holder then proves, in a single batched Schnorr step, knowledge of <tt>(b[j], s[j], s2[j])</tt> such that <tt>D[j] = b[j] * G + s[j] * H</tt> and <tt>D[j] = b[j] * D[j] + s2[j] * H</tt> (the linearized bit constraint), producing per-bit Schnorr commitments <tt>T1[j]</tt> and <tt>T2[j]</tt> from fresh per-bit random scalars.</li>
<li>The challenge is <tt>c = hash_to_scalar(transcript, challenge_dst)</tt> with <tt>challenge_dst = api_id || "SIGMA_RANGE_CHAL_"</tt> and <tt>hash_to_scalar</tt> the base BBS primitive of <xref target="cipher-suite"/>.</li>
</ul>
<t>[Editor's Note: describe wire format of proof]</t>
</section>

<section anchor="equality-proof"><name>Equality Proof Sub-Proof</name>

<dl spacing="compact">
<dt>Algorithm identifier:</dt>
<dd><tt>schnorr-eq</tt></dd>
</dl>
<t>Inputs (beyond the base sub-proof fields):</t>

<ul spacing="compact">
<li><tt>i</tt>: a single-element array <tt>[idx]</tt>.</li>
<li><tt>c_ext</tt>: a base64url-encoded BLS12-381 G1 point.</li>
</ul>
<t>The sub-proof attests that <tt>C_idx</tt> (from the core proof) and <tt>c_ext</tt> open to the same scalar under the generators <tt>(G, H)</tt> of <xref target="cipher-suite"/>. Cross-group equality is out of scope.</t>
<t>The construction is a 3-DL Schnorr discrete-logarithm-equality (DLEQ) proof over BLS12-381 G1 with <tt>(G, H)</tt>, with witness <tt>(m, s_1, s_2)</tt> such that:</t>

<artwork><![CDATA[C_idx = m * G + s_1 * H
c_ext = m * G + s_2 * H
]]>
</artwork>
<t>The Holder samples fresh random scalars <tt>(r_m, r_s1, r_s2)</tt> and computes Schnorr commitments <tt>T_1 = r_m * G + r_s1 * H</tt> and <tt>T_2 = r_m * G + r_s2 * H</tt>. The challenge is <tt>c = hash_to_scalar(transcript, challenge_dst)</tt> with <tt>challenge_dst = api_id || "SCHNORR_EQ_CHAL_"</tt> and <tt>hash_to_scalar</tt> the base BBS primitive of <xref target="cipher-suite"/>.</t>
<t>[Editor's Note: describe wire format of proof]</t>
</section>
</section>

<section anchor="example-presentation"><name>Example Presentation</name>
<t>Continuing the example of <xref target="example-issuer-header"/>, a Verifier requests <tt>family_name</tt> and asks the Holder to prove <tt>exp</tt> is in the future without disclosing it. The Presentation Header:</t>

<sourcecode type="json"><![CDATA[{
  "nonce": "f4Oa3wT0r8m2Vn1pQ7sKdA",
  "aud": "https://verifier.example.com"
}
]]>
</sourcecode>
<t>The Holder marks index 1 (<tt>family_name</tt>) as <tt>DISCLOSE</tt>, index 13 (<tt>exp</tt>) as <tt>COMMIT</tt>, and the rest as <tt>HIDE</tt>. The core proof then carries a fresh Pedersen commitment to m_13. The Holder attaches a <tt>sigma-range</tt> sub-proof over index 13 proving <tt>now &lt;= exp &lt; 2^63</tt> (with <tt>now = 1779926400</tt>):</t>

<sourcecode type="json"><![CDATA[{
  "alg": "sigma-range",
  "input": { "i": [13], "l": 1779926400, "u": 9223372036854775808 },
  "proof": "..."
}
]]>
</sourcecode>
<t>The Compact Serialization concatenates with <tt>.</tt>: Presentation Header, Issuer Header, Presentation Payloads, Presentation Proof. The disclosed <tt>family_name</tt> at index 1 is the only populated payload and the other thirteen slots are empty:</t>

<artwork><![CDATA[<base64url(Presentation Header)>
.
<base64url(Issuer Header)>
.
~TXVzdGVybWFubg~~~~~~~~~~~~
.
<core proof>~<sigma-range sub-proof>
]]>
</artwork>
<t>The Verifier verifies the core proof, recovers <tt>C_13</tt>, and checks the sub-proof against it. It learns <tt>family_name</tt> and that the credential has not expired.</t>
</section>

<section anchor="reconstructed-payload"><name>Reconstructed JSON Payload</name>
<t>After verifying the core proof and any sub-proofs, the Verifier SHOULD convey to the application a JSON object reconstructed from the disclosed information, analogous to the Processed SD-JWT Payload of <xref target="RFC9901"/>:</t>

<ol spacing="compact">
<li>Start from <tt>{ "vct": &lt;vct from Issuer Header&gt; }</tt>.</li>
<li>Walk <tt>claims</tt>. For each leaf at a disclosed index <tt>i</tt>, set its value from the corresponding Presentation Payload (per <xref target="message-derivation"/>), except when the payload octets are byte-equal to the decoy octets for that leaf's <tt>scalar</tt> flag (see <xref target="decoys"/>), in which case omit the leaf. Hidden and committed-but-not-disclosed leaves are omitted.</li>
<li>Preserve the object and array structure of <tt>claims</tt> for surviving leaves. Array entries that were omitted do not appear, so reconstructed array indices may differ from those in the <tt>claims</tt> annotations.</li>
</ol>
<t>Predicates established by sub-proofs are not represented as leaf values. The reconstruction procedure MUST NOT populate values for hidden or committed-but-not-disclosed leaves.</t>
<t>For <xref target="example-presentation"/>, the reconstructed payload is:</t>

<sourcecode type="json"><![CDATA[{
  "vct": "https://credentials.example.com/identity_credential",
  "family_name": "Mustermann"
}
]]>
</sourcecode>
</section>
</section>

<section anchor="cipher-suite"><name>Cipher Suite</name>
<t>This profile fixes exactly one cipher suite, so that <tt>alg</tt> does not vary across a credential population and split its anonymity set (see <xref target="anonymity"/>).</t>

<section anchor="identifier"><name>Identifier</name>
<t>JPA Algorithm JSON Label: <tt>BBS-MOD</tt>.</t>
<t>Cipher suite identifier (also used as <tt>api_id</tt> for hash-to-scalar, generator derivation, and sub-proof domain separation):</t>

<artwork><![CDATA[BBS-MOD_BLS12381G1_XMD:SHA-256_SSWU_RO_BLIND_H2G_HM2S_
]]>
</artwork>
<t>The <tt>BBS-MOD_</tt> prefix separates this profile from both the base BBS JPA (<tt>BBS</tt> of Section 9.1.2.4 of <xref target="I-D.ietf-jose-json-proof-algorithms"/>) and the base blind BBS Interface (<tt>BBS_BLS12381G1_XMD:SHA-256_SSWU_RO_BLIND_H2G_HM2S_</tt>). This profile adds committed-message proof generation to that Interface. It also bypasses hash-to-scalar on a per-message basis under the <tt>scalar</tt> flag and attaches sub-proofs as described in <xref target="sub-proofs"/>.</t>
</section>

<section anchor="parameters"><name>Parameters</name>

<ul spacing="compact">
<li><strong>Curve / group</strong>: BLS12-381, G1 subgroup.</li>
<li><strong>Underlying BBS ciphersuite</strong>: <tt>BLS12-381-SHA-256</tt> (Section 7.2.2 of <xref target="I-D.irtf-cfrg-bbs-signatures"/>) with hash-to-curve SHA-256 SSWU random oracle <xref target="RFC9380"/>.</li>
<li><strong>Hash-to-scalar</strong>: as in the underlying BBS ciphersuite, with domain separation derived from <tt>api_id</tt>.</li>
<li><strong>Core proof operations</strong>: <tt>CoreProofGen</tt> / <tt>CoreProofVerify</tt> of <xref target="I-D.irtf-cfrg-bbs-blind-signatures"/> invoked directly (not via <tt>BlindProofGen</tt>), so implementations MUST apply the input validity checks of Section 7.1 of that document.</li>
<li><strong>Pedersen commitment generators</strong>: <tt>(G, H) = (Y_1, Y_0)</tt> where <tt>(Y_0, Y_1) = BBS.create_generators(2, "COM_DIS_" || api_id)</tt>. Every committed-index commitment has the form <tt>C_i = m_i * G + s_i * H</tt> with <tt>s_i</tt> sampled per presentation by <tt>CoreProofGen</tt>.</li>
<li><strong>Per-message hash-to-scalar bypass</strong>: governed by each leaf's <tt>scalar</tt> flag (see <xref target="claims-mapping"/>).</li>
</ul>
<t>The base BBS <tt>KeyGen</tt>, <tt>Sign</tt>, and <tt>Verify</tt> operations defined by this document use the BBS ciphersuite identifier <tt>BBS-MOD_BLS12381G1_XMD:SHA-256_SSWU_RO_</tt>. The BBS draft's default <tt>api_id = ciphersuite_id || "H2G_HM2S_"</tt> is not used. All base-BBS operations are parameterized by the <tt>api_id</tt> defined above (carrying the <tt>BLIND_H2G_HM2S_</tt> suffix).</t>
</section>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>

<section anchor="random-number-generation"><name>Random Number Generation</name>
<t>All randomness used by this document MUST be generated using a cryptographically secure random number generator. Reuse or predictability of a blinding scalar or proof nonce can break unlinkability or soundness, or even leak the signing key. ECDSA implementations SHOULD use deterministic nonces per <xref target="RFC6979"/>.</t>
</section>

<section anchor="hash-to-scalar-bypass"><name>Hash-to-Scalar Bypass</name>
<t>[Editor's Note: TODO - Check what exactly the attack scenarios are / if there are some]</t>
</section>
</section>

<section anchor="privacy-considerations"><name>Privacy Considerations</name>

<section anchor="anonymity"><name>Issuer Header Correlation</name>
<t>The Issuer Header is sent in clear to the Verifier. Any variation in it across Holders of the same <tt>vct</tt> narrows the anonymity set.</t>
<t>Implementations SHOULD make the Issuer Header byte-identical across the entire population of a <tt>vct</tt>, by:</t>

<ul spacing="compact">
<li>Fixing the <tt>claims</tt> layout (including all optional attributes and maximum-length array slots) with a constant serialization.</li>
<li>Filling unused slots with decoys per <xref target="decoys"/>.</li>
<li>Carrying per-credential metadata (issuance time, expiry, identifiers) as messages in the message vector</li>
</ul>
</section>

<section anchor="cipher-suite-and-algorithm-identifiers"><name>Cipher Suite and Algorithm Identifiers</name>
<t><tt>alg</tt> and <tt>kb</tt> likewise split the anonymity set when they vary across the population of a <tt>vct</tt>. Implementations SHOULD use a single <tt>alg</tt> and a single <tt>kb</tt> value (or omit <tt>kb</tt> entirely) across all credentials of a <tt>vct</tt>, and SHOULD NOT mix device-bound and non-device-bound credentials under the same <tt>vct</tt>.</t>
</section>
</section>

<section anchor="iana"><name>IANA Considerations</name>
<t>This document requests the following registrations and registry creations.</t>

<section anchor="jpa-alg-value"><name>JPA <tt>alg</tt> Value</name>
<t>IANA is requested to register the following JSON Proof Algorithm in the "JSON Web Proof Algorithms" registry established by <xref target="I-D.ietf-jose-json-proof-algorithms"/>:</t>

<ul spacing="compact">
<li>Algorithm Name: BBS-MOD using SHA-256</li>
<li>Algorithm JSON Label: <tt>BBS-MOD</tt></li>
<li>Algorithm CBOR Label: (to be assigned by IANA)</li>
<li>Algorithm Description: Blind BBS over BLS12-381 with <tt>CoreProofGen</tt>-based committed-message proofs, the per-message <tt>scalar</tt> flag, and the sub-proof attachment mechanism of <xref target="sub-proofs"/>. Cipher suite identifier <tt>BBS-MOD_BLS12381G1_XMD:SHA-256_SSWU_RO_BLIND_H2G_HM2S_</tt>.</li>
<li>Algorithm Usage Location(s): Issued, Presented</li>
<li>JWP Implementation Requirements: Optional</li>
<li>Change Controller: IETF</li>
<li>Specification Document(s): <xref target="cipher-suite"/> of this document.</li>
<li>Algorithm Analysis Document(s): <xref target="LSZ25"/>, <xref target="CT25"/></li>
</ul>
</section>

<section anchor="header-parameter-registrations"><name>Header Parameter Registrations</name>
<t>IANA is requested to register the following Header Parameters in the "JSON Web Proof Header Parameters" registry established by <xref target="I-D.ietf-jose-json-web-proof"/>:</t>

<ul>
<li>Header Parameter Name: <tt>claims</tt></li>
<li>Header Parameter Description: Mapping from credential attribute names to their position in the BBS message vector and whether each is hashed to a scalar or supplied directly as a scalar.</li>
<li>Header Parameter Usage Location(s): Issued, Presented</li>
<li>Change Controller: IETF</li>
<li><t>Specification Document(s): <xref target="claims-mapping"/> of this document.</t>
</li>
<li><t>Header Parameter Name: <tt>kb</tt></t>
</li>
<li><t>Header Parameter Description: Identifier for the device public-key type and its encoding layout in the BBS message vector.</t>
</li>
<li><t>Header Parameter Usage Location(s): Issued, Presented</t>
</li>
<li><t>Change Controller: IETF</t>
</li>
<li><t>Specification Document(s): <xref target="device-binding-header"/> of this document.</t>
</li>
</ul>
</section>

<section anchor="sub-proof-algorithms-registry"><name>Sub-Proof Algorithms Registry</name>
<t>IANA is requested to create a new "Sub-Proof Algorithms" registry.</t>
<t>Allocation policy: Specification Required (<xref target="RFC8126"/>). Designated experts SHOULD verify that each entry pins its underlying group, generators, transcript hash, and Fiat-Shamir domain separation, and that the sub-proof is bound to a commitment attested by the core proof per <xref target="sub-proofs"/>.</t>
<t>Registry fields: Identifier (the <tt>alg</tt> value of a sub-proof object), Description, Reference, Change Controller.</t>
<t>Initial entries:</t>

<ul>
<li>Identifier: <tt>ecdsa-p256-db</tt></li>
<li>Description: ECDSA P-256 device-binding sub-proof.</li>
<li>Reference: This document, <xref target="ecdsa-db"/>.</li>
<li><t>Change Controller: IETF.</t>
</li>
<li><t>Identifier: <tt>sigma-range</tt></t>
</li>
<li><t>Description: Sigma-protocol range proof over a committed scalar message.</t>
</li>
<li><t>Reference: This document, <xref target="range-proof"/>.</t>
</li>
<li><t>Change Controller: IETF.</t>
</li>
<li><t>Identifier: <tt>schnorr-eq</tt></t>
</li>
<li><t>Description: Schnorr proof of equality between a committed message and an external commitment.</t>
</li>
<li><t>Reference: This document, <xref target="equality-proof"/>.</t>
</li>
<li><t>Change Controller: IETF.</t>
</li>
</ul>
</section>
</section>

</middle>

<back>
<references><name>References</name>
<references><name>Normative References</name>
<reference anchor="FIPS186-5" target="https://doi.org/10.6028/NIST.FIPS.186-5">
  <front>
    <title>Digital Signature Standard (DSS)</title>
    <author>
      <organization>National Institute of Standards and Technology</organization>
    </author>
    <date year="2023" month="February"/>
  </front>
  <seriesInfo name="FIPS PUB" value="186-5"/>
  <seriesInfo name="DOI" value="10.6028/NIST.FIPS.186-5"/>
</reference>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-jose-json-proof-algorithms.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-jose-json-web-proof.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-oauth-sd-jwt-vc.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-privacypass-arc-crypto.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.irtf-cfrg-bbs-blind-signatures.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.irtf-cfrg-bbs-signatures.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7519.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9380.xml"/>
</references>
<references><name>Informative References</name>
<reference anchor="CT25" target="https://eprint.iacr.org/2025/1093.pdf">
  <front>
    <title>On the Concrete Security of BBS/BBS+ Signatures</title>
    <author initials="R." surname="Chairattana-Apirom"/>
    <author initials="S." surname="Tessaro"/>
    <date year="2025"/>
  </front>
</reference>
<reference anchor="LSZ25" target="https://eprint.iacr.org/2025/1981.pdf">
  <front>
    <title>Vision: A Modular Framework for Anonymous Credential Systems</title>
    <author initials="A." surname="Lehmann"/>
    <author initials="A." surname="Sidorenko"/>
    <author initials="A." surname="Zacharakis"/>
    <date year="2025"/>
  </front>
  <seriesInfo name="IACR ePrint" value="2025/1981"/>
</reference>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6979.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9901.xml"/>
<reference anchor="TS14" target="https://github.com/eu-digital-identity-wallet/eudi-doc-standards-and-technical-specifications/blob/main/docs/technical-specifications/ts14-zkps-from-mms.md">
  <front>
    <title>Specification for the implementation of Zero-Knowledge Proofs based on multi-message signatures in the EUDI Wallet (TS-14)</title>
    <author>
      <organization>European Commission, EUDI Wallet Expert Group</organization>
    </author>
    <date year="2025"/>
  </front>
  <seriesInfo name="EUDI" value="TS-14"/>
  <refcontent>Work in Progress.</refcontent>
</reference>
</references>
</references>

<section anchor="acknowledgments"><name>Acknowledgments</name>
<t>This document rests on the work captured in <xref target="TS14"/> by the EUDI Wallet expert group. The committed-message core proof builds on <xref target="I-D.irtf-cfrg-bbs-blind-signatures"/>, and the modular committed-disclosure framework draws on <xref target="LSZ25"/>.</t>
</section>

<section anchor="document-history"><name>Document History</name>
<t>[[ pre Working Group Adoption: ]]</t>
<t>-00</t>

<ul spacing="compact">
<li>Initial Version</li>
</ul>
</section>

</back>

</rfc>
