Batch and multi-key issuance
A single Key Attestation can attest many keys at once. This is what makes batch issuance possible: the Issuer can mint several copies of a credential, each bound to a different attested key, so the wallet can present a fresh key per transaction (better unlinkability) without a new attestation round trip each time.
Two numbers govern what happens:
- N, the number of keys the KA attests.
batch_size, the cap the Issuer applies (ETSI TS 119 472-3credential_reuse_policy.options.batch_size).
The Issuer binds min(N, batch_size) keys. Any attested keys beyond that are wasted, because the KA is single-use.
With a Key Attestation, the batch is driven by the attested_keys array, not by the number of proofs. A single JWT proof carries the KA, and the Issuer SHOULD issue one credential per key in attested_keys, capped by batch_size (OpenID4VCI v1.0 Appendix F.1; ยง14.6 sets the credential count "regardless of number of proofs/keys" in the request).
So OpenID4VCI and TS3 are not "N proofs vs one proof" here. Both send a single proof and produce the batch from the KA. The genuine difference is how TS3 profiles that one proof:
- OpenID4VCI signs the proof with one of the attested keys (identified by
kid); the KA binds the rest. - TS3 v1.5 profiles this: the proof MUST be signed by
attested_keys[0],kidis removed, and the KA is typedkeyattestation+jwt. Its reason for the single signature is user experience (some WSCDs need a user gesture per signature), and it "does not degrade the security" because the Wallet Provider's signature still binds every key to the same WSCD.
OpenID4VCI's N-element proofs array (one proof per key) is its batch path used without a Key Attestation, where each proof independently proves possession of its own key.
The Playground shows all of this live: drag N and batch_size, watch the counters (credentials, WSCD signatures, keys bound) move, and click any KA, proof, credential or Credential Request to read its JSON.
See the full rule-by-rule breakdown on OpenID4VCI vs TS3, and the checks the Issuer runs on How the Issuer verifies.