Skip to content

Commit c513390

Browse files
authored
feat: add loose type hinting for hash algorithm options (#17)
* feat: add loose type hinting for hash algorithm options * chore(docs): add link to all available algorithms
1 parent 70a03de commit c513390

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

index.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
import base32Encode from 'base32-encode'
55
import base32Decode from 'base32-decode'
66

7+
/**
8+
* @typedef {'SHA-1' | 'SHA-256' | 'SHA-386' | 'SHA-512' | string & {}} HashAlgorithm
9+
*
10+
* For all available algorithms, refer to the following:
11+
* https://developer.mozilla.org/en-US/docs/Web/API/HmacImportParams#hash
12+
*/
13+
714
// SHA-1 is not secure, but in the context of TOTPs, it's unrealistic to expect
815
// security issues. Also, it's the default for compatibility with OTP apps.
916
// That said, if you're acting the role of both client and server and your TOTP
@@ -25,7 +32,7 @@ const DEFAULT_PERIOD = 30
2532
* Defaults to 0.
2633
* @param {number} [options.digits=6] - The number of digits to use for the
2734
* HOTP. Defaults to 6.
28-
* @param {string} [options.algorithm='SHA-1'] - The algorithm to use for the
35+
* @param {HashAlgorithm} [options.algorithm='SHA-1'] - The algorithm to use for the
2936
* HOTP. Defaults to 'SHA-1'.
3037
* @param {string} [options.charSet='0123456789'] - The character set to use, defaults to the numbers 0-9.
3138
* @returns {Promise<string>} The generated HOTP.
@@ -37,15 +44,15 @@ async function generateHOTP(
3744
digits = DEFAULT_DIGITS,
3845
algorithm = DEFAULT_ALGORITHM,
3946
charSet = DEFAULT_CHAR_SET,
40-
} = {}
47+
} = {},
4148
) {
4249
const byteCounter = intToBytes(counter)
4350
const key = await crypto.subtle.importKey(
4451
'raw',
4552
secret,
4653
{ name: 'HMAC', hash: algorithm },
4754
false,
48-
['sign']
55+
['sign'],
4956
)
5057
const signature = await crypto.subtle.sign('HMAC', key, byteCounter)
5158
const hashBytes = new Uint8Array(signature)
@@ -76,7 +83,7 @@ async function generateHOTP(
7683
* Defaults to 0.
7784
* @param {number} [options.digits=6] - The number of digits to use for the
7885
* HOTP. Defaults to 6.
79-
* @param {string} [options.algorithm='SHA-1'] - The algorithm to use for the
86+
* @param {HashAlgorithm} [options.algorithm='SHA-1'] - The algorithm to use for the
8087
* HOTP. Defaults to 'SHA-1'.
8188
* @param {string} [options.charSet='0123456789'] - The character set to use, defaults to the numbers 0-9.
8289
* @param {number} [options.window=1] - The number of counter values to check
@@ -94,11 +101,16 @@ async function verifyHOTP(
94101
algorithm = DEFAULT_ALGORITHM,
95102
charSet = DEFAULT_CHAR_SET,
96103
window = DEFAULT_WINDOW,
97-
} = {}
104+
} = {},
98105
) {
99106
for (let i = counter - window; i <= counter + window; ++i) {
100107
if (
101-
await generateHOTP(secret, { counter: i, digits, algorithm, charSet }) === otp
108+
(await generateHOTP(secret, {
109+
counter: i,
110+
digits,
111+
algorithm,
112+
charSet,
113+
})) === otp
102114
) {
103115
return { delta: i - counter }
104116
}
@@ -115,7 +127,7 @@ async function verifyHOTP(
115127
* @param {number} [options.period=30] The number of seconds for the OTP to be
116128
* valid. Defaults to 30.
117129
* @param {number} [options.digits=6] The length of the OTP. Defaults to 6.
118-
* @param {string} [options.algorithm='SHA-1'] The algorithm to use. Defaults to
130+
* @param {HashAlgorithm} [options.algorithm='SHA-1'] The algorithm to use. Defaults to
119131
* SHA-1.
120132
* @param {string} [options.charSet='0123456789'] - The character set to use, defaults to the numbers 0-9.
121133
* @param {string} [options.secret] The secret to use for the TOTP. It should be
@@ -148,7 +160,7 @@ export async function generateTOTP({
148160
* @param {Object} options Configuration options for the TOTP Auth URI.
149161
* @param {number} options.period The number of seconds for the OTP to be valid.
150162
* @param {number} options.digits The length of the OTP.
151-
* @param {string} options.algorithm The algorithm to use.
163+
* @param {HashAlgorithm} options.algorithm The algorithm to use.
152164
* @param {string} options.secret The secret to use for the TOTP Auth URI.
153165
* @param {string} options.accountName A way to uniquely identify this Auth URI
154166
* (in case they have multiple of these).
@@ -189,7 +201,7 @@ export function getTOTPAuthUri({
189201
* @param {string} options.secret The secret to use for the TOTP.
190202
* @param {number} [options.period] The number of seconds for the OTP to be valid.
191203
* @param {number} [options.digits] The length of the OTP.
192-
* @param {string} [options.algorithm] The algorithm to use.
204+
* @param {HashAlgorithm} [options.algorithm] The algorithm to use.
193205
* @param {string} [options.charSet] - The character set to use, defaults to the numbers 0-9.
194206
* @param {number} [options.window] The number of OTPs to check before and after
195207
* the current OTP. Defaults to 1.
@@ -250,4 +262,4 @@ function getCounter(period = DEFAULT_PERIOD) {
250262
const now = new Date().getTime()
251263
const counter = Math.floor(now / 1000 / period)
252264
return counter
253-
}
265+
}

0 commit comments

Comments
 (0)