@jovijovi/two-fa.js
Version:
A two-factor authentication(2FA) based on HOTP & TOTP written in TypeScript
103 lines • 3.35 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenKey = exports.DecodeKey = exports.EncodeKey = exports.toBuffer = exports.GetCode = void 0;
const crypto_1 = require("crypto");
const random_1 = require("./random");
const options_1 = require("./options");
const base32 = __importStar(require("./base32"));
const CodeDigits6 = 6;
const CodeDigits7 = 7;
const CodeDigits8 = 8;
const power = new Map([
[CodeDigits6, 1e6],
[CodeDigits7, 1e7],
[CodeDigits8, 1e8],
]);
function GetCode(key, tm) {
const raw = Buffer.from(DecodeKey(key));
const code = tOTP(raw, tm ? tm : new Date().getTime(), CodeDigits6).toString();
if (code.length < CodeDigits6) {
return code.padStart(CodeDigits6, '0');
}
return code;
}
exports.GetCode = GetCode;
function checkDigits(digits) {
if (!power.has(digits)) {
throw new Error('invalid digits');
}
}
function toBuffer(value) {
let buf = Buffer.alloc(8);
let tmp = value;
for (let i = 0; i < 8; i++) {
buf[7 - i] = tmp & 0xFF;
tmp = tmp >> 8;
}
return buf;
}
exports.toBuffer = toBuffer;
function hOTP(key, counter, digits) {
checkDigits(digits);
const hmac = (0, crypto_1.createHmac)('sha1', key);
const digest = hmac.update(toBuffer(counter)).digest();
const bin = digest.subarray(digest[digest.length - 1] & 0x0F).readUInt32BE() & 0x7FFFFFFF;
return bin % power.get(digits);
}
function tOTP(key, tm, digits) {
return hOTP(key, Math.floor(tm / 30e3), digits);
}
// EncodeKey returns encoded key
function EncodeKey(raw, ...opt) {
const opts = (0, options_1.NewOptions)(...opt);
let key;
if (opts.withHash) {
const digest = opts.HashFunc.Hash(raw);
key = base32.Encode(digest).toUpperCase();
}
else {
key = base32.Encode(raw).toUpperCase();
}
// TODO: QR
if (opts.withQR) {
}
return key;
}
exports.EncodeKey = EncodeKey;
function DecodeKey(key) {
return base32.Decode(key);
}
exports.DecodeKey = DecodeKey;
// GenKey returns random encoded key
function GenKey(...opt) {
const val = (0, random_1.NewRand)();
if (!val) {
throw new Error('invalid random');
}
return EncodeKey(val.toString(), ...opt);
}
exports.GenKey = GenKey;
//# sourceMappingURL=twofa.js.map