All files / sample-services/src/vat-lib registration-token.ts

0% Statements 0/8
0% Branches 0/6
0% Functions 0/2
0% Lines 0/7

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 */