@4sure-tech/vc-bitstring-status-lists
Version:
TypeScript library for W3C Bitstring Status List v1.0 specification - privacy-preserving credential status management
363 lines (355 loc) • 12.9 kB
text/typescript
/**
* BitManager - Low-level bitstring manipulation for W3C Bitstring Status Lists
*
* Manages a packed bitstring where credentials are mapped to bit positions.
* Each credential gets a fixed-width status entry at position: credentialIndex * statusSize.
*
* Features:
* - Direct bit access without entry tracking
* - Automatic buffer expansion in 16KB blocks
* - MSB-first bit ordering within bytes
* - Zero-initialized status values
*
* @example
* ```typescript
* const manager = new BitManager({ statusSize: 2 })
* manager.setStatus(0, 3) // Sets 2 bits at position 0
* console.log(manager.getStatus(0)) // Returns 3
* console.log(manager.getStatus(1)) // Returns 0 (unset)
* ```
*/
declare class BitManager {
private bits;
private readonly statusSize;
/**
* Creates a new BitManager instance
*
* @param options.statusSize - Bits per credential status (default: 1, max: 31)
* @param options.buffer - Existing buffer for decoding
* @param options.initialSize - Initial buffer size in bytes (default: 16KB)
*/
constructor(options?: {
statusSize?: number;
buffer?: Uint8Array;
initialSize?: number;
});
/**
* Gets the status value for a credential
*
* @param credentialIndex - Non-negative credential identifier
* @returns Status value (0 to 2^statusSize - 1)
*/
getStatus(credentialIndex: number): number;
/**
* Sets the status value for a credential
*
* @param credentialIndex - Non-negative credential identifier
* @param status - Status value (0 to 2^statusSize - 1)
* @throws {StatusRangeError} If status exceeds maximum value for statusSize
*/
setStatus(credentialIndex: number, status: number): void;
/**
* Returns current buffer trimmed to actual data size
*
* @returns Copy of buffer containing only written data
*/
toBuffer(): Uint8Array;
/**
* Gets the uniform status size for all entries
*
* @returns Number of bits per status entry
*/
getStatusSize(): number;
/**
* Gets the total buffer size in bytes
*
* @returns Buffer size in bytes
*/
getBufferLength(): number;
/**
* Reads status bits from buffer starting at bit position
*
* @param startBit - Starting bit position
* @returns Decoded status value
*/
private readStatusBits;
/**
* Writes status bits to buffer starting at bit position
*
* @param startBit - Starting bit position
* @param status - Status value to write
*/
private writeStatusBits;
/**
* Ensures buffer can hold the specified number of bytes
* Grows in bitstring-sized chunks for better memory efficiency
*
* @param requiredBytes - Minimum bytes needed
*/
private ensureBufferCanHold;
}
/**
* StatusList - High-level W3C Bitstring Status List implementation
*
* Provides a complete implementation of the W3C Bitstring Status List v1.0 specification.
* Manages a compressed bitstring where each credential has a uniform-width status entry.
*
* Features:
* - W3C compliant 16KB minimum bitstring size
* - GZIP compression with multibase encoding (u-prefix)
* - Uniform status size for all entries in a list
* - Direct credential access without explicit entry creation
* - Efficient ISIZE-based length calculation
*
* @example
* ```typescript
* // Create a status list for revocation (1-bit per credential)
* const list = new StatusList({ statusSize: 1 })
* list.setStatus(42, 1) // Mark credential 42 as revoked
*
* const encoded = await list.encode() // Get compressed, encoded string
* const decoded = await StatusList.decode({ encodedList: encoded, statusSize: 1 })
* console.log(decoded.getStatus(42)) // Returns 1
* ```
*/
declare class BitstreamStatusList {
private readonly bitManager;
private readonly statusSize;
/**
* Creates a new StatusList instance
*
* @param options.buffer - Existing bitstring buffer for decoding (uncompressed)
* @param options.initialSize - Initial buffer size in bytes (default: 16KB)
* @param options.statusSize - Uniform bit width for all entries (default: 1)
*/
constructor(options?: {
buffer?: Uint8Array;
initialSize?: number;
statusSize?: number;
});
/**
* Gets the status value for a credential
*
* @param credentialIndex - Credential identifier
* @returns Status value (0 to 2^statusSize - 1)
*/
getStatus(credentialIndex: number): number;
/**
* Sets the status value for a credential
*
* @param credentialIndex - Credential identifier
* @param status - Status value (0 to 2^statusSize - 1)
*/
setStatus(credentialIndex: number, status: number): void;
/**
* Returns the uniform status size (bit width) for all entries
*/
getStatusSize(): number;
/**
* Encodes the status list into a W3C compliant compressed string
*
* Process:
* 1. Get current bitstring buffer
* 2. Pad to minimum 16KB (W3C requirement)
* 3. GZIP compress the padded buffer
* 4. Base64url encode with 'u' prefix (multibase)
*
* @returns Promise resolving to u-prefixed compressed string
*/
encode(): Promise<string>;
/**
* Decodes a W3C compliant status list string into a StatusList instance
*
* @param options.encodedList - u-prefixed, gzip-compressed base64url string
* @param options.statusSize - Uniform bit width used during encoding (default: 1)
* @returns Promise resolving to new StatusList instance
* @throws {MalformedValueError} If format is invalid
* @throws {StatusListLengthError} If size requirements not met
*/
static decode(options: {
encodedList: string;
statusSize?: number;
}): Promise<BitstreamStatusList>;
/**
* Gets the maximum number of entries this decoded status list can hold
*
* @returns Maximum number of entries based on current buffer size
*/
getLength(): number;
/**
* Efficiently calculates the maximum number of entries in an encoded status list
* Uses GZIP ISIZE field to determine uncompressed size without full decompression
*
* @param encodedList - u-prefixed, gzip-compressed base64url string
* @param statusSize - Uniform bit width used during encoding
* @returns Maximum number of entries (uncompressed_bits / statusSize)
* @throws {MalformedValueError} If format is invalid
*/
static getStatusListLength(encodedList: string, statusSize: number): number;
/**
* Pads buffer to W3C minimum size requirement (16KB)
*
* @param buffer - Source buffer to pad
* @returns Padded buffer (original if already >= 16KB)
*/
private padToMinimumSize;
}
/**
* Central type definitions for the Bitstring Status List library
* Based on W3C Bitstring Status List v1.0 specification
*/
type BitstringStatusPurpose = 'revocation' | 'suspension' | 'refresh' | 'message' | string;
interface BitstringStatusListEntry {
id?: string;
type: 'BitstringStatusListEntry';
statusPurpose: 'revocation' | 'suspension' | 'message' | string;
statusListIndex: string;
statusListCredential: string;
statusSize?: number;
statusMessage?: StatusMessage[];
statusReference?: string | string[];
}
interface BitstringStatusListCredentialSubject {
id: string;
type: 'BitstringStatusList';
statusPurpose: 'revocation' | 'suspension' | 'message' | string | string[];
encodedList: string;
ttl?: number;
}
type AdditionalClaims = Record<string, any>;
type BitstringStatusListCredentialUnsigned = AdditionalClaims & {
'@context': string[];
id: string;
issuer: string | IIssuer;
type: string[];
credentialSubject: BitstringStatusListCredentialSubject;
validFrom?: string;
validUntil?: string;
};
interface IIssuer {
id: string;
[x: string]: any;
}
type CredentialStatus = BitstringStatusListEntry | BitstringStatusListEntry[];
interface CredentialWithStatus {
'@context': string[];
id: string;
type: string[];
issuer: string | IIssuer;
validFrom?: string;
validUntil?: string;
credentialStatus?: CredentialStatus;
credentialSubject: {
id: string;
type: string;
[key: string]: any;
};
}
interface CheckStatusOptions {
credential: CredentialWithStatus;
getStatusListCredential: (url: string) => Promise<BitstringStatusListCredentialUnsigned>;
}
interface VerificationResult {
verified: boolean;
status: number;
statusMessage?: StatusMessage;
error?: Error;
}
interface StatusMessage {
id: string;
message: string;
}
/**
* High-level credential creation functions for W3C Bitstring Status Lists
*
* Provides convenient functions to create compliant BitstringStatusListCredentials
* according to the W3C Bitstring Status List v1.0 specification.
*/
/**
* Creates a W3C compliant BitstringStatusListCredential with an empty status list
*
* The created credential contains an empty status list that can be referenced by
* other credentials through their credentialStatus.statusListCredential property.
* Individual credential statuses are managed separately by updating the status list
* and republishing the credential.
*
* @example
* ```typescript
* // Create a revocation list for single-bit status (revoked/not revoked)
* const credential = await createStatusListCredential({
* id: 'https://issuer.example/status/1',
* issuer: 'https://issuer.example',
* statusPurpose: 'revocation'
* })
*
* // Create a message list with 4-bit status codes
* const messageList = await createStatusListCredential({
* id: 'https://issuer.example/status/messages',
* issuer: { id: 'https://issuer.example', name: 'Example Issuer' },
* statusPurpose: 'message',
* statusSize: 4,
* validUntil: new Date('2025-12-31')
* })
* ```
*
* @param options.id - Unique identifier for the status list credential
* @param options.issuer - Issuer identifier (string) or issuer object with id
* @param options.statusSize - Uniform bit width for status entries (default: 1)
* @param options.statusPurpose - Purpose(s) of the status list (e.g., 'revocation', 'suspension')
* @param options.validFrom - Optional start of validity period
* @param options.validUntil - Optional end of validity period
* @param options.ttl - Optional time-to-live in milliseconds
* @returns Promise resolving to unsigned BitstringStatusListCredential
*/
declare function createStatusListCredential(options: {
id: string;
issuer: string | IIssuer;
statusSize?: number;
statusList?: BitstreamStatusList;
statusPurpose: string | string[];
validFrom?: Date;
validUntil?: Date;
ttl?: number;
}): Promise<BitstringStatusListCredentialUnsigned>;
/**
* W3C Bitstring Status List credential verification logic
*
* Implements the complete W3C Bitstring Status List v1.0 verification algorithm
* including status purpose validation, temporal validity checks, and minimum
* bitstring length requirements.
*/
/**
* Checks the status of a credential against its referenced status list
*
* Implements the W3C Bitstring Status List verification algorithm:
* 1. Validates credential structure and extracts BitstringStatusListEntry
* 2. Retrieves and validates the status list credential
* 3. Checks temporal validity (validFrom/validUntil)
* 4. Validates status purpose matching
* 5. Verifies minimum bitstring length requirements
* 6. Decodes status list and retrieves credential status
* 7. Determines verification result based on status purpose
*
* @example
* ```typescript
* const result = await checkStatus({
* credential: someCredentialWithStatus,
* getStatusListCredential: async (url) => {
* const response = await fetch(url)
* return response.json()
* }
* })
*
* if (result.verified) {
* console.log('Credential is valid')
* } else {
* console.log('Credential failed:', result.error?.message)
* }
* ```
*
* @param options.credential - The credential to check status for
* @param options.getStatusListCredential - Function to retrieve status list credential by URL
* @returns Promise resolving to verification result with status details
*/
declare function checkStatus(options: CheckStatusOptions): Promise<VerificationResult>;
export { type AdditionalClaims, BitManager, BitstreamStatusList, type BitstringStatusListCredentialSubject, type BitstringStatusListCredentialUnsigned, type BitstringStatusListEntry, type BitstringStatusPurpose, type CheckStatusOptions, type CredentialStatus, type CredentialWithStatus, type IIssuer, type StatusMessage, type VerificationResult, checkStatus, createStatusListCredential };