diff --git a/website/package-lock.json b/website/package-lock.json index 59bf07d..6aa364d 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -9,7 +9,7 @@ "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "bwip-js": "^4.5.1", - "dosipas-ts": "^2.0.0", + "dosipas-ts": "^3.0.0", "react": "^19.1.0", "react-dom": "^19.1.0", "zxing-wasm": "^2.2.1" @@ -55,7 +55,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1543,7 +1542,6 @@ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1621,7 +1619,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -1718,9 +1715,9 @@ } }, "node_modules/dosipas-ts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dosipas-ts/-/dosipas-ts-2.0.0.tgz", - "integrity": "sha512-vprLsu0fjsRspfmNvuv0m+1kUx/jqGTi4EwJGLgJO7BzfMo2DbOUg3toR248+51M8Ml8Vu0vgqqTTz9iqtVi1g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dosipas-ts/-/dosipas-ts-3.0.0.tgz", + "integrity": "sha512-0u2t8bDqcrzbttE8ugapZqozPWrWVGzXkQileeeRdIT/W7CFIdQwidVQUPOJIa9RjecbEI3QzgVsSG8f2n6rJQ==", "license": "MIT", "dependencies": { "@noble/curves": "^2.0.1", @@ -2241,7 +2238,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2283,7 +2279,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2506,7 +2501,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/website/package.json b/website/package.json index 56b393d..09671d9 100644 --- a/website/package.json +++ b/website/package.json @@ -11,7 +11,7 @@ "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "bwip-js": "^4.5.1", - "dosipas-ts": "^2.0.0", + "dosipas-ts": "^3.0.0", "react": "^19.1.0", "react-dom": "^19.1.0", "zxing-wasm": "^2.2.1" diff --git a/website/src/components/HexViewer.tsx b/website/src/components/HexViewer.tsx index 1b8c619..40495e1 100644 --- a/website/src/components/HexViewer.tsx +++ b/website/src/components/HexViewer.tsx @@ -1,8 +1,8 @@ -import type { ExtractedSignedData } from 'dosipas-ts'; +import type { ExtractedTicket } from 'dosipas-ts'; interface Props { hex: string; - signedData: ExtractedSignedData | null; + signedData: ExtractedTicket | null; } interface Region { @@ -34,44 +34,44 @@ export default function HexViewer({ hex, signedData }: Props) { const regions: Region[] = []; if (signedData) { - const l1Idx = findSubarray(bytes, signedData.level1DataBytes); + const l1Idx = findSubarray(bytes, signedData.level1.signedBytes); if (l1Idx >= 0) { regions.push({ start: l1Idx, - end: l1Idx + signedData.level1DataBytes.length, + end: l1Idx + signedData.level1.signedBytes.length, label: 'L1 data', color: 'bg-blue-100 text-blue-900', }); } - const l2Idx = findSubarray(bytes, signedData.level2SignedBytes); + const l2Idx = findSubarray(bytes, signedData.level2.signedBytes); if (l2Idx >= 0) { regions.push({ start: l2Idx, - end: l2Idx + signedData.level2SignedBytes.length, + end: l2Idx + signedData.level2.signedBytes.length, label: 'L2 signed', color: 'bg-green-100 text-green-900', }); } - if (signedData.security.level1Signature) { - const sigIdx = findSubarray(bytes, signedData.security.level1Signature); + if (signedData.level1.signature) { + const sigIdx = findSubarray(bytes, signedData.level1.signature); if (sigIdx >= 0) { regions.push({ start: sigIdx, - end: sigIdx + signedData.security.level1Signature.length, + end: sigIdx + signedData.level1.signature.length, label: 'L1 sig', color: 'bg-orange-100 text-orange-900', }); } } - if (signedData.security.level2Signature) { - const sigIdx = findSubarray(bytes, signedData.security.level2Signature); + if (signedData.level2.signature) { + const sigIdx = findSubarray(bytes, signedData.level2.signature); if (sigIdx >= 0) { regions.push({ start: sigIdx, - end: sigIdx + signedData.security.level2Signature.length, + end: sigIdx + signedData.level2.signature.length, label: 'L2 sig', color: 'bg-purple-100 text-purple-900', }); diff --git a/website/src/hooks/useTicketDecode.ts b/website/src/hooks/useTicketDecode.ts index 7ff97b1..2bd7eb3 100644 --- a/website/src/hooks/useTicketDecode.ts +++ b/website/src/hooks/useTicketDecode.ts @@ -1,16 +1,16 @@ import { useState, useEffect, useRef } from 'react'; -import { decodeTicket, verifySignatures, extractSignedData } from 'dosipas-ts'; +import { decodeTicket, verifySignatures, extractTicket } from 'dosipas-ts'; import type { UicBarcodeTicket, SignatureVerificationResult, - ExtractedSignedData, + ExtractedTicket, } from 'dosipas-ts'; import { createKeyProvider } from '../lib/keys'; export interface DecodeResult { ticket: UicBarcodeTicket | null; signatures: SignatureVerificationResult | null; - signedData: ExtractedSignedData | null; + signedData: ExtractedTicket | null; error: string | null; loading: boolean; } @@ -23,7 +23,7 @@ export function useTicketDecode( ): DecodeResult { const [ticket, setTicket] = useState(null); const [signatures, setSignatures] = useState(null); - const [signedData, setSignedData] = useState(null); + const [signedData, setSignedData] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const debounceRef = useRef>(undefined); @@ -54,7 +54,7 @@ export function useTicketDecode( const bytes = new Uint8Array( clean.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)), ); - const extracted = extractSignedData(bytes); + const extracted = extractTicket(bytes); setSignedData(extracted); } catch { setSignedData(null); diff --git a/website/src/lib/keys.ts b/website/src/lib/keys.ts index b644aaa..ef29614 100644 --- a/website/src/lib/keys.ts +++ b/website/src/lib/keys.ts @@ -81,14 +81,15 @@ export async function createKeyProvider( ): Promise { const xml = await loadKeysXml(); return { - async getPublicKey(securityProvider, keyId) { + async getPublicKey(key) { // Issuers identified by an IA5 string are not in the UIC registry, // which is keyed by numeric RICS codes. - if (trustCarJauneKey && securityProvider.ia5 === 'IWN8' && keyId === 1) { + if (trustCarJauneKey && key.securityProviderIA5 === 'IWN8' && key.keyId === 1) { return getCarJauneKey(); } - const issuerCode = securityProvider.num ?? 0; + const issuerCode = key.securityProviderNum ?? 0; + const keyId = key.keyId ?? 0; // No algorithms supplied for these two: their barcodes carry their own // OIDs, and a configured value that disagreed would be a hard error. if (trustFipsKey && issuerCode === 9999 && keyId === 0) { @@ -98,12 +99,11 @@ export async function createKeyProvider( return { publicKey: getSysdevrunPublicKey() }; } - const key = findKeyInXml(xml, issuerCode, keyId); - if (!key) { - const issuer = securityProvider.ia5 ?? issuerCode; - throw new Error(`Key not found: issuer=${issuer}, keyId=${keyId}`); + const material = findKeyInXml(xml, issuerCode, keyId); + if (!material) { + throw new Error(`Key not found: ${key.id}`); } - return key; + return material; }, }; }