Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /* eslint-disable n/no-unsupported-features/node-builtins -- the crypto global is "experimental" before Node 23 by ESLint's Node-builtins rule, but we also need to handle the SES-vat case where the endowment lands as a bare `crypto` Compartment global. Both code paths reference the same Web Crypto shape and are stable here. */ /** * Generate an opaque cryptographic-random token for service registration. * * SES lockdown blocks `Math.random()` inside vats, so this uses the Web * Crypto API (which the kernel-utils-tools `crypto` endowment plumbs * through to vat compartments). Throws if no crypto source is reachable, * since an unpredictable token is required: if the matcher could be * tricked into registering a service under a weak token, third parties * could spoof registrations for services they don't control. * * @returns A 128-bit hex-encoded random token. */ export function makeRegistrationToken(): string { // Try `crypto` as a bare global (what endowments land as, as Compartment // properties) before `globalThis.crypto`, to minimize the chance that // the compartment's globalThis hasn't plumbed the endowment through. const bareCrypto: unknown = typeof crypto === 'undefined' ? undefined : crypto; const cryptoSource = (bareCrypto ?? globalThis.crypto) as | { getRandomValues?: (array: Uint8Array) => Uint8Array } | undefined; if (!cryptoSource?.getRandomValues) { throw new Error( 'makeRegistrationToken: crypto.getRandomValues is not available; ' + `typeof crypto=${typeof crypto}, ` + `typeof globalThis.crypto=${typeof (globalThis as { crypto?: unknown }).crypto}`, ); } const bytes = new Uint8Array(16); cryptoSource.getRandomValues(bytes); return [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join(''); } /* eslint-enable n/no-unsupported-features/node-builtins */ |