Skip to content

Fail-Closed Bitstring Status Lists v1.0

Credential revocation and suspension are evaluated using W3C Bitstring Status List v1.0 (BitstringStatusListEntry) or legacy StatusList2021 (StatusList2021Entry).

Credential Subject Status Pointer:
{
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "131075",
"statusListCredential": "https://issuer.example/status/revocation-2026.json"
}
│
▼ (Hardened HTTPS fetch through SafeHttpClient)
Status List Credential:
├── Verify Credential Proof (eddsa-jcs-2022 or VC-JOSE)
├── Validate Issuer (MUST equal credential issuer)
├── Decompress Gzip Bitstring (capped at 16 MiB)
├── Check Minimum Size (MUST be ≥ 131,072 bits)
└── Read Bit at index 131075:
Bit = 0 ──► ACTIVE (Valid)
Bit = 1 ──► SET (Revoked / Suspended)

  1. Wire Transfer Limit: The HTTP request for the status list credential enforces MAX_STATUS_LIST_BYTES = 1_048_576 (1 MiB).
  2. Decompression Bomb Defense: Bitstrings are GZIP-compressed and base64url encoded. Decompression via flate2::read::GzDecoder enforces a strict reading ceiling:
    const MAX_DECOMPRESSED_BITS_BYTES: u64 = 16 * 1024 * 1024; // 16 MiB
    GzDecoder::new(compressed.as_slice())
    .take(MAX_DECOMPRESSED_BITS_BYTES + 1)
    .read_to_end(&mut out)
    If decompressed output exceeds 16 MiB, processing aborts immediately with a decompression bomb error.
  3. Minimum Bitstring Length: To prevent privacy reduction via micro-lists, a decompressed bitstring MUST contain at least 16 KiB ($16,384 \times 8 = 131,072$ bits):
    if bits.len() < 16 * 1024 {
    ev.detail = "status list contains fewer than 131072 single-bit entries (STATUS_LIST_LENGTH_ERROR); fail-closed".into();
    return ev;
    }
  4. Encoding Constraints:
    • For BitstringStatusListEntry, encodedList MUST use multibase base64url encoding (prefix 'u').
    • statusSize MUST equal 1 (single-bit semantics). Multi-bit sizes or custom status messages return UNSUPPORTED.
    • statusListIndex MUST be a non-negative string integer.

4.3 Same-Issuer Authority & Fail-Closed Rules

Section titled “4.3 Same-Issuer Authority & Fail-Closed Rules”
  1. Same-Issuer Authorization Policy: The entity issuing the status list credential MUST match the issuer of the credential being evaluated: $$\text{status_list_vc.issuer} \equiv \text{credential.issuer}$$ Delegated third-party status lists are not permitted and evaluate fail-closed.
  2. Fail-Closed Invariant: If any of the following occur, status evaluation yields INDETERMINATE, preventing validation:
    • Network failure or timeout while fetching the status list.
    • Status list signature verification failure.
    • Status list expiration or invalid validity window.
    • statusListIndex out of bounds ($\text{index} \ge \text{bits.len()} \times 8$).
    • Mismatched statusPurpose (e.g. entry declared "revocation", list declares "suspension").