UNPKG

totpify

Version:

Advanced TOTP Library with enhanced security features and algorithm support

78 lines 2.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.normalizeSecret = normalizeSecret; exports.decodeBase32 = decodeBase32; exports.generateHOTP = generateHOTP; exports.getCurrentTimestamp = getCurrentTimestamp; exports.getHashFunction = getHashFunction; function normalizeSecret(secret) { return secret.replace(/\s+/g, '').toUpperCase(); } function decodeBase32(base32) { const normalizedKey = normalizeSecret(base32).replace(/=+$/, ''); if (normalizedKey.length === 0) { throw new Error('Empty Base32 string'); } if (!/^[A-Z2-7]+$/.test(normalizedKey)) { throw new Error('Invalid base32 character in key'); } const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; let bits = 0; let value = 0; const result = []; for (let i = 0; i < normalizedKey.length; i++) { const char = normalizedKey.charAt(i); value = (value << 5) | alphabet.indexOf(char); bits += 5; if (bits >= 8) { result.push((value >>> (bits - 8)) & 0xff); bits -= 8; } } return new Uint8Array(result); } function generateHOTP(key, counter, algorithm = 'SHA-1', digits = 6) { let crypto; try { crypto = require('crypto'); } catch (e) { throw new Error('Node.js crypto library is required for HMAC operations'); } const counterBuffer = new Uint8Array(8); let tempCounter = counter; for (let i = 7; i >= 0; i--) { counterBuffer[i] = tempCounter & 0xff; tempCounter = tempCounter >>> 8; } const algoMap = { 'SHA-1': 'sha1', 'SHA-256': 'sha256', 'SHA-512': 'sha512' }; const hmac = crypto.createHmac(algoMap[algorithm], Buffer.from(key)); const digest = hmac.update(Buffer.from(counterBuffer)).digest(); const offset = digest[digest.length - 1] & 0x0f; const binary = ((digest[offset] & 0x7f) << 24) | ((digest[offset + 1] & 0xff) << 16) | ((digest[offset + 2] & 0xff) << 8) | (digest[offset + 3] & 0xff); const otp = binary % Math.pow(10, digits); return otp.toString().padStart(digits, '0'); } function getCurrentTimestamp() { return Math.floor(Date.now() / 1000); } function getHashFunction(algorithm) { switch (algorithm) { case 'SHA-1': return 'sha1'; case 'SHA-256': return 'sha256'; case 'SHA-512': return 'sha512'; default: throw new Error(`Unsupported algorithm: ${algorithm}`); } } //# sourceMappingURL=utils.js.map