3 const HOTP
= require('./hotp');
5 class TimeBasedOneTimePassword
extends HOTP
{
8 * @param {Object} options
9 * @param {Number} options.codeLength
10 * @param {Buffer|String} options.key
11 * @param {String} options.keyEncoding
12 * @param {String} options.algorithm
13 * @param {Number} options.timeStepSeconds
14 * @param {Number} options.timeStepStartSeconds
15 * @param {Number} options.driftForward
16 * @param {Number} options.driftBackward
18 constructor(options
) {
19 const _options
= { ...options
};
22 0n
, // check now first
23 ...Array
.from({ length: this.driftBackward
}, (v
, k
) => BigInt(-(k
+ 1))),
24 ...Array
.from({ length: this.driftForward
}, (v
, k
) => BigInt(k
+ 1)),
28 static get _algorithmKeyLengths() {
30 ...super._algorithmKeyLengths
,
37 * The type used when constructing the otpauth URI.
44 * Derive counter from epoch.
47 const epoch
= Math
.floor(Date
.now() / 1000);
48 return BigInt(Math
.floor((epoch
- this.timeStepStartSeconds
) / this.timeStepSeconds
));
51 set counter(_
) { /* ignore assignment */ } // eslint-disable-line class-methods-use-this
53 static get _defaultOptions() {
54 const options
= Object
.assign(super._defaultOptions
, {
56 timeStepStartSeconds: 0,
60 delete options
.counter
;
66 * @param {BigInt=} count
69 generate(count
= this.counter
) {
70 return super.generate(count
);
75 * @param {String} hotp
76 * @param {BigInt=} count
79 validate(hotp
, count
) {
80 const counter
= count
?? this.counter
;
81 for (const offset
of this.driftOffsets
) {
82 const codeString
= this.generate(counter
+ offset
);
83 if (codeString
=== hotp
.trim()) {
92 module
.exports
= TimeBasedOneTimePassword
;