import { readFileSync } from "node:fs"; import { env } from "./env.js"; /** * JWT RS256 密钥对加载(president §2.15:本地文件密钥)。 * * - 私钥:IAM 签发 access_token / refresh_token * - 公钥:api-gateway 通过 JWKS 或 gRPC GetPublicKey 拉取验签 * * 启动时一次性加载到内存,避免每次签名/验签的 IO 开销。 * kid(Key ID)用于 JWKS 端点多密钥轮换场景下标识密钥。 */ export interface JwtKeyPair { privateKey: string; publicKey: string; kid: string; alg: "RS256"; } let keyPair: JwtKeyPair | null = null; export function getJwtKeyPair(): JwtKeyPair { if (!keyPair) { const privateKey = readFileSync(env.IAM_PRIVATE_KEY_PATH, "utf-8"); const publicKey = readFileSync(env.IAM_PUBLIC_KEY_PATH, "utf-8"); keyPair = { privateKey, publicKey, kid: env.JWT_KEY_ID, alg: "RS256", }; } return keyPair; } /** * TTL 计算:将 "15m" / "7d" 等字符串转为秒数。 * 用于 JWT expiresIn 配置与响应中的 expires_in 字段。 */ export function ttlToSeconds(ttl: string): number { const match = /^(\d+)([smhd])$/.exec(ttl); if (!match || match[1] === undefined || match[2] === undefined) { throw new Error(`Invalid TTL format: ${ttl}`); } const value = Number.parseInt(match[1], 10); const unit = match[2] as "s" | "m" | "h" | "d"; const multipliers: Record<"s" | "m" | "h" | "d", number> = { s: 1, m: 60, h: 3600, d: 86400, }; return value * multipliers[unit]; }