43 lines
1.2 KiB
TypeScript
43 lines
1.2 KiB
TypeScript
import { randomBytes } from "node:crypto";
|
|
|
|
/**
|
|
* Generate a cryptographically secure random pairing code.
|
|
* Format: XXXX-XXXX-XXXX (12 alphanumeric characters in groups of 4)
|
|
* Excludes confusing characters: 0, O, 1, I
|
|
*/
|
|
export function generatePairingCode(): string {
|
|
const bytes = randomBytes(8);
|
|
const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // Excludes confusing chars (0, O, 1, I)
|
|
|
|
let code = "";
|
|
for (let i = 0; i < 12; i++) {
|
|
code += chars[bytes[i % bytes.length] % chars.length];
|
|
}
|
|
|
|
// Format as XXXX-XXXX-XXXX
|
|
return `${code.slice(0, 4)}-${code.slice(4, 8)}-${code.slice(8, 12)}`;
|
|
}
|
|
|
|
/**
|
|
* Generate a shared secret for client authentication.
|
|
* This is issued by the server after successful pairing.
|
|
* Returns a base64url-encoded 32-byte random string.
|
|
*/
|
|
export function generateSecret(): string {
|
|
return randomBytes(32).toString("base64url");
|
|
}
|
|
|
|
/**
|
|
* Generate a 24-character nonce for authentication.
|
|
* Uses base64url encoding of 18 random bytes, truncated to 24 chars.
|
|
*/
|
|
export function generateNonce(): string {
|
|
const bytes = randomBytes(18);
|
|
return bytes.toString("base64url").slice(0, 24);
|
|
}
|
|
|
|
/**
|
|
* Default pairing code TTL in seconds (5 minutes)
|
|
*/
|
|
export const DEFAULT_PAIRING_TTL_SECONDS = 300;
|