Skip to content
File

Blob: src/worker/auth/host-labels.ts

typescript32 lines
1import { randomBytes } from "@/worker/auth/bytes";
2import { HOST_WORDS } from "@/worker/auth/host-wordlist";
3 
4const wordSet = new Set<string>(HOST_WORDS);
5const hostLabelRe = /^[a-z]+(-[a-z]+){4}$/;
6 
7function randomWordIndex(): number {
8 const length = HOST_WORDS.length;
9 const max = 65_536 - (65_536 % length);
10 
11 while (true) {
12 const bytes = randomBytes(2);
13 const value = (bytes[0] << 8) | bytes[1];
14 if (value < max) return value % length;
15 }
16}
17 
18export function isValidHostLabel(label: string): boolean {
19 if (label.length > 63 || !hostLabelRe.test(label)) return false;
20 return label.split("-").every((word) => wordSet.has(word));
21}
22 
23export function generateHostLabel(): string {
24 for (let attempt = 0; attempt < 100; attempt += 1) {
25 const words = Array.from({ length: 5 }, () => HOST_WORDS[randomWordIndex()]);
26 const label = words.join("-");
27 if (label.length <= 63) return label;
28 }
29 
30 throw new Error("Unable to generate a host label under 64 characters");
31}