@epic-web/totp
Advanced tools
Comparing version 2.1.1 to 2.2.0
27
index.js
@@ -47,3 +47,3 @@ /** | ||
charSet = DEFAULT_CHAR_SET, | ||
} = {}, | ||
} = {} | ||
) { | ||
@@ -56,17 +56,22 @@ const byteCounter = intToBytes(counter) | ||
false, | ||
['sign'], | ||
['sign'] | ||
) | ||
const signature = await crypto.subtle.sign('HMAC', key, byteCounter) | ||
const hashBytes = new Uint8Array(signature) | ||
const offset = hashBytes[19] & 0xf | ||
let hotpVal = | ||
((hashBytes[offset] & 0x7f) << 24) | | ||
((hashBytes[offset + 1] & 0xff) << 16) | | ||
((hashBytes[offset + 2] & 0xff) << 8) | | ||
(hashBytes[offset + 3] & 0xff) | ||
// Use more bytes for longer OTPs | ||
const bytesNeeded = Math.ceil((digits * Math.log2(charSet.length)) / 8) | ||
const offset = hashBytes[hashBytes.length - 1] & 0xf | ||
// Convert bytes to BigInt for larger numbers | ||
let hotpVal = 0n | ||
for (let i = 0; i < Math.min(bytesNeeded, hashBytes.length - offset); i++) { | ||
hotpVal = (hotpVal << 8n) | BigInt(hashBytes[offset + i]) | ||
} | ||
let hotp = '' | ||
const charSetLength = BigInt(charSet.length) | ||
for (let i = 0; i < digits; i++) { | ||
hotp = charSet.charAt(hotpVal % charSet.length) + hotp | ||
hotpVal = Math.floor(hotpVal / charSet.length) | ||
hotp = charSet.charAt(Number(hotpVal % charSetLength)) + hotp | ||
hotpVal = hotpVal / charSetLength | ||
} | ||
@@ -106,3 +111,3 @@ | ||
window = DEFAULT_WINDOW, | ||
} = {}, | ||
} = {} | ||
) { | ||
@@ -109,0 +114,0 @@ for (let i = counter - window; i <= counter + window; ++i) { |
@@ -17,3 +17,3 @@ { | ||
}, | ||
"version": "2.1.1", | ||
"version": "2.2.0", | ||
"description": "Create and verify cryptographically secure Time-based One-time Passwords (TOTP) using the HMAC-based One-time Password (HOTP) algorithm.", | ||
@@ -20,0 +20,0 @@ "main": "index.js", |
25340
343