import { createHash, randomInt, timingSafeEqual } from 'node:crypto' /** * OTP용 이메일 정규화(소문자·trim) * @param {string} email - 원본 * @returns {string} */ export const normalizeOtpEmail = (email) => String(email || '').trim().toLowerCase() /** * 6자리 숫자 인증 코드 생성 * @returns {string} */ export const generateSixDigitOtp = () => String(randomInt(0, 1_000_000)).padStart(6, '0') /** * OTP 코드 해시(hex) * @param {{ pepper: string, email: string, purpose: string, code: string }} input - 입력 * @returns {string} sha256 hex */ export const hashOtpCode = (input) => { const payload = `${String(input.pepper || '')}|${normalizeOtpEmail(input.email)}|${String(input.purpose || '')}|${String(input.code || '')}` return createHash('sha256').update(payload, 'utf8').digest('hex') } /** * 두 sha256 hex 문자열을 상수 시간으로 비교한다. * @param {string} a - hex * @param {string} b - hex * @returns {boolean} */ export const timingSafeEqualHex = (a, b) => { try { const ba = Buffer.from(String(a || ''), 'hex') const bb = Buffer.from(String(b || ''), 'hex') if (ba.length !== bb.length || ba.length === 0) { return false } return timingSafeEqual(ba, bb) } catch { return false } }