From bdd93fc10a576d53de7e03a666b9381da74e7220 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 12:15:02 +0000 Subject: [PATCH] chore(website): migrate to dosipas-ts 4.0.0 Bump the dependency and adopt the async Signer API: the signing.ts adapter wraps localSigner and returns promises, callers in useTicketEncode and EncodeTab await them (the dynamic-refresh signing moves into an async IIFE outside the synchronous countdown state updater), and the derivePublicKey rename replaces the old getPublicKey import alias in keys.ts and signing.ts. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01BMYUez7fcvaL34RUjxKZRJ --- website/package-lock.json | 8 ++++---- website/package.json | 2 +- website/src/components/EncodeTab.tsx | 19 +++++++++++-------- website/src/hooks/useTicketEncode.ts | 4 ++-- website/src/lib/keys.ts | 2 +- website/src/lib/signing.ts | 20 ++++++++++++-------- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index 6aa364d..c78b1c7 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": "^3.0.0", + "dosipas-ts": "^4.0.0", "react": "^19.1.0", "react-dom": "^19.1.0", "zxing-wasm": "^2.2.1" @@ -1715,9 +1715,9 @@ } }, "node_modules/dosipas-ts": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dosipas-ts/-/dosipas-ts-3.0.0.tgz", - "integrity": "sha512-0u2t8bDqcrzbttE8ugapZqozPWrWVGzXkQileeeRdIT/W7CFIdQwidVQUPOJIa9RjecbEI3QzgVsSG8f2n6rJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dosipas-ts/-/dosipas-ts-4.0.0.tgz", + "integrity": "sha512-Yg6WIs6LGv3fSbp7R7I69sjhZ3gWrzZ1q4yisr+KxI5rRbvNhtsLWAsEmU3AbF4X0C+FZscMALTvhZ/LEnwUeQ==", "license": "MIT", "dependencies": { "@noble/curves": "^2.0.1", diff --git a/website/package.json b/website/package.json index 09671d9..7a0a28c 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": "^3.0.0", + "dosipas-ts": "^4.0.0", "react": "^19.1.0", "react-dom": "^19.1.0", "zxing-wasm": "^2.2.1" diff --git a/website/src/components/EncodeTab.tsx b/website/src/components/EncodeTab.tsx index 4b1e569..8c74c59 100644 --- a/website/src/components/EncodeTab.tsx +++ b/website/src/components/EncodeTab.tsx @@ -429,10 +429,10 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill // Generate Level 1 signature // ------------------------------------------------------------------------- - const handleGenerateL1Sig = useCallback(() => { + const handleGenerateL1Sig = useCallback(async () => { try { const prepared = buildPreparedTicket(); - const sig = signLevel1Data(prepared, l1PrivKey, l1Curve); + const sig = await signLevel1Data(prepared, l1PrivKey, l1Curve); const sigHex = bytesToHex(sig); setL1SigHex(sigHex); setL1SigStale(false); @@ -448,7 +448,7 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill // Generate Level 2 signature // ------------------------------------------------------------------------- - const handleGenerateL2Sig = useCallback(() => { + const handleGenerateL2Sig = useCallback(async () => { if (!l1SigHex) { setL2SigError('Level 1 signature must be generated first'); return; @@ -462,7 +462,7 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill level1Signature: hexToBytes(l1SigHex), }, }; - const sig = signLevel2Data(withL1Sig, l2PrivKey, l2Curve); + const sig = await signLevel2Data(withL1Sig, l2PrivKey, l2Curve); const sigHex = bytesToHex(sig); setL2SigHex(sigHex); setL2SigStale(false); @@ -579,7 +579,9 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill regenRef.current = { ...params, ticket: updatedTicket }; setTicket(updatedTicket); - // Full sign+encode for dynamic refresh + // Full sign+encode for dynamic refresh (async, outside the + // synchronous state updater) + void (async () => { try { const level1Key: KeyPair = { privateKey: hexToBytes(params.l1PrivKey), @@ -591,7 +593,7 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill publicKey: getPublicKey(params.l2PrivKey, params.l2Curve), curve: params.l2Curve as CurveName, }; - const refreshedBytes = signTicket(updatedTicket, level1Key, level2Key); + const refreshedBytes = await signTicket(updatedTicket, level1Key, level2Key); const refreshedHex = bytesToHex(refreshedBytes); setHex(refreshedHex); setBytes(refreshedBytes); @@ -611,7 +613,7 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill }, }, }; - const l1Sig = signLevel1Data(prepTicket, params.l1PrivKey, params.l1Curve); + const l1Sig = await signLevel1Data(prepTicket, params.l1PrivKey, params.l1Curve); setL1SigHex(bytesToHex(l1Sig)); setL1SigStale(false); const withL1Sig: UicBarcodeTicket = { @@ -621,13 +623,14 @@ export default function EncodeTab({ onDecode, onControl, prefillInput, onPrefill level1Signature: l1Sig, }, }; - const l2Sig = signLevel2Data(withL1Sig, params.l2PrivKey, params.l2Curve); + const l2Sig = await signLevel2Data(withL1Sig, params.l2PrivKey, params.l2Curve); setL2SigHex(bytesToHex(l2Sig)); setL2SigStale(false); setEncodeError(null); } catch (e) { setEncodeError(e instanceof Error ? e.message : 'Dynamic refresh failed'); } + })(); } return dynamicRefreshInterval; } diff --git a/website/src/hooks/useTicketEncode.ts b/website/src/hooks/useTicketEncode.ts index 36b1c43..a8a227a 100644 --- a/website/src/hooks/useTicketEncode.ts +++ b/website/src/hooks/useTicketEncode.ts @@ -24,7 +24,7 @@ export function useTicketEncode() { }); const encode = useCallback( - ( + async ( ticket: UicBarcodeTicket, level1PrivateKeyHex: string, level1Curve: string, @@ -49,7 +49,7 @@ export function useTicketEncode() { }; } - const bytes = signTicket(ticket, level1Key, level2Key); + const bytes = await signTicket(ticket, level1Key, level2Key); const hex = bytesToHex(bytes); setResult({ hex, bytes, error: null, loading: false }); diff --git a/website/src/lib/keys.ts b/website/src/lib/keys.ts index ef29614..adc2ace 100644 --- a/website/src/lib/keys.ts +++ b/website/src/lib/keys.ts @@ -1,7 +1,7 @@ import { parseKeysXml, findKeyInXml, - getPublicKey as derivePublicKey, + derivePublicKey, CAR_JAUNE_SIGNATURES, } from 'dosipas-ts'; import type { Level1KeyProvider, Level1KeyMaterial, UicPublicKeyEntry } from 'dosipas-ts'; diff --git a/website/src/lib/signing.ts b/website/src/lib/signing.ts index 484263f..3269cd3 100644 --- a/website/src/lib/signing.ts +++ b/website/src/lib/signing.ts @@ -3,8 +3,9 @@ import { signLevel1 as libSignLevel1, signLevel2 as libSignLevel2, encodeTicketToBytes as libEncodeTicketToBytes, - getPublicKey as libGetPublicKey, + derivePublicKey, generateKeyPair as libGenerateKeyPair, + localSigner, CURVES, } from 'dosipas-ts'; import type { UicBarcodeTicket, CurveName, SigningKeyPair } from 'dosipas-ts'; @@ -17,7 +18,7 @@ export function generateKeyPair(curve: string): SigningKeyPair { } export function getPublicKey(privateKeyHex: string, curve: string): Uint8Array { - return libGetPublicKey(hexToBytes(privateKeyHex), curve as CurveName); + return derivePublicKey(hexToBytes(privateKeyHex), curve as CurveName); } /** @@ -29,8 +30,11 @@ export function signTicket( ticket: UicBarcodeTicket, level1Key: SigningKeyPair, level2Key?: SigningKeyPair, -): Uint8Array { - return signAndEncodeTicket(ticket, level1Key, level2Key); +): Promise { + return signAndEncodeTicket(ticket, { + level1: localSigner(level1Key.privateKey, level1Key.curve), + ...(level2Key ? { level2: localSigner(level2Key.privateKey, level2Key.curve) } : {}), + }); } /** Sign Level 1 data and return the DER-encoded signature bytes. */ @@ -38,8 +42,8 @@ export function signLevel1Data( ticket: UicBarcodeTicket, privateKeyHex: string, curve: string, -): Uint8Array { - return libSignLevel1(ticket, hexToBytes(privateKeyHex), curve as CurveName); +): Promise { + return libSignLevel1(ticket, localSigner(hexToBytes(privateKeyHex), curve as CurveName)); } /** Sign Level 2 data and return the DER-encoded signature bytes. */ @@ -47,8 +51,8 @@ export function signLevel2Data( ticket: UicBarcodeTicket, privateKeyHex: string, curve: string, -): Uint8Array { - return libSignLevel2(ticket, hexToBytes(privateKeyHex), curve as CurveName); +): Promise { + return libSignLevel2(ticket, localSigner(hexToBytes(privateKeyHex), curve as CurveName)); } /** Encode a ticket to bytes (with signatures already set). */