@openeudi/openid4vp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/index.cjs +430 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -7
- package/dist/index.d.ts +22 -7
- package/dist/index.js +431 -122
- package/dist/index.js.map +1 -1
- package/package.json +7 -18
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/parsers/sd-jwt.parser.ts","../src/parsers/mdoc.parser.ts","../src/authorization.ts","../src/presentation.ts","../src/index.ts"],"names":["bytesEqual","mapToCredentialClaims","uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["export class InvalidSignatureError extends Error {\n constructor(message = 'Credential signature validation failed') {\n super(message);\n this.name = 'InvalidSignatureError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ExpiredCredentialError extends Error {\n constructor(message = 'Credential has expired') {\n super(message);\n this.name = 'ExpiredCredentialError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class UnsupportedFormatError extends Error {\n constructor(format: string) {\n super(`Unsupported credential format: ${format}`);\n this.name = 'UnsupportedFormatError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class MalformedCredentialError extends Error {\n constructor(message = 'Credential structure is malformed') {\n super(message);\n this.name = 'MalformedCredentialError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class NonceValidationError extends Error {\n constructor(message = 'Nonce does not match expected value') {\n super(message);\n this.name = 'NonceValidationError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { splitSdJwt, decodeSdJwt, getClaims } from '@sd-jwt/decode';\nimport { decodeProtectedHeader, jwtVerify, importX509, importJWK } from 'jose';\n\nimport { MalformedCredentialError } from '../errors.js';\nimport type { IssuerInfo } from '../types/issuer.js';\nimport type { CredentialFormat, CredentialClaims, PresentationResult } from '../types/presentation.js';\n\nimport type { ICredentialParser, ParseOptions } from './parser.interface.js';\n\n/**\n * Hasher function signature expected by @sd-jwt/decode.\n * Inlined here to avoid a direct dependency on @sd-jwt/types.\n */\ntype SdJwtHasher = (data: string | ArrayBuffer, alg: string) => Promise<Uint8Array>;\n\nconst DEFAULT_ALLOWED_ALGORITHMS = ['ES256', 'ES384', 'ES512'];\n\n/**\n * SHA-256 hasher implementation using the Web Crypto API.\n * Compatible with the @sd-jwt/decode Hasher signature.\n */\nconst sha256Hasher: SdJwtHasher = async (data: string | ArrayBuffer, _alg: string): Promise<Uint8Array> => {\n const encoder = new TextEncoder();\n const input = typeof data === 'string' ? encoder.encode(data) : data;\n const hashBuffer = await crypto.subtle.digest('SHA-256', input);\n return new Uint8Array(hashBuffer);\n};\n\n// Standard base64 alphabet for decoding x5c certificate entries\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n/**\n * Decodes a standard base64-encoded string into raw bytes.\n * Does not depend on Node.js Buffer or browser atob.\n */\nfunction base64ToBytes(base64: string): Uint8Array<ArrayBuffer> {\n const cleaned = base64.replace(/=+$/, '');\n const byteLength = Math.floor((cleaned.length * 3) / 4);\n const buffer = new ArrayBuffer(byteLength);\n const bytes = new Uint8Array(buffer);\n\n let byteIndex = 0;\n for (let i = 0; i < cleaned.length; i += 4) {\n const a = BASE64_CHARS.indexOf(cleaned[i]);\n const b = i + 1 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 1]) : 0;\n const c = i + 2 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 2]) : 0;\n const d = i + 3 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 3]) : 0;\n\n bytes[byteIndex++] = (a << 2) | (b >> 4);\n if (byteIndex < byteLength) bytes[byteIndex++] = ((b & 0x0f) << 4) | (c >> 2);\n if (byteIndex < byteLength) bytes[byteIndex++] = ((c & 0x03) << 6) | d;\n }\n\n return bytes;\n}\n\n/**\n * Checks whether two Uint8Array instances contain identical bytes.\n */\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/**\n * Converts a base64-encoded DER certificate to PEM format for jose.importX509.\n */\nfunction derToPem(base64Der: string): string {\n const lines = base64Der.match(/.{1,64}/g) || [];\n return `-----BEGIN CERTIFICATE-----\\n${lines.join('\\n')}\\n-----END CERTIFICATE-----`;\n}\n\n/**\n * Encodes a Uint8Array to base64url (no padding).\n * Used by disclosure hash verification (Task 5) and KB-JWT verification (Task 6).\n */\nfunction bytesToBase64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return globalThis.btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Maps raw decoded claims to the CredentialClaims structure,\n * picking known age/residency fields and preserving any extra keys.\n */\nfunction mapToCredentialClaims(raw: Record<string, unknown>): CredentialClaims {\n const claims: CredentialClaims = {};\n\n if (typeof raw['age_over_18'] === 'boolean') {\n claims.age_over_18 = raw['age_over_18'];\n }\n if (typeof raw['age_over_21'] === 'boolean') {\n claims.age_over_21 = raw['age_over_21'];\n }\n if (typeof raw['resident_country'] === 'string') {\n claims.resident_country = raw['resident_country'];\n }\n if (typeof raw['nationality'] === 'string') {\n claims.nationality = raw['nationality'];\n }\n if (typeof raw['family_name_birth'] === 'string') {\n claims.family_name_birth = raw['family_name_birth'];\n }\n\n for (const [key, value] of Object.entries(raw)) {\n if (\n !(key in claims) &&\n !key.startsWith('_sd') &&\n key !== 'iss' &&\n key !== 'exp' &&\n key !== 'iat' &&\n key !== 'cnf' &&\n key !== 'vct'\n ) {\n claims[key] = value;\n }\n }\n\n return claims;\n}\n\n/**\n * Best-effort extraction of a country code hint from an issuer URL or string.\n */\nfunction extractCountryHint(issuer: string): string {\n try {\n const url = new URL(issuer);\n const tld = url.hostname.split('.').pop()?.toUpperCase();\n if (tld && tld.length === 2) {\n return tld;\n }\n } catch {\n // Not a valid URL\n }\n return '';\n}\n\n/**\n * SD-JWT VC credential parser.\n *\n * Decodes and cryptographically validates SD-JWT Verifiable Credentials:\n * - JWT signature verification via x5c public key (jose)\n * - Issuer certificate trust chain verification\n * - Disclosure hash integrity verification\n * - Key binding JWT signature and sd_hash verification\n * - Selective disclosure claim extraction\n */\nexport class SdJwtParser implements ICredentialParser {\n readonly format: CredentialFormat = 'sd-jwt-vc';\n\n canParse(vpToken: unknown): boolean {\n return typeof vpToken === 'string' && vpToken.includes('~');\n }\n\n async parse(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n if (typeof vpToken !== 'string') {\n throw new MalformedCredentialError('VP token must be a string');\n }\n\n const allowedAlgorithms = options.allowedAlgorithms ?? DEFAULT_ALLOWED_ALGORITHMS;\n\n const invalidResult = (error: string): PresentationResult => ({\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error,\n });\n\n // Step 1: Split the SD-JWT into components\n let parts: ReturnType<typeof splitSdJwt>;\n try {\n parts = splitSdJwt(vpToken);\n } catch {\n throw new MalformedCredentialError('Failed to split SD-JWT structure');\n }\n\n // Step 2: Peek at issuer JWT header (need alg and x5c before verification)\n let header: ReturnType<typeof decodeProtectedHeader>;\n try {\n header = decodeProtectedHeader(parts.jwt);\n } catch {\n throw new MalformedCredentialError('Failed to decode SD-JWT issuer JWT header');\n }\n\n // Step 3: Check algorithm against allowlist\n const alg = header.alg;\n if (typeof alg !== 'string' || !allowedAlgorithms.includes(alg)) {\n return invalidResult(`Unsupported algorithm: ${alg}`);\n }\n\n // Step 4: Extract public key from x5c certificate\n const x5cArray = header.x5c;\n if (!Array.isArray(x5cArray) || x5cArray.length === 0 || typeof x5cArray[0] !== 'string') {\n throw new MalformedCredentialError('Missing or invalid x5c in JWT header');\n }\n\n let issuerKey: Awaited<ReturnType<typeof importX509>>;\n let issuerCertBytes: Uint8Array;\n try {\n issuerKey = await importX509(derToPem(x5cArray[0]), alg);\n issuerCertBytes = base64ToBytes(x5cArray[0]);\n } catch (err) {\n if (err instanceof MalformedCredentialError) throw err;\n throw new MalformedCredentialError('Failed to import issuer certificate');\n }\n\n // Step 5: Verify issuer JWT signature (also validates exp, iat via jose)\n let payload: Record<string, unknown>;\n try {\n const result = await jwtVerify(parts.jwt, issuerKey, { algorithms: allowedAlgorithms });\n payload = result.payload as unknown as Record<string, unknown>;\n } catch {\n return invalidResult('Issuer JWT signature verification failed');\n }\n\n // Step 6: Trust check — certificate must be in the trusted set\n const issuerString = typeof payload['iss'] === 'string' ? payload['iss'] : '';\n const issuerInfo: IssuerInfo = {\n certificate: issuerCertBytes,\n country: extractCountryHint(issuerString),\n };\n\n if (options.trustedCertificates.length > 0) {\n const isTrusted = options.trustedCertificates.some((trusted) => bytesEqual(trusted, issuerCertBytes));\n if (!isTrusted) {\n return invalidResult('Issuer certificate is not trusted');\n }\n }\n\n // Step 7: Verify disclosure hashes against _sd array\n const sdArray = payload['_sd'];\n if (parts.disclosures.length > 0) {\n if (!Array.isArray(sdArray) || sdArray.length === 0) {\n return invalidResult('Disclosures present but no _sd array in issuer JWT');\n }\n for (const disclosure of parts.disclosures) {\n const hashBytes = await sha256Hasher(disclosure, 'sha-256');\n const hashB64url = bytesToBase64url(hashBytes);\n if (!sdArray.includes(hashB64url)) {\n return invalidResult('Disclosure hash mismatch');\n }\n }\n }\n\n // Step 8: Verify key binding JWT (if present)\n if (parts.kbJwt) {\n // Extract holder public key from cnf claim\n const cnf = payload['cnf'] as Record<string, unknown> | undefined;\n if (!cnf || typeof cnf !== 'object' || !cnf['jwk']) {\n throw new MalformedCredentialError('Missing cnf.jwk in issuer JWT for key binding');\n }\n\n let holderKey: Awaited<ReturnType<typeof importJWK>>;\n try {\n const kbHeader = decodeProtectedHeader(parts.kbJwt);\n const kbAlg = kbHeader.alg;\n if (typeof kbAlg !== 'string' || !allowedAlgorithms.includes(kbAlg)) {\n return invalidResult(`Unsupported KB-JWT algorithm: ${kbAlg}`);\n }\n holderKey = await importJWK(cnf['jwk'] as Record<string, unknown>, kbAlg);\n } catch (err) {\n if (err instanceof MalformedCredentialError) throw err;\n throw new MalformedCredentialError('Failed to import holder key from cnf.jwk');\n }\n\n // Verify KB-JWT signature\n let kbPayload: Record<string, unknown>;\n try {\n const kbResult = await jwtVerify(parts.kbJwt, holderKey, {\n algorithms: allowedAlgorithms,\n ...(options.audience ? { audience: options.audience } : {}),\n });\n kbPayload = kbResult.payload as unknown as Record<string, unknown>;\n } catch {\n return invalidResult('Key binding JWT signature verification failed');\n }\n\n // Validate nonce — must be present and match when KB-JWT is used\n if (kbPayload['nonce'] !== options.nonce) {\n return invalidResult('Key binding JWT nonce does not match');\n }\n\n // Verify sd_hash — hash of the SD-JWT content before the KB-JWT\n const disclosurePart = parts.disclosures.length > 0 ? parts.disclosures.join('~') + '~' : '';\n const sdJwtForHash = parts.jwt + '~' + disclosurePart;\n const sdHashBytes = await sha256Hasher(sdJwtForHash, 'sha-256');\n const expectedSdHash = bytesToBase64url(sdHashBytes);\n if (kbPayload['sd_hash'] !== expectedSdHash) {\n return invalidResult('Key binding JWT sd_hash does not match');\n }\n }\n\n // Step 9: Decode disclosures and extract claims\n let resolvedClaims: Record<string, unknown>;\n try {\n const decoded = await decodeSdJwt(vpToken, sha256Hasher);\n resolvedClaims = await getClaims<Record<string, unknown>>(\n decoded.jwt.payload,\n decoded.disclosures,\n sha256Hasher\n );\n } catch {\n throw new MalformedCredentialError('Failed to decode SD-JWT disclosures');\n }\n\n return {\n valid: true,\n format: this.format,\n claims: mapToCredentialClaims(resolvedClaims),\n issuer: issuerInfo,\n };\n }\n}\n","import { decode } from 'cbor-x';\n\nimport { MalformedCredentialError } from '../errors.js';\nimport type { IssuerInfo } from '../types/issuer.js';\nimport type { CredentialFormat, CredentialClaims, PresentationResult } from '../types/presentation.js';\n\nimport type { ICredentialParser, ParseOptions } from './parser.interface.js';\n\n/**\n * Runtime check for binary data. Returns true for Uint8Array and Node.js Buffer\n * without referencing the Buffer type (which is unavailable in DOM-only tsconfig).\n * Buffer extends Uint8Array, so `instanceof Uint8Array` catches both.\n */\nfunction isBinaryData(value: unknown): value is Uint8Array {\n return value instanceof Uint8Array;\n}\n\n/**\n * Checks whether two Uint8Array instances contain identical bytes.\n */\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/**\n * Represents a single IssuerSignedItem element from an mDOC nameSpace.\n * ISO 18013-5 Section 8.3.2.1.2.\n */\ninterface IssuerSignedItem {\n digestID: number;\n random: Uint8Array | unknown;\n elementIdentifier: string;\n elementValue: unknown;\n}\n\n/**\n * Simplified DeviceResponse structure from ISO 18013-5.\n * Only the fields required for claim extraction and trust validation.\n */\ninterface MdocDocument {\n docType: string;\n issuerSigned: {\n nameSpaces: Record<string, IssuerSignedItem[]>;\n issuerAuth: unknown[];\n };\n}\n\ninterface DeviceResponse {\n version: string;\n documents: MdocDocument[];\n status: number;\n}\n\n/**\n * Extracts the issuer certificate bytes from a COSE_Sign1 issuerAuth structure.\n *\n * The issuerAuth is a COSE_Sign1 array: [protected, unprotected, payload, signature].\n * The protected header (index 0) is CBOR-encoded and may contain the x5chain (label 33)\n * with the issuer certificate. The unprotected header (index 1) may also carry it.\n *\n * If neither header contains a certificate, the raw protected bytes are returned\n * as a fallback for trust matching (test/simplified scenarios).\n */\nfunction extractCertificateFromIssuerAuth(issuerAuth: unknown[]): Uint8Array {\n // Try unprotected header first (index 1) -- it's already decoded as a Map or object\n const unprotected = issuerAuth[1];\n if (unprotected && typeof unprotected === 'object') {\n // x5chain is COSE header label 33\n const certFromUnprotected = extractX5Chain(unprotected);\n if (certFromUnprotected) return certFromUnprotected;\n }\n\n // Try protected header (index 0) -- CBOR-encoded bytes\n const protectedHeader = issuerAuth[0];\n if (isBinaryData(protectedHeader)) {\n try {\n const decoded = decode(protectedHeader) as unknown;\n if (decoded && typeof decoded === 'object') {\n const certFromProtected = extractX5Chain(decoded);\n if (certFromProtected) return certFromProtected;\n }\n } catch {\n // Protected header could not be decoded -- fall through\n }\n // Return raw protected bytes as fallback identifier\n return new Uint8Array(protectedHeader);\n }\n\n return new Uint8Array();\n}\n\n/**\n * Extracts certificate bytes from an x5chain (label 33) in a COSE header.\n * The header can be a plain object or a Map.\n */\nfunction extractX5Chain(header: unknown): Uint8Array | null {\n if (header instanceof Map) {\n const cert = header.get(33) as unknown;\n if (isBinaryData(cert)) {\n return new Uint8Array(cert);\n }\n } else if (typeof header === 'object' && header !== null) {\n const rec = header as Record<string | number, unknown>;\n const cert = rec[33] ?? rec['x5chain'] ?? rec['33'];\n if (isBinaryData(cert)) {\n return new Uint8Array(cert);\n }\n }\n return null;\n}\n\n/**\n * Maps raw mDOC IssuerSignedItem elements to the CredentialClaims structure,\n * picking known age/residency fields and preserving any additional identifiers.\n */\nfunction mapToCredentialClaims(items: IssuerSignedItem[]): CredentialClaims {\n const claims: CredentialClaims = {};\n\n for (const item of items) {\n const key = item.elementIdentifier;\n const value = item.elementValue;\n\n switch (key) {\n case 'age_over_18':\n if (typeof value === 'boolean') claims.age_over_18 = value;\n break;\n case 'age_over_21':\n if (typeof value === 'boolean') claims.age_over_21 = value;\n break;\n case 'resident_country':\n if (typeof value === 'string') claims.resident_country = value;\n break;\n case 'nationality':\n if (typeof value === 'string') claims.nationality = value;\n break;\n case 'family_name_birth':\n if (typeof value === 'string') claims.family_name_birth = value;\n break;\n default:\n claims[key] = value;\n break;\n }\n }\n\n return claims;\n}\n\n/**\n * Extracts validity period from the issuerAuth payload.\n *\n * The payload (index 2) of the COSE_Sign1 is CBOR-encoded and should\n * contain a MobileSecurityObject with a validityInfo field carrying\n * `validFrom` and `validUntil` dates.\n */\nfunction extractValidityPeriod(issuerAuth: unknown[]): { validFrom?: Date; validUntil?: Date } {\n const payload = issuerAuth[2];\n if (!payload) return {};\n\n try {\n // payload can be raw CBOR bytes or already decoded\n const decoded = isBinaryData(payload) ? (decode(payload) as unknown) : payload;\n\n if (decoded && typeof decoded === 'object') {\n const obj = decoded as Record<string, unknown>;\n const validityInfo = obj['validityInfo'] as Record<string, unknown> | undefined;\n if (validityInfo) {\n return {\n validFrom:\n validityInfo['validFrom'] instanceof Date\n ? validityInfo['validFrom']\n : typeof validityInfo['validFrom'] === 'string'\n ? new Date(validityInfo['validFrom'])\n : undefined,\n validUntil:\n validityInfo['validUntil'] instanceof Date\n ? validityInfo['validUntil']\n : typeof validityInfo['validUntil'] === 'string'\n ? new Date(validityInfo['validUntil'])\n : undefined,\n };\n }\n }\n } catch {\n // Could not decode payload -- validity check will be skipped\n }\n\n return {};\n}\n\n/**\n * mDOC / mDL credential parser.\n *\n * Decodes and validates mDOC (Mobile Document) credentials as specified in\n * ISO 18013-5 and the EUDI Wallet ecosystem. Processes CBOR-encoded\n * DeviceResponse structures containing:\n * - Document type validation (eu.europa.ec.eudi.pid.1)\n * - Issuer certificate trust chain verification via COSE_Sign1 issuerAuth\n * - Validity period checking\n * - Claim extraction from IssuerSignedItem nameSpace elements\n */\nexport class MdocParser implements ICredentialParser {\n readonly format: CredentialFormat = 'mdoc';\n\n /**\n * Returns true when the token is binary data (Uint8Array or Buffer),\n * indicating a CBOR-encoded mDOC DeviceResponse.\n */\n canParse(vpToken: unknown): boolean {\n return isBinaryData(vpToken);\n }\n\n /**\n * Parses and validates an mDOC DeviceResponse token.\n *\n * @throws {MalformedCredentialError} when the CBOR structure cannot be decoded\n * or does not match the expected DeviceResponse format\n */\n async parse(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n if (!isBinaryData(vpToken)) {\n throw new MalformedCredentialError('VP token must be a Uint8Array or Buffer');\n }\n\n const invalidResult = (error: string): PresentationResult => ({\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error,\n });\n\n // Step 1: Decode the CBOR DeviceResponse\n let deviceResponse: DeviceResponse;\n try {\n deviceResponse = decode(vpToken) as DeviceResponse;\n } catch {\n throw new MalformedCredentialError('Failed to decode CBOR DeviceResponse');\n }\n\n // Step 2: Validate basic DeviceResponse structure\n if (\n !deviceResponse ||\n typeof deviceResponse !== 'object' ||\n !Array.isArray(deviceResponse.documents) ||\n deviceResponse.documents.length === 0\n ) {\n throw new MalformedCredentialError('Invalid DeviceResponse structure: missing or empty documents array');\n }\n\n const document = deviceResponse.documents[0];\n if (!document.issuerSigned || !document.issuerSigned.nameSpaces || !document.issuerSigned.issuerAuth) {\n throw new MalformedCredentialError('Invalid mDOC document: missing issuerSigned data');\n }\n\n // Step 3: Extract issuer certificate from COSE_Sign1 issuerAuth\n const issuerAuth = document.issuerSigned.issuerAuth;\n if (!Array.isArray(issuerAuth) || issuerAuth.length < 4) {\n throw new MalformedCredentialError('Invalid issuerAuth: expected COSE_Sign1 array with 4 elements');\n }\n\n const issuerCertBytes = extractCertificateFromIssuerAuth(issuerAuth);\n const issuerInfo: IssuerInfo = {\n certificate: issuerCertBytes,\n country: '',\n };\n\n // Step 4: Verify trust -- certificate must be in the trusted set\n if (options.trustedCertificates.length > 0) {\n const isTrusted = options.trustedCertificates.some((trusted) => bytesEqual(trusted, issuerCertBytes));\n if (!isTrusted) {\n return invalidResult('Issuer certificate is not trusted');\n }\n } else if (issuerCertBytes.length === 0) {\n return invalidResult('No issuer certificate found and no trusted certificates configured');\n }\n\n // Step 5: Check validity period\n const { validUntil } = extractValidityPeriod(issuerAuth);\n if (validUntil) {\n const now = new Date();\n if (validUntil < now) {\n return invalidResult('Credential has expired');\n }\n }\n\n // Step 6: Extract claims from nameSpaces\n // Prefer the EUDI PID namespace, fall back to the first available namespace\n const pidNamespace = 'eu.europa.ec.eudi.pid.1';\n const nameSpaces = document.issuerSigned.nameSpaces;\n const items: IssuerSignedItem[] =\n nameSpaces[pidNamespace] ?? nameSpaces[document.docType] ?? Object.values(nameSpaces)[0] ?? [];\n\n const claims = mapToCredentialClaims(items);\n\n // Try to derive country from resident_country claim\n if (claims.resident_country && typeof claims.resident_country === 'string') {\n issuerInfo.country = claims.resident_country;\n }\n\n return {\n valid: true,\n format: this.format,\n claims,\n issuer: issuerInfo,\n };\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\n\nimport type { AuthorizationRequestInput, AuthorizationRequest } from './types/authorization.js';\n\nexport function createAuthorizationRequest(input: AuthorizationRequestInput): AuthorizationRequest {\n const state = input.state ?? uuidv4();\n\n const presentationDefinition = {\n id: uuidv4(),\n input_descriptors: input.requestedAttributes.map((attr, index) => ({\n id: `descriptor_${index}`,\n format: Object.fromEntries(\n input.acceptedFormats.map((fmt) => {\n if (fmt === 'sd-jwt-vc') return ['vc+sd-jwt', { 'sd-jwt_alg_values': ['ES256'] }];\n return ['mso_mdoc', { alg: ['ES256'] }];\n })\n ),\n constraints: {\n fields: [\n {\n path: [`$.${attr}`, `$['${attr}']`],\n filter: { type: attr.startsWith('age_over') ? 'boolean' : 'string' },\n },\n ],\n },\n })),\n };\n\n const params = new URLSearchParams({\n response_type: 'vp_token',\n response_mode: 'direct_post',\n response_uri: input.responseUri,\n client_id: input.clientId,\n nonce: input.nonce,\n state,\n presentation_definition: JSON.stringify(presentationDefinition),\n });\n\n return {\n uri: `openid4vp://authorize?${params.toString()}`,\n presentationDefinition,\n nonce: input.nonce,\n state,\n };\n}\n","import { MdocParser } from './parsers/mdoc.parser.js';\nimport type { ParseOptions, ICredentialParser } from './parsers/parser.interface.js';\nimport { SdJwtParser } from './parsers/sd-jwt.parser.js';\nimport type { PresentationResult } from './types/presentation.js';\n\nconst parsers: ICredentialParser[] = [new SdJwtParser(), new MdocParser()];\n\nexport async function parsePresentation(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n for (const parser of parsers) {\n if (parser.canParse(vpToken)) {\n return parser.parse(vpToken, options);\n }\n }\n\n return {\n valid: false,\n format: 'sd-jwt-vc',\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error: 'Unsupported credential format',\n };\n}\n\nexport type { ParseOptions } from './parsers/parser.interface.js';\n","export const VERSION = '0.2.0';\n\nexport type {\n CredentialFormat,\n CredentialClaims,\n PresentationResult,\n IssuerInfo,\n AuthorizationRequestInput,\n AuthorizationRequest,\n} from './types/index.js';\n\nexport type { ICredentialParser, ParseOptions } from './parsers/parser.interface.js';\n\nexport { SdJwtParser } from './parsers/sd-jwt.parser.js';\nexport { MdocParser } from './parsers/mdoc.parser.js';\n\nexport {\n InvalidSignatureError,\n ExpiredCredentialError,\n UnsupportedFormatError,\n MalformedCredentialError,\n NonceValidationError,\n} from './errors.js';\n\nexport { createAuthorizationRequest } from './authorization.js';\n\nexport { parsePresentation } from './presentation.js';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/parsers/sd-jwt.parser.ts","../src/crypto/cose-sign1.ts","../src/crypto/digest.ts","../src/crypto/mso.ts","../src/parsers/mdoc.parser.ts","../src/authorization.ts","../src/presentation.ts","../src/index.ts"],"names":["encoder","CborEncoder","decoder","bytesEqual","Tag","DEFAULT_ALLOWED_ALGORITHMS","derToPem","importX509","uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["export class InvalidSignatureError extends Error {\n constructor(message = 'Credential signature validation failed') {\n super(message);\n this.name = 'InvalidSignatureError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ExpiredCredentialError extends Error {\n constructor(message = 'Credential has expired') {\n super(message);\n this.name = 'ExpiredCredentialError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class UnsupportedFormatError extends Error {\n constructor(format: string) {\n super(`Unsupported credential format: ${format}`);\n this.name = 'UnsupportedFormatError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class MalformedCredentialError extends Error {\n constructor(message = 'Credential structure is malformed') {\n super(message);\n this.name = 'MalformedCredentialError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class NonceValidationError extends Error {\n constructor(message = 'Nonce does not match expected value') {\n super(message);\n this.name = 'NonceValidationError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { splitSdJwt, decodeSdJwt, getClaims } from '@sd-jwt/decode';\nimport { decodeProtectedHeader, jwtVerify, importX509, importJWK } from 'jose';\n\nimport { MalformedCredentialError } from '../errors.js';\nimport type { IssuerInfo } from '../types/issuer.js';\nimport type { CredentialFormat, CredentialClaims, PresentationResult } from '../types/presentation.js';\n\nimport type { ICredentialParser, ParseOptions } from './parser.interface.js';\n\n/**\n * Hasher function signature expected by @sd-jwt/decode.\n * Inlined here to avoid a direct dependency on @sd-jwt/types.\n */\ntype SdJwtHasher = (data: string | ArrayBuffer, alg: string) => Promise<Uint8Array>;\n\nconst DEFAULT_ALLOWED_ALGORITHMS = ['ES256', 'ES384', 'ES512'];\n\n/**\n * SHA-256 hasher implementation using the Web Crypto API.\n * Compatible with the @sd-jwt/decode Hasher signature.\n */\nconst sha256Hasher: SdJwtHasher = async (data: string | ArrayBuffer, _alg: string): Promise<Uint8Array> => {\n const encoder = new TextEncoder();\n const input = typeof data === 'string' ? encoder.encode(data) : data;\n const hashBuffer = await crypto.subtle.digest('SHA-256', input);\n return new Uint8Array(hashBuffer);\n};\n\n// Standard base64 alphabet for decoding x5c certificate entries\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n/**\n * Decodes a standard base64-encoded string into raw bytes.\n * Does not depend on Node.js Buffer or browser atob.\n */\nfunction base64ToBytes(base64: string): Uint8Array<ArrayBuffer> {\n const cleaned = base64.replace(/=+$/, '');\n const byteLength = Math.floor((cleaned.length * 3) / 4);\n const buffer = new ArrayBuffer(byteLength);\n const bytes = new Uint8Array(buffer);\n\n let byteIndex = 0;\n for (let i = 0; i < cleaned.length; i += 4) {\n const a = BASE64_CHARS.indexOf(cleaned[i]);\n const b = i + 1 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 1]) : 0;\n const c = i + 2 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 2]) : 0;\n const d = i + 3 < cleaned.length ? BASE64_CHARS.indexOf(cleaned[i + 3]) : 0;\n\n bytes[byteIndex++] = (a << 2) | (b >> 4);\n if (byteIndex < byteLength) bytes[byteIndex++] = ((b & 0x0f) << 4) | (c >> 2);\n if (byteIndex < byteLength) bytes[byteIndex++] = ((c & 0x03) << 6) | d;\n }\n\n return bytes;\n}\n\n/**\n * Checks whether two Uint8Array instances contain identical bytes.\n */\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/**\n * Converts a base64-encoded DER certificate to PEM format for jose.importX509.\n */\nfunction derToPem(base64Der: string): string {\n const lines = base64Der.match(/.{1,64}/g) || [];\n return `-----BEGIN CERTIFICATE-----\\n${lines.join('\\n')}\\n-----END CERTIFICATE-----`;\n}\n\n/**\n * Encodes a Uint8Array to base64url (no padding).\n * Used by disclosure hash verification (Task 5) and KB-JWT verification (Task 6).\n */\nfunction bytesToBase64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return globalThis.btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Maps raw decoded claims to the CredentialClaims structure,\n * picking known age/residency fields and preserving any extra keys.\n */\nfunction mapToCredentialClaims(raw: Record<string, unknown>): CredentialClaims {\n const claims: CredentialClaims = {};\n\n if (typeof raw['age_over_18'] === 'boolean') {\n claims.age_over_18 = raw['age_over_18'];\n }\n if (typeof raw['age_over_21'] === 'boolean') {\n claims.age_over_21 = raw['age_over_21'];\n }\n if (typeof raw['resident_country'] === 'string') {\n claims.resident_country = raw['resident_country'];\n }\n if (typeof raw['nationality'] === 'string') {\n claims.nationality = raw['nationality'];\n }\n if (typeof raw['family_name_birth'] === 'string') {\n claims.family_name_birth = raw['family_name_birth'];\n }\n\n for (const [key, value] of Object.entries(raw)) {\n if (\n !(key in claims) &&\n !key.startsWith('_sd') &&\n key !== 'iss' &&\n key !== 'exp' &&\n key !== 'iat' &&\n key !== 'cnf' &&\n key !== 'vct'\n ) {\n claims[key] = value;\n }\n }\n\n return claims;\n}\n\n/**\n * Best-effort extraction of a country code hint from an issuer URL or string.\n */\nfunction extractCountryHint(issuer: string): string {\n try {\n const url = new URL(issuer);\n const tld = url.hostname.split('.').pop()?.toUpperCase();\n if (tld && tld.length === 2) {\n return tld;\n }\n } catch {\n // Not a valid URL\n }\n return '';\n}\n\n/**\n * SD-JWT VC credential parser.\n *\n * Decodes and cryptographically validates SD-JWT Verifiable Credentials:\n * - JWT signature verification via x5c public key (jose)\n * - Issuer certificate trust chain verification\n * - Disclosure hash integrity verification\n * - Key binding JWT signature and sd_hash verification\n * - Selective disclosure claim extraction\n */\nexport class SdJwtParser implements ICredentialParser {\n readonly format: CredentialFormat = 'sd-jwt-vc';\n\n canParse(vpToken: unknown): boolean {\n return typeof vpToken === 'string' && vpToken.includes('~');\n }\n\n async parse(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n if (typeof vpToken !== 'string') {\n throw new MalformedCredentialError('VP token must be a string');\n }\n\n const allowedAlgorithms = options.allowedAlgorithms ?? DEFAULT_ALLOWED_ALGORITHMS;\n\n const invalidResult = (error: string): PresentationResult => ({\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error,\n });\n\n // Step 1: Split the SD-JWT into components\n let parts: ReturnType<typeof splitSdJwt>;\n try {\n parts = splitSdJwt(vpToken);\n } catch {\n throw new MalformedCredentialError('Failed to split SD-JWT structure');\n }\n\n // Step 2: Peek at issuer JWT header (need alg and x5c before verification)\n let header: ReturnType<typeof decodeProtectedHeader>;\n try {\n header = decodeProtectedHeader(parts.jwt);\n } catch {\n throw new MalformedCredentialError('Failed to decode SD-JWT issuer JWT header');\n }\n\n // Step 3: Check algorithm against allowlist\n const alg = header.alg;\n if (typeof alg !== 'string' || !allowedAlgorithms.includes(alg)) {\n return invalidResult(`Unsupported algorithm: ${alg}`);\n }\n\n // Step 4: Extract public key from x5c certificate\n const x5cArray = header.x5c;\n if (!Array.isArray(x5cArray) || x5cArray.length === 0 || typeof x5cArray[0] !== 'string') {\n throw new MalformedCredentialError('Missing or invalid x5c in JWT header');\n }\n\n let issuerKey: Awaited<ReturnType<typeof importX509>>;\n let issuerCertBytes: Uint8Array;\n try {\n issuerKey = await importX509(derToPem(x5cArray[0]), alg);\n issuerCertBytes = base64ToBytes(x5cArray[0]);\n } catch (err) {\n if (err instanceof MalformedCredentialError) throw err;\n throw new MalformedCredentialError('Failed to import issuer certificate');\n }\n\n // Step 5: Verify issuer JWT signature (also validates exp, iat via jose)\n let payload: Record<string, unknown>;\n try {\n const result = await jwtVerify(parts.jwt, issuerKey, { algorithms: allowedAlgorithms });\n payload = result.payload as unknown as Record<string, unknown>;\n } catch {\n return invalidResult('Issuer JWT signature verification failed');\n }\n\n // Step 6: Trust check — certificate must be in the trusted set\n // unless the caller explicitly opts out via skipTrustCheck.\n const issuerString = typeof payload['iss'] === 'string' ? payload['iss'] : '';\n const issuerInfo: IssuerInfo = {\n certificate: issuerCertBytes,\n country: extractCountryHint(issuerString),\n };\n\n if (options.trustedCertificates.length === 0) {\n if (options.skipTrustCheck !== true) {\n throw new MalformedCredentialError(\n 'trustedCertificates must not be empty unless skipTrustCheck is true'\n );\n }\n } else {\n const isTrusted = options.trustedCertificates.some((trusted) => bytesEqual(trusted, issuerCertBytes));\n if (!isTrusted) {\n return invalidResult('Issuer certificate is not trusted');\n }\n }\n\n // Step 7: Verify disclosure hashes against _sd array\n const sdArray = payload['_sd'];\n if (parts.disclosures.length > 0) {\n if (!Array.isArray(sdArray) || sdArray.length === 0) {\n return invalidResult('Disclosures present but no _sd array in issuer JWT');\n }\n for (const disclosure of parts.disclosures) {\n const hashBytes = await sha256Hasher(disclosure, 'sha-256');\n const hashB64url = bytesToBase64url(hashBytes);\n if (!sdArray.includes(hashB64url)) {\n return invalidResult('Disclosure hash mismatch');\n }\n }\n }\n\n // Step 8: Verify key binding JWT (if present)\n if (parts.kbJwt) {\n // Extract holder public key from cnf claim\n const cnf = payload['cnf'] as Record<string, unknown> | undefined;\n if (!cnf || typeof cnf !== 'object' || !cnf['jwk']) {\n throw new MalformedCredentialError('Missing cnf.jwk in issuer JWT for key binding');\n }\n\n let holderKey: Awaited<ReturnType<typeof importJWK>>;\n try {\n const kbHeader = decodeProtectedHeader(parts.kbJwt);\n const kbAlg = kbHeader.alg;\n if (typeof kbAlg !== 'string' || !allowedAlgorithms.includes(kbAlg)) {\n return invalidResult(`Unsupported KB-JWT algorithm: ${kbAlg}`);\n }\n holderKey = await importJWK(cnf['jwk'] as Record<string, unknown>, kbAlg);\n } catch (err) {\n if (err instanceof MalformedCredentialError) throw err;\n throw new MalformedCredentialError('Failed to import holder key from cnf.jwk');\n }\n\n // Verify KB-JWT signature\n let kbPayload: Record<string, unknown>;\n try {\n const kbResult = await jwtVerify(parts.kbJwt, holderKey, {\n algorithms: allowedAlgorithms,\n ...(options.audience ? { audience: options.audience } : {}),\n });\n kbPayload = kbResult.payload as unknown as Record<string, unknown>;\n } catch {\n return invalidResult('Key binding JWT signature verification failed');\n }\n\n // Validate nonce — must be present and match when KB-JWT is used\n if (kbPayload['nonce'] !== options.nonce) {\n return invalidResult('Key binding JWT nonce does not match');\n }\n\n // Verify sd_hash — hash of the SD-JWT content before the KB-JWT\n const disclosurePart = parts.disclosures.length > 0 ? parts.disclosures.join('~') + '~' : '';\n const sdJwtForHash = parts.jwt + '~' + disclosurePart;\n const sdHashBytes = await sha256Hasher(sdJwtForHash, 'sha-256');\n const expectedSdHash = bytesToBase64url(sdHashBytes);\n if (kbPayload['sd_hash'] !== expectedSdHash) {\n return invalidResult('Key binding JWT sd_hash does not match');\n }\n }\n\n // Step 9: Decode disclosures and extract claims\n let resolvedClaims: Record<string, unknown>;\n try {\n const decoded = await decodeSdJwt(vpToken, sha256Hasher);\n resolvedClaims = await getClaims<Record<string, unknown>>(\n decoded.jwt.payload,\n decoded.disclosures,\n sha256Hasher\n );\n } catch {\n throw new MalformedCredentialError('Failed to decode SD-JWT disclosures');\n }\n\n return {\n valid: true,\n format: this.format,\n claims: mapToCredentialClaims(resolvedClaims),\n issuer: issuerInfo,\n };\n }\n}\n","import { Encoder as CborEncoder, Tag } from 'cbor-x';\n\nimport { MalformedCredentialError } from '../errors.js';\n\n// Decoder that preserves CBOR maps as JS Maps (cbor-x default converts them to objects).\nconst decoder = new CborEncoder({ mapsAsObjects: false, useRecords: false });\n\n/**\n * COSE label for the `alg` header parameter.\n */\nconst HEADER_ALG = 1;\n\n/**\n * COSE label for the `x5chain` header parameter (RFC 9360).\n */\nconst HEADER_X5CHAIN = 33;\n\nconst COSE_ALG_TO_NAME: Record<number, string> = {\n [-7]: 'ES256',\n [-35]: 'ES384',\n [-36]: 'ES512',\n};\n\nexport interface CoseSign1 {\n protectedHeaderBytes: Uint8Array;\n protectedHeader: Map<number, unknown>;\n unprotectedHeader: Map<number, unknown>;\n payload: Uint8Array;\n signature: Uint8Array;\n x5chain: Uint8Array[];\n alg: 'ES256' | 'ES384' | 'ES512';\n}\n\nexport function decodeCoseSign1(bytes: Uint8Array): CoseSign1 {\n let outer: unknown = decoder.decode(bytes);\n if (outer instanceof Tag && outer.tag === 18) {\n // tag-18 value may be the raw bytes of the COSE_Sign1 structure — decode again\n const tagValue = outer.value;\n outer = tagValue instanceof Uint8Array ? decoder.decode(tagValue) : tagValue;\n }\n if (!Array.isArray(outer) || outer.length !== 4) {\n throw new MalformedCredentialError('COSE_Sign1 must be a CBOR array of length 4');\n }\n const [protectedHeaderBytes, unprotectedHeader, payloadRaw, signature] = outer;\n if (!(protectedHeaderBytes instanceof Uint8Array)) {\n throw new MalformedCredentialError('COSE_Sign1 protected header must be a bstr');\n }\n if (!(unprotectedHeader instanceof Map)) {\n throw new MalformedCredentialError('COSE_Sign1 unprotected header must be a Map');\n }\n if (!(signature instanceof Uint8Array)) {\n throw new MalformedCredentialError('COSE_Sign1 signature must be a bstr');\n }\n\n let protectedHeader: Map<number, unknown>;\n try {\n const decoded = decoder.decode(protectedHeaderBytes);\n if (!(decoded instanceof Map)) {\n throw new Error('protected header not a Map');\n }\n protectedHeader = decoded as Map<number, unknown>;\n } catch {\n throw new MalformedCredentialError('COSE_Sign1 protected header is not decodable CBOR');\n }\n\n const algLabel = protectedHeader.get(HEADER_ALG);\n const alg = typeof algLabel === 'number' ? COSE_ALG_TO_NAME[algLabel] : undefined;\n if (!alg) {\n throw new MalformedCredentialError(`COSE_Sign1 uses unknown alg label: ${String(algLabel)}`);\n }\n\n // Payload may be a bstr, tag-24 bstr (embedded CBOR), or absent (detached — not supported here)\n let payload: Uint8Array;\n if (payloadRaw instanceof Uint8Array) {\n payload = payloadRaw;\n } else if (payloadRaw instanceof Tag && payloadRaw.tag === 24 && payloadRaw.value instanceof Uint8Array) {\n payload = payloadRaw.value;\n } else {\n throw new MalformedCredentialError('COSE_Sign1 payload must be a byte string');\n }\n\n // x5chain may be a single cert bstr or an array of bstrs\n const x5raw = unprotectedHeader.get(HEADER_X5CHAIN);\n let x5chain: Uint8Array[];\n if (x5raw === undefined) {\n throw new MalformedCredentialError('COSE_Sign1 missing x5chain in unprotected header (label 33)');\n }\n if (x5raw instanceof Uint8Array) {\n x5chain = [x5raw];\n } else if (Array.isArray(x5raw) && x5raw.every((v) => v instanceof Uint8Array)) {\n x5chain = x5raw as Uint8Array[];\n } else {\n throw new MalformedCredentialError('COSE_Sign1 x5chain must be a bstr or array of bstr');\n }\n\n return {\n protectedHeaderBytes,\n protectedHeader,\n unprotectedHeader: unprotectedHeader as Map<number, unknown>,\n payload,\n signature,\n x5chain,\n alg: alg as 'ES256' | 'ES384' | 'ES512',\n };\n}\n\nconst ALG_TO_HASH: Record<string, string> = {\n ES256: 'SHA-256',\n ES384: 'SHA-384',\n ES512: 'SHA-512',\n};\n\n/**\n * Verifies the COSE_Sign1 signature using the provided public key.\n * Throws when the algorithm is not in the allowlist or the signature is invalid.\n */\nexport async function verifyCoseSign1(\n coseSign1: CoseSign1,\n publicKey: CryptoKey,\n allowedAlgorithms: string[]\n): Promise<void> {\n if (!allowedAlgorithms.includes(coseSign1.alg)) {\n throw new MalformedCredentialError(`COSE_Sign1 algorithm ${coseSign1.alg} not in allowlist`);\n }\n const hashAlg = ALG_TO_HASH[coseSign1.alg];\n if (!hashAlg) {\n throw new MalformedCredentialError(`no hash mapping for alg ${coseSign1.alg}`);\n }\n\n // Sig_structure1 = [\"Signature1\", protected_header_bytes, external_aad (empty bstr), payload]\n // coseSign1.payload is the raw bstr from the COSE array — it already contains the tag-24\n // encoded MSO bytes as stored by the signer, so we use it directly without re-wrapping.\n const sigStructure = ['Signature1', coseSign1.protectedHeaderBytes, new Uint8Array(0), coseSign1.payload];\n const sigInput = decoder.encode(sigStructure);\n\n // Copy into a plain Uint8Array<ArrayBuffer> so TS's BufferSource constraint is satisfied.\n const ok = await crypto.subtle.verify(\n { name: 'ECDSA', hash: hashAlg },\n publicKey,\n new Uint8Array(coseSign1.signature),\n sigInput\n );\n if (!ok) {\n throw new MalformedCredentialError('COSE_Sign1 signature verification failed');\n }\n}\n","import { Encoder as CborEncoder, Tag } from 'cbor-x';\n\nimport { MalformedCredentialError } from '../errors.js';\n\nimport type { MobileSecurityObject } from './mso.js';\n\n// Decoder that preserves CBOR maps as JS Maps (cbor-x default converts them to objects).\nconst decoder = new CborEncoder({ mapsAsObjects: false, useRecords: false });\n\nconst ALLOWED_HASH_ALGS = new Set(['SHA-256', 'SHA-384', 'SHA-512']);\n\nexport async function computeItemDigest(itemBytes: Uint8Array, digestAlgorithm: string): Promise<Uint8Array> {\n if (!ALLOWED_HASH_ALGS.has(digestAlgorithm)) {\n throw new MalformedCredentialError(`Unknown digest algorithm: ${digestAlgorithm}`);\n }\n // Copy into a plain Uint8Array<ArrayBuffer> to satisfy TypeScript's BufferSource constraint.\n const buf = await crypto.subtle.digest(digestAlgorithm, new Uint8Array(itemBytes));\n return new Uint8Array(buf);\n}\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/**\n * Unwrap an IssuerSignedItem from its tag-24 encoding and return the inner Map.\n *\n * Three shapes arise depending on test vs. production paths:\n * A) Tag(24, Uint8Array) — production cbor-x path (no addExtension)\n * B) EmbeddedCbor-like obj — test-fixture path (addExtension in mdoc-helpers.ts registers a\n * custom class whose instances have `.value: Uint8Array`)\n * C) Plain Map — if cbor-x auto-unwraps deeper than expected\n */\nfunction unwrapItemMap(itemBytes: Uint8Array): Map<string, unknown> {\n let decoded: unknown;\n try {\n decoded = decoder.decode(itemBytes);\n } catch {\n throw new MalformedCredentialError('IssuerSignedItem is not decodable CBOR');\n }\n\n let inner: unknown;\n if (decoded instanceof Tag && decoded.tag === 24 && decoded.value instanceof Uint8Array) {\n // Path A: tag-24 Tag object\n inner = decoder.decode(decoded.value as Uint8Array);\n } else if (\n decoded !== null &&\n typeof decoded === 'object' &&\n !(decoded instanceof Tag) &&\n !(decoded instanceof Map) &&\n !(decoded instanceof Uint8Array) &&\n 'value' in (decoded as object) &&\n (decoded as { value: unknown }).value instanceof Uint8Array\n ) {\n // Path B: EmbeddedCbor-like object from test fixture's addExtension\n inner = decoder.decode((decoded as { value: Uint8Array }).value);\n } else if (decoded instanceof Map) {\n // Path C: already a Map\n inner = decoded;\n } else {\n throw new MalformedCredentialError('IssuerSignedItem must be a tag-24 wrapped CBOR Map');\n }\n\n if (!(inner instanceof Map)) {\n throw new MalformedCredentialError('IssuerSignedItem must decode to a Map');\n }\n return inner as Map<string, unknown>;\n}\n\n/**\n * Verifies every IssuerSignedItem across every namespace against the MSO's valueDigests.\n * All items must match — no partial acceptance.\n *\n * @param nameSpaces Per-namespace arrays of tag-24-wrapped IssuerSignedItem bytes\n * (exactly the bytes used as digest input during issuance).\n * @param mso Decoded MobileSecurityObject carrying the expected valueDigests.\n */\nexport async function verifyAllDigests(\n nameSpaces: Map<string, Uint8Array[]>,\n mso: MobileSecurityObject\n): Promise<void> {\n for (const [ns, items] of nameSpaces) {\n const expected = mso.valueDigests.get(ns);\n if (!expected) {\n throw new MalformedCredentialError(`namespace ${ns} has no valueDigests entry in MSO`);\n }\n for (const itemBytes of items) {\n // Hash the raw tag-24 bytes — this is what the issuer hashed during issuance.\n const hash = await computeItemDigest(itemBytes, mso.digestAlgorithm);\n\n // Decode to extract digestID for lookup.\n const item = unwrapItemMap(itemBytes);\n const digestID = item.get('digestID');\n if (typeof digestID !== 'number') {\n throw new MalformedCredentialError('IssuerSignedItem missing digestID');\n }\n\n const expectedDigest = expected.get(digestID);\n if (!expectedDigest) {\n throw new MalformedCredentialError(`digestID ${digestID} missing from MSO valueDigests[${ns}]`);\n }\n if (!bytesEqual(hash, expectedDigest)) {\n throw new MalformedCredentialError(`digest mismatch for ns=${ns} digestID=${digestID}`);\n }\n }\n }\n}\n","import { Encoder as CborEncoder, Tag } from 'cbor-x';\n\nimport { MalformedCredentialError, ExpiredCredentialError } from '../errors.js';\n\n// Decoder that preserves CBOR maps as JS Maps (cbor-x default converts them to objects).\nconst decoder = new CborEncoder({ mapsAsObjects: false, useRecords: false });\n\nexport interface MobileSecurityObject {\n version: string;\n digestAlgorithm: string;\n valueDigests: Map<string, Map<number, Uint8Array>>;\n docType: string;\n validityInfo: {\n signed: Date;\n validFrom: Date;\n validUntil: Date;\n expectedUpdate?: Date;\n };\n}\n\nfunction decodeDateLike(value: unknown): Date {\n if (value instanceof Date) return value;\n if (value instanceof Tag) {\n // Tag 0 = RFC 3339 string; Tag 1 = epoch seconds; Tag 1004 = full-date (YYYY-MM-DD)\n if (value.tag === 0 && typeof value.value === 'string') {\n return new Date(value.value);\n }\n if (value.tag === 1 && typeof value.value === 'number') {\n return new Date(value.value * 1000);\n }\n if (value.tag === 1004 && typeof value.value === 'string') {\n return new Date(value.value);\n }\n }\n if (typeof value === 'string') {\n return new Date(value);\n }\n throw new MalformedCredentialError(`unsupported date encoding in MSO: ${typeof value}`);\n}\n\nexport function decodeMso(payload: Uint8Array): MobileSecurityObject {\n let raw: unknown;\n try {\n raw = decoder.decode(payload);\n // Unwrap tag-24 (embedded CBOR): COSE payload may be tag-24 wrapped MSO bytes.\n // In production cbor-x decodes tag-24 as Tag(24, bytes); in test fixtures that register\n // a custom addExtension for tag-24 it decodes to an EmbeddedCbor-like object with .value.\n if (raw instanceof Tag && raw.tag === 24 && raw.value instanceof Uint8Array) {\n raw = decoder.decode(raw.value);\n } else if (\n raw !== null &&\n typeof raw === 'object' &&\n !(raw instanceof Tag) &&\n !(raw instanceof Map) &&\n !(raw instanceof Uint8Array) &&\n 'value' in (raw as object) &&\n (raw as { value: unknown }).value instanceof Uint8Array\n ) {\n // TEST-FIXTURE COMPATIBILITY: tests/fixtures/mdoc-helpers.ts registers a custom\n // tag-24 addExtension globally, so cbor-x returns an EmbeddedCbor-like object\n // (with `.value: Uint8Array`) instead of Tag(24, bytes) during tests. The `!(raw\n // instanceof Tag)` guard ensures we don't misinterpret arbitrary Tag(N, bytes)\n // values as embedded CBOR in production.\n raw = decoder.decode((raw as { value: Uint8Array }).value);\n }\n } catch (err) {\n if (err instanceof MalformedCredentialError) throw err;\n throw new MalformedCredentialError('MSO payload is not decodable CBOR');\n }\n if (!(raw instanceof Map)) {\n throw new MalformedCredentialError('MSO must be a CBOR Map');\n }\n const m = raw as Map<string, unknown>;\n\n const version = m.get('version');\n if (typeof version !== 'string') {\n throw new MalformedCredentialError('MSO.version must be a string');\n }\n const digestAlgorithm = m.get('digestAlgorithm');\n if (typeof digestAlgorithm !== 'string') {\n throw new MalformedCredentialError('MSO.digestAlgorithm must be a string');\n }\n const docType = m.get('docType');\n if (typeof docType !== 'string') {\n throw new MalformedCredentialError('MSO.docType must be a string');\n }\n\n const vdRaw = m.get('valueDigests');\n if (!(vdRaw instanceof Map)) {\n throw new MalformedCredentialError('MSO.valueDigests must be a Map');\n }\n const valueDigests = new Map<string, Map<number, Uint8Array>>();\n for (const [ns, inner] of vdRaw.entries()) {\n if (typeof ns !== 'string' || !(inner instanceof Map)) {\n throw new MalformedCredentialError('MSO.valueDigests entry malformed');\n }\n const perNs = new Map<number, Uint8Array>();\n for (const [id, digest] of (inner as Map<unknown, unknown>).entries()) {\n if (typeof id !== 'number' || !(digest instanceof Uint8Array)) {\n throw new MalformedCredentialError('MSO digest entry must map number→bstr');\n }\n perNs.set(id, digest);\n }\n valueDigests.set(ns, perNs);\n }\n\n const viRaw = m.get('validityInfo');\n if (!(viRaw instanceof Map)) {\n throw new MalformedCredentialError('MSO.validityInfo must be a Map');\n }\n const vi = viRaw as Map<string, unknown>;\n const validityInfo: MobileSecurityObject['validityInfo'] = {\n signed: decodeDateLike(vi.get('signed')),\n validFrom: decodeDateLike(vi.get('validFrom')),\n validUntil: decodeDateLike(vi.get('validUntil')),\n };\n if (vi.has('expectedUpdate')) {\n validityInfo.expectedUpdate = decodeDateLike(vi.get('expectedUpdate'));\n }\n\n return { version, digestAlgorithm, valueDigests, docType, validityInfo };\n}\n\n/**\n * Validates the MSO's validityInfo block against a reference time.\n * Enforces strict ISO 18013-5 rules:\n * - signed <= now\n * - validFrom <= now\n * - validFrom <= validUntil\n * - signed within [validFrom, validUntil]\n * - validUntil >= now (else ExpiredCredentialError)\n */\nexport function validateMsoValidity(mso: MobileSecurityObject, now: Date): void {\n const { signed, validFrom, validUntil } = mso.validityInfo;\n if (signed.getTime() > now.getTime()) {\n throw new MalformedCredentialError(`MSO signed=${signed.toISOString()} is in the future`);\n }\n if (validFrom.getTime() > now.getTime()) {\n throw new MalformedCredentialError(`MSO validFrom=${validFrom.toISOString()} is in the future`);\n }\n if (validFrom.getTime() > validUntil.getTime()) {\n throw new MalformedCredentialError('MSO validFrom is after validUntil');\n }\n if (signed.getTime() < validFrom.getTime() || signed.getTime() > validUntil.getTime()) {\n throw new MalformedCredentialError('MSO signed is outside the validity window');\n }\n if (validUntil.getTime() < now.getTime()) {\n throw new ExpiredCredentialError(`MSO validUntil=${validUntil.toISOString()} is in the past`);\n }\n}\n\n/**\n * Validates that the MSO's docType matches the expected one.\n * Used by callers who want to lock the accepted credential type.\n */\nexport function validateMsoDocType(mso: MobileSecurityObject, expectedDocType: string): void {\n if (mso.docType !== expectedDocType) {\n throw new MalformedCredentialError(`MSO docType=${mso.docType} does not match expected ${expectedDocType}`);\n }\n}\n","import { Encoder as CborEncoder, Tag } from 'cbor-x';\nimport { importX509 } from 'jose';\n\nimport { decodeCoseSign1, verifyCoseSign1 } from '../crypto/cose-sign1.js';\nimport { verifyAllDigests } from '../crypto/digest.js';\nimport { decodeMso, validateMsoValidity, validateMsoDocType } from '../crypto/mso.js';\nimport { MalformedCredentialError, ExpiredCredentialError } from '../errors.js';\nimport type { IssuerInfo } from '../types/issuer.js';\nimport type { CredentialFormat, CredentialClaims, PresentationResult } from '../types/presentation.js';\n\nimport type { ICredentialParser, ParseOptions } from './parser.interface.js';\n\n// Decoder that preserves CBOR maps as JS Maps (cbor-x default converts them to objects).\nconst decoder = new CborEncoder({ mapsAsObjects: false, useRecords: false });\nconst encoder = new CborEncoder({ mapsAsObjects: false, useRecords: false });\n\nconst DEFAULT_ALLOWED_ALGORITHMS = ['ES256', 'ES384', 'ES512'];\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction derToPem(der: Uint8Array): string {\n let binary = '';\n for (const b of der) binary += String.fromCharCode(b);\n const b64 = globalThis.btoa(binary);\n const lines = b64.match(/.{1,64}/g) || [];\n return `-----BEGIN CERTIFICATE-----\\n${lines.join('\\n')}\\n-----END CERTIFICATE-----`;\n}\n\nfunction extractCountryHintFromCert(_certDer: Uint8Array): string {\n // Placeholder — full X.509 subject parsing is workstream 3.\n return '';\n}\n\n/**\n * Extracts raw tag-24 bytes from an IssuerSignedItem.\n *\n * Each IssuerSignedItem in the DeviceResponse is stored as EmbeddedCbor(itemTag24),\n * which on the wire is tag-24 wrapping the already-tag-24-wrapped item bytes.\n * cbor-x decoding unwraps one layer, so `item.value` (or the Tag(24).value) is\n * exactly `itemTag24` — the bytes the issuer hashed. Return those directly.\n *\n * Three shapes arise depending on test vs. production paths:\n * A) Tag(24, Uint8Array) — production cbor-x path (no addExtension)\n * B) EmbeddedCbor-like obj — test-fixture path (addExtension in mdoc-helpers.ts registers a\n * custom class whose instances have `.value: Uint8Array`)\n * C) Plain Uint8Array — already encoded tag-24 bytes\n */\nfunction extractRawItemBytes(item: unknown): Uint8Array {\n if (item instanceof Tag && item.tag === 24 && item.value instanceof Uint8Array) {\n return item.value;\n }\n if (item instanceof Uint8Array) {\n return item;\n }\n if (\n item !== null &&\n typeof item === 'object' &&\n !(item instanceof Tag) &&\n !(item instanceof Map) &&\n 'value' in (item as object) &&\n (item as { value: unknown }).value instanceof Uint8Array\n ) {\n return (item as { value: Uint8Array }).value;\n }\n throw new MalformedCredentialError('IssuerSignedItem must be a tag-24 byte string');\n}\n\n/**\n * Maps raw IssuerSignedItem bytes (from all namespaces) to CredentialClaims.\n *\n * Handles all three tag-24 shapes (Tag(24,bytes), EmbeddedCbor-like object, plain bytes).\n */\nfunction mapRawToClaims(nameSpaces: Map<string, Uint8Array[]>): CredentialClaims {\n const out: CredentialClaims = {};\n for (const items of nameSpaces.values()) {\n for (const itemBytes of items) {\n let decoded: unknown;\n try {\n decoded = decoder.decode(itemBytes);\n } catch {\n continue;\n }\n\n // Unwrap all three tag-24 shapes to get the inner CBOR bytes\n let inner: unknown;\n if (decoded instanceof Tag && decoded.tag === 24 && decoded.value instanceof Uint8Array) {\n // Path A: Tag(24, bytes)\n inner = decoder.decode(decoded.value as Uint8Array);\n } else if (\n decoded !== null &&\n typeof decoded === 'object' &&\n !(decoded instanceof Tag) &&\n !(decoded instanceof Map) &&\n !(decoded instanceof Uint8Array) &&\n 'value' in (decoded as object) &&\n (decoded as { value: unknown }).value instanceof Uint8Array\n ) {\n // Path B: EmbeddedCbor-like object from test fixture's addExtension\n inner = decoder.decode((decoded as { value: Uint8Array }).value);\n } else if (decoded instanceof Map) {\n // Path C: already a Map\n inner = decoded;\n } else {\n continue;\n }\n\n if (inner instanceof Map) {\n const id = (inner as Map<string, unknown>).get('elementIdentifier');\n const val = (inner as Map<string, unknown>).get('elementValue');\n if (typeof id === 'string') {\n (out as Record<string, unknown>)[id] = val;\n }\n }\n }\n }\n return out;\n}\n\n/**\n * mDOC / mDL credential parser.\n *\n * Decodes and validates mDOC (Mobile Document) credentials as specified in\n * ISO 18013-5 and the EUDI Wallet ecosystem. Composes the crypto modules\n * to perform full verification:\n * - COSE_Sign1 decode + signature verification\n * - MSO decode + validity + docType validation\n * - Digest verification for all IssuerSignedItems\n * - Issuer certificate trust chain check\n */\nexport class MdocParser implements ICredentialParser {\n readonly format: CredentialFormat = 'mdoc';\n\n /**\n * Returns true when the token is binary data (Uint8Array or Buffer),\n * indicating a CBOR-encoded mDOC DeviceResponse.\n * Buffer extends Uint8Array, so `instanceof Uint8Array` catches both.\n */\n canParse(vpToken: unknown): boolean {\n return vpToken instanceof Uint8Array;\n }\n\n /**\n * Parses and validates an mDOC DeviceResponse token.\n *\n * @throws {MalformedCredentialError} when the CBOR structure cannot be decoded\n * or does not match the expected DeviceResponse format\n */\n async parse(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n if (!(vpToken instanceof Uint8Array)) {\n throw new MalformedCredentialError('mDOC vpToken must be a Uint8Array');\n }\n const allowedAlgorithms = options.allowedAlgorithms ?? DEFAULT_ALLOWED_ALGORITHMS;\n\n // Step 1: Decode DeviceResponse\n let deviceResponse: Map<unknown, unknown>;\n try {\n const decoded = decoder.decode(vpToken);\n if (!(decoded instanceof Map)) throw new Error();\n deviceResponse = decoded as Map<unknown, unknown>;\n } catch {\n throw new MalformedCredentialError('vpToken is not a CBOR DeviceResponse Map');\n }\n\n // Step 2: Extract first document\n const docs = deviceResponse.get('documents');\n if (!Array.isArray(docs) || docs.length === 0) {\n throw new MalformedCredentialError('DeviceResponse has no documents');\n }\n const document = docs[0];\n if (!(document instanceof Map)) {\n throw new MalformedCredentialError('document must be a Map');\n }\n const issuerSigned = document.get('issuerSigned');\n if (!(issuerSigned instanceof Map)) {\n throw new MalformedCredentialError('document.issuerSigned must be a Map');\n }\n const issuerAuth = issuerSigned.get('issuerAuth');\n if (!Array.isArray(issuerAuth)) {\n throw new MalformedCredentialError('issuerAuth must be a COSE_Sign1 array');\n }\n\n // Re-encode issuerAuth as bytes so we can pass to decodeCoseSign1\n const issuerAuthBytes = encoder.encode(issuerAuth);\n\n // Step 3: Decode COSE_Sign1 + algorithm check\n const cose = decodeCoseSign1(issuerAuthBytes);\n if (!allowedAlgorithms.includes(cose.alg)) {\n return {\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error: `Unsupported algorithm: ${cose.alg}`,\n };\n }\n\n // Step 4: Trust check (reuse 0.2.1 skipTrustCheck semantics)\n const issuerCertBytes = cose.x5chain[0];\n if (!issuerCertBytes) {\n throw new MalformedCredentialError('Missing issuer certificate in x5chain');\n }\n if (options.trustedCertificates.length === 0) {\n if (options.skipTrustCheck !== true) {\n throw new MalformedCredentialError(\n 'trustedCertificates must not be empty unless skipTrustCheck is true'\n );\n }\n } else {\n const trusted = options.trustedCertificates.some((t) => bytesEqual(t, issuerCertBytes));\n if (!trusted) {\n return {\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: issuerCertBytes, country: '' },\n error: 'Issuer certificate is not trusted',\n };\n }\n }\n\n // Step 5: Import public key + verify signature\n const publicKey = await importX509(derToPem(issuerCertBytes), cose.alg);\n try {\n await verifyCoseSign1(cose, publicKey, allowedAlgorithms);\n } catch (err) {\n if (err instanceof MalformedCredentialError) {\n return {\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: issuerCertBytes, country: '' },\n error: err.message,\n };\n }\n throw err;\n }\n\n // Step 6: Decode + validate MSO\n const mso = decodeMso(cose.payload);\n try {\n validateMsoValidity(mso, new Date());\n } catch (err) {\n if (err instanceof ExpiredCredentialError) {\n return {\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: issuerCertBytes, country: '' },\n error: 'Credential expired',\n };\n }\n throw err;\n }\n\n if (options.expectedDocType !== undefined) {\n try {\n validateMsoDocType(mso, options.expectedDocType);\n } catch (err) {\n if (err instanceof MalformedCredentialError) {\n return {\n valid: false,\n format: this.format,\n claims: {},\n issuer: { certificate: issuerCertBytes, country: '' },\n error: err.message,\n };\n }\n throw err;\n }\n }\n\n // Step 7: Extract items from nameSpaces, verify all digests\n const nsRaw = issuerSigned.get('nameSpaces');\n if (!(nsRaw instanceof Map)) {\n throw new MalformedCredentialError('issuerSigned.nameSpaces must be a Map');\n }\n const nameSpaces = new Map<string, Uint8Array[]>();\n for (const [ns, items] of (nsRaw as Map<unknown, unknown>).entries()) {\n if (typeof ns !== 'string' || !Array.isArray(items)) {\n throw new MalformedCredentialError('nameSpaces entry malformed');\n }\n nameSpaces.set(ns, items.map(extractRawItemBytes));\n }\n await verifyAllDigests(nameSpaces, mso);\n\n // Step 8: Map to claims\n const claims = mapRawToClaims(nameSpaces);\n\n const issuer: IssuerInfo = {\n certificate: issuerCertBytes,\n country: extractCountryHintFromCert(issuerCertBytes),\n };\n return { valid: true, format: this.format, claims, issuer };\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\n\nimport type { AuthorizationRequestInput, AuthorizationRequest } from './types/authorization.js';\n\nexport function createAuthorizationRequest(input: AuthorizationRequestInput): AuthorizationRequest {\n const state = input.state ?? uuidv4();\n\n const presentationDefinition = {\n id: uuidv4(),\n input_descriptors: input.requestedAttributes.map((attr, index) => ({\n id: `descriptor_${index}`,\n format: Object.fromEntries(\n input.acceptedFormats.map((fmt) => {\n if (fmt === 'sd-jwt-vc') return ['vc+sd-jwt', { 'sd-jwt_alg_values': ['ES256'] }];\n return ['mso_mdoc', { alg: ['ES256'] }];\n })\n ),\n constraints: {\n fields: [\n {\n path: [`$.${attr}`, `$['${attr}']`],\n filter: { type: attr.startsWith('age_over') ? 'boolean' : 'string' },\n },\n ],\n },\n })),\n };\n\n const params = new URLSearchParams({\n response_type: 'vp_token',\n response_mode: 'direct_post',\n response_uri: input.responseUri,\n client_id: input.clientId,\n nonce: input.nonce,\n state,\n presentation_definition: JSON.stringify(presentationDefinition),\n });\n\n return {\n uri: `openid4vp://authorize?${params.toString()}`,\n presentationDefinition,\n nonce: input.nonce,\n state,\n };\n}\n","import { MdocParser } from './parsers/mdoc.parser.js';\nimport type { ParseOptions, ICredentialParser } from './parsers/parser.interface.js';\nimport { SdJwtParser } from './parsers/sd-jwt.parser.js';\nimport type { PresentationResult } from './types/presentation.js';\n\nconst parsers: ICredentialParser[] = [new SdJwtParser(), new MdocParser()];\n\nexport async function parsePresentation(vpToken: unknown, options: ParseOptions): Promise<PresentationResult> {\n for (const parser of parsers) {\n if (parser.canParse(vpToken)) {\n return parser.parse(vpToken, options);\n }\n }\n\n return {\n valid: false,\n format: 'sd-jwt-vc',\n claims: {},\n issuer: { certificate: new Uint8Array(), country: '' },\n error: 'Unsupported credential format',\n };\n}\n\nexport type { ParseOptions } from './parsers/parser.interface.js';\n","export const VERSION = '0.3.0';\n\nexport type {\n CredentialFormat,\n CredentialClaims,\n PresentationResult,\n IssuerInfo,\n AuthorizationRequestInput,\n AuthorizationRequest,\n} from './types/index.js';\n\nexport type { ICredentialParser, ParseOptions } from './parsers/parser.interface.js';\n\nexport { SdJwtParser } from './parsers/sd-jwt.parser.js';\nexport { MdocParser } from './parsers/mdoc.parser.js';\n\nexport {\n InvalidSignatureError,\n ExpiredCredentialError,\n UnsupportedFormatError,\n MalformedCredentialError,\n NonceValidationError,\n} from './errors.js';\n\nexport { createAuthorizationRequest } from './authorization.js';\n\nexport { parsePresentation } from './presentation.js';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openeudi/openid4vp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "OpenID4VP credential parsing and validation for EUDI Wallets (SD-JWT VC + mDOC)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -32,21 +32,24 @@
|
|
|
32
32
|
"type-check": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
+
"@peculiar/x509": "^2.0.0",
|
|
35
36
|
"@sd-jwt/decode": "^0.19.0",
|
|
36
37
|
"@sphereon/pex": "5.0.0-unstable.28",
|
|
37
38
|
"@sphereon/ssi-types": "^0.37.1",
|
|
38
39
|
"cbor-x": "^1.6.0",
|
|
39
|
-
"cose-js": "^0.9.0",
|
|
40
40
|
"jose": "^6.1.3",
|
|
41
41
|
"uuid": "^11.1.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@peculiar/x509": "^2.0.0",
|
|
45
44
|
"reflect-metadata": "^0.2.2",
|
|
46
45
|
"tsup": "^8.5.1",
|
|
47
46
|
"typescript": "^5.8.3",
|
|
48
47
|
"vitest": "^4.0.18"
|
|
49
48
|
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/openeudi/openid4vp"
|
|
52
|
+
},
|
|
50
53
|
"keywords": [
|
|
51
54
|
"openid4vp",
|
|
52
55
|
"eudi",
|
|
@@ -54,19 +57,5 @@
|
|
|
54
57
|
"mdoc",
|
|
55
58
|
"verifiable-credentials",
|
|
56
59
|
"eidas"
|
|
57
|
-
]
|
|
58
|
-
"publishConfig": {
|
|
59
|
-
"access": "public",
|
|
60
|
-
"provenance": true,
|
|
61
|
-
"registry": "https://registry.npmjs.org"
|
|
62
|
-
},
|
|
63
|
-
"repository": {
|
|
64
|
-
"type": "git",
|
|
65
|
-
"url": "https://github.com/openeudi/openid4vp"
|
|
66
|
-
},
|
|
67
|
-
"homepage": "https://github.com/openeudi/openid4vp#readme",
|
|
68
|
-
"bugs": {
|
|
69
|
-
"url": "https://github.com/openeudi/openid4vp/issues"
|
|
70
|
-
},
|
|
71
|
-
"author": "OpenEUDI Contributors"
|
|
60
|
+
]
|
|
72
61
|
}
|