Comparing version 1.1.1 to 1.2.0
@@ -0,0 +0,0 @@ /** |
@@ -1,11 +0,10 @@ | ||
"use strict"; | ||
const charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | ||
'use strict';const charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | ||
const byteTable = new Uint8Array([ | ||
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, | ||
0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, | ||
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, | ||
0xff, 0xff | ||
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, | ||
0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, | ||
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, | ||
0xff, 0xff | ||
]); | ||
@@ -19,3 +18,3 @@ /** | ||
function quintetCount(buffer) { | ||
return Math.ceil(buffer.length / 5); | ||
return Math.ceil(buffer.length / 5); | ||
} | ||
@@ -30,32 +29,35 @@ /** | ||
function encode(plain, { pad = true } = {}) { | ||
let index = 0; | ||
let encodedIndex = 0; | ||
let shiftIndex = 0; | ||
let digit = 0; | ||
const encoded = Array.from({ length: quintetCount(plain) * 8 }); | ||
while (index < plain.length) { | ||
const current = plain[+index]; | ||
if (shiftIndex > 3) { | ||
digit = current & (0xff >> shiftIndex); | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
digit = | ||
(digit << shiftIndex) | | ||
((index + 1 < plain.length ? plain[index + 1] : 0) >> (8 - shiftIndex)); | ||
index++; | ||
} else { | ||
digit = (current >> (8 - (shiftIndex + 5))) & 0x1f; | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
if (shiftIndex === 0) index++; | ||
let index = 0; | ||
let encodedIndex = 0; | ||
let shiftIndex = 0; | ||
let digit = 0; | ||
const encoded = Array.from({ length: quintetCount(plain) * 8 }); | ||
while (index < plain.length) { | ||
const current = plain[+index]; | ||
if (shiftIndex > 3) { | ||
digit = current & (0xff >> shiftIndex); | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
digit = | ||
(digit << shiftIndex) | | ||
((index + 1 < plain.length ? plain[index + 1] : 0) >> (8 - shiftIndex)); | ||
index++; | ||
} | ||
else { | ||
digit = (current >> (8 - (shiftIndex + 5))) & 0x1f; | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
if (shiftIndex === 0) | ||
index++; | ||
} | ||
encoded[+encodedIndex] = charTable.codePointAt(digit); | ||
encodedIndex++; | ||
} | ||
encoded[+encodedIndex] = charTable.codePointAt(digit); | ||
encodedIndex++; | ||
} | ||
if (pad) { | ||
for (index = encodedIndex; index < encoded.length; index++) { | ||
encoded[+index] = 0x3d; | ||
if (pad) { | ||
for (index = encodedIndex; index < encoded.length; index++) { | ||
encoded[+index] = 0x3d; | ||
} | ||
} | ||
} else { | ||
encoded.splice(encodedIndex); | ||
} | ||
return String.fromCharCode(...encoded); | ||
else { | ||
encoded.splice(encodedIndex); | ||
} | ||
return String.fromCharCode(...encoded); | ||
} | ||
@@ -70,39 +72,40 @@ /** | ||
function decode(encoded) { | ||
let shiftIndex = 0; | ||
let plainDigit = 0; | ||
let plainChar = 0; | ||
let plainPos = 0; | ||
const decoded = new Uint8Array(Math.ceil((encoded.length * 5) / 8)); | ||
const chars = encoded.split("").map((char) => char.charCodeAt(0)); | ||
for (let index = 0; index < encoded.length; index++) { | ||
if (chars[+index] === 0x3d) { | ||
break; | ||
} | ||
const encodedByte = chars[+index] - 0x30; | ||
if (encodedByte < byteTable.length) { | ||
plainDigit = byteTable[+encodedByte]; | ||
if (shiftIndex <= 3) { | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
if (shiftIndex === 0) { | ||
plainChar |= plainDigit; | ||
decoded[+plainPos] = plainChar; | ||
plainPos++; | ||
plainChar = 0; | ||
} else { | ||
plainChar |= 0xff & (plainDigit << (8 - shiftIndex)); | ||
let shiftIndex = 0; | ||
let plainDigit = 0; | ||
let plainChar = 0; | ||
let plainPos = 0; | ||
const decoded = new Uint8Array(Math.ceil((encoded.length * 5) / 8)); | ||
const chars = encoded.split("").map((char) => char.charCodeAt(0)); | ||
for (let index = 0; index < encoded.length; index++) { | ||
if (chars[+index] === 0x3d) { | ||
break; | ||
} | ||
} else { | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
plainChar |= 0xff & (plainDigit >>> shiftIndex); | ||
decoded[+plainPos] = plainChar; | ||
plainPos++; | ||
plainChar = 0xff & (plainDigit << (8 - shiftIndex)); | ||
} | ||
} else { | ||
throw new Error("Invalid input - it is not base32 encoded string"); | ||
const encodedByte = chars[+index] - 0x30; | ||
if (encodedByte < byteTable.length) { | ||
plainDigit = byteTable[+encodedByte]; | ||
if (shiftIndex <= 3) { | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
if (shiftIndex === 0) { | ||
plainChar |= plainDigit; | ||
decoded[+plainPos] = plainChar; | ||
plainPos++; | ||
plainChar = 0; | ||
} | ||
else { | ||
plainChar |= 0xff & (plainDigit << (8 - shiftIndex)); | ||
} | ||
} | ||
else { | ||
shiftIndex = (shiftIndex + 5) % 8; | ||
plainChar |= 0xff & (plainDigit >>> shiftIndex); | ||
decoded[+plainPos] = plainChar; | ||
plainPos++; | ||
plainChar = 0xff & (plainDigit << (8 - shiftIndex)); | ||
} | ||
} | ||
else { | ||
throw new Error("Invalid input - it is not base32 encoded string"); | ||
} | ||
} | ||
} | ||
return decoded.slice(0, plainPos); | ||
} | ||
exports.decode = decode; | ||
exports.encode = encode; | ||
return decoded.slice(0, plainPos); | ||
}exports.decode=decode;exports.encode=encode; |
@@ -0,0 +0,0 @@ /** |
@@ -1,3 +0,2 @@ | ||
"use strict"; | ||
/** | ||
'use strict';/** | ||
* | ||
@@ -9,8 +8,8 @@ * | ||
function hexToBytes(hex) { | ||
const bytes = new Uint8Array(hex.length / 2); | ||
for (let index = 0; index < bytes.length; index++) { | ||
const string = hex.slice(index * 2, index * 2 + 2); | ||
bytes[+index] = Number.parseInt(string, 16); | ||
} | ||
return bytes; | ||
const bytes = new Uint8Array(hex.length / 2); | ||
for (let index = 0; index < bytes.length; index++) { | ||
const string = hex.slice(index * 2, index * 2 + 2); | ||
bytes[+index] = Number.parseInt(string, 16); | ||
} | ||
return bytes; | ||
} | ||
@@ -24,11 +23,10 @@ /** | ||
function getBigIntBytes(number) { | ||
if (typeof BigInt !== "undefined") { | ||
const message = new Uint8Array(8); | ||
const view = new DataView(message.buffer); | ||
view.setBigUint64(0, BigInt(number), false); | ||
return message; | ||
} | ||
const hex = number.toString(16).padStart(16, "0"); | ||
return hexToBytes(hex); | ||
} | ||
exports.getBigIntBytes = getBigIntBytes; | ||
if (typeof BigInt !== "undefined") { | ||
const message = new Uint8Array(8); | ||
const view = new DataView(message.buffer); | ||
view.setBigUint64(0, BigInt(number), false); | ||
return message; | ||
} | ||
const hex = number.toString(16).padStart(16, "0"); | ||
return hexToBytes(hex); | ||
}exports.getBigIntBytes=getBigIntBytes; |
export { hmac, randomBytes } from "./crypto/node"; |
@@ -1,4 +0,1 @@ | ||
"use strict"; | ||
const node = require("./crypto/node.js"); | ||
exports.hmac = node.hmac; | ||
exports.randomBytes = node.randomBytes; | ||
'use strict';const node=require('./crypto/node.js');exports.hmac=node.hmac;exports.randomBytes=node.randomBytes; |
export { hmac, randomBytes } from "./crypto/browser"; |
@@ -0,0 +0,0 @@ import { Hmac } from "./hmac"; |
@@ -0,0 +0,0 @@ export declare const enum HmacAlgorithm { |
@@ -0,0 +0,0 @@ import type { Hmac } from "./hmac"; |
@@ -1,10 +0,6 @@ | ||
"use strict"; | ||
const crypto = require("crypto"); | ||
const hmac = async function hmac(algorithm, key, message) { | ||
return crypto.createHmac(algorithm, key).update(message).digest(); | ||
'use strict';const crypto=require('crypto');const hmac = async function hmac(algorithm, key, message) { | ||
return crypto.createHmac(algorithm, key).update(message).digest(); | ||
}; | ||
const randomBytes = function randomBytes(size) { | ||
return crypto.randomFillSync(new Uint8Array(size)); | ||
}; | ||
exports.hmac = hmac; | ||
exports.randomBytes = randomBytes; | ||
return crypto.randomFillSync(new Uint8Array(size)); | ||
};exports.hmac=hmac;exports.randomBytes=randomBytes; |
export type RandomBytes = (size: number) => Uint8Array; |
@@ -0,0 +0,0 @@ import type { Hmac } from "./crypto/hmac"; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
const hotp = require("./hotp.js"), | ||
uri = require("./uri.js"); | ||
/** | ||
'use strict';const hotp=require('./hotp.js'),uri=require('./uri.js');/** | ||
* | ||
@@ -11,58 +8,52 @@ * | ||
class HOTP { | ||
/** | ||
* Creates an instance of HOTP. | ||
* @param {Hmac} _hmac | ||
* @param {HOTPOptions} options | ||
* @memberof HOTP | ||
*/ | ||
constructor(_hmac, options) { | ||
this._hmac = _hmac; | ||
this.options = options; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} name | ||
* @param {string} issuer | ||
* @return {string} {string} | ||
* @memberof HOTP | ||
*/ | ||
getUri(name, issuer) { | ||
return uri.getKeyUri( | ||
Object.assign({ type: "hotp", name, issuer }, this.options) | ||
); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} code | ||
* @param {Partial<HOTPOptions>} [overrides] | ||
* @return {Promise<boolean>} {Promise<boolean>} | ||
* @memberof HOTP | ||
*/ | ||
async checkCode(code, overrides) { | ||
return code === (await this.generateCode(overrides)); | ||
} | ||
/** | ||
* | ||
* @param {Partial<HOTPOptions>} [overrides={}] | ||
* @return {Promise<string>} {Promise<string>} | ||
* @memberof HOTP | ||
*/ | ||
async generateCode(overrides = {}) { | ||
return await hotp.hotp( | ||
this._hmac, | ||
Object.assign(Object.assign({}, this.options), overrides) | ||
); | ||
} | ||
/** | ||
* | ||
* | ||
* @return {number} next value of the counter | ||
* @memberof HOTP | ||
*/ | ||
increment() { | ||
return ++this.options.counter; | ||
} | ||
} | ||
exports.HOTP = HOTP; | ||
/** | ||
* Creates an instance of HOTP. | ||
* @param {Hmac} _hmac | ||
* @param {HOTPOptions} options | ||
* @memberof HOTP | ||
*/ | ||
constructor(_hmac, options) { | ||
this._hmac = _hmac; | ||
this.options = options; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} name | ||
* @param {string} issuer | ||
* @return {string} {string} | ||
* @memberof HOTP | ||
*/ | ||
getUri(name, issuer) { | ||
return uri.getKeyUri(Object.assign({ type: "hotp", name, issuer }, this.options)); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} code | ||
* @param {Partial<HOTPOptions>} [overrides] | ||
* @return {Promise<boolean>} {Promise<boolean>} | ||
* @memberof HOTP | ||
*/ | ||
async checkCode(code, overrides) { | ||
return code === (await this.generateCode(overrides)); | ||
} | ||
/** | ||
* | ||
* @param {Partial<HOTPOptions>} [overrides={}] | ||
* @return {Promise<string>} {Promise<string>} | ||
* @memberof HOTP | ||
*/ | ||
async generateCode(overrides = {}) { | ||
return await hotp.hotp(this._hmac, Object.assign(Object.assign({}, this.options), overrides)); | ||
} | ||
/** | ||
* | ||
* | ||
* @return {number} next value of the counter | ||
* @memberof HOTP | ||
*/ | ||
increment() { | ||
return ++this.options.counter; | ||
} | ||
}exports.HOTP=HOTP; |
@@ -0,0 +0,0 @@ import type { Hmac } from "./crypto/hmac"; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
const bytes = require("./bytes.js"), | ||
hotp_options = require("./hotp.options.js"); | ||
/** | ||
'use strict';const bytes=require('./bytes.js'),hotp_options=require('./hotp.options.js');/** | ||
* Generates HOTP code from secret key, counter and options | ||
@@ -13,16 +10,8 @@ * | ||
async function hotp(hmac, options) { | ||
const merged = Object.assign( | ||
Object.assign({}, hotp_options.getDefaultHOTPOptions()), | ||
options | ||
); | ||
const digest = await hmac( | ||
merged.algorithm, | ||
merged.secret.bytes, | ||
bytes.getBigIntBytes(merged.counter) | ||
); | ||
const offset = digest[digest.length - 1] & 0xf; | ||
const view = new DataView(digest.buffer); | ||
const binary = view.getUint32(offset) & 2147483647; | ||
return binary.toString().slice(-merged.digits); | ||
} | ||
exports.hotp = hotp; | ||
const merged = Object.assign(Object.assign({}, hotp_options.getDefaultHOTPOptions()), options); | ||
const digest = await hmac(merged.algorithm, merged.secret.bytes, bytes.getBigIntBytes(merged.counter)); | ||
const offset = digest[digest.length - 1] & 0xf; | ||
const view = new DataView(digest.buffer); | ||
const binary = view.getUint32(offset) & 2147483647; | ||
return binary.toString().slice(-merged.digits); | ||
}exports.hotp=hotp; |
@@ -0,0 +0,0 @@ import { HmacAlgorithm } from "./crypto/hmac"; |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
const key = require("./key.js"); | ||
/** | ||
'use strict';const key=require('./key.js');/** | ||
* | ||
@@ -10,9 +8,8 @@ * | ||
function getDefaultHOTPOptions() { | ||
return { | ||
algorithm: "sha1", | ||
digits: 6, | ||
counter: 0, | ||
secret: new key.SecretKey(new Uint8Array()) | ||
}; | ||
} | ||
exports.getDefaultHOTPOptions = getDefaultHOTPOptions; | ||
return { | ||
algorithm: "sha1" , | ||
digits: 6, | ||
counter: 0, | ||
secret: new key.SecretKey(new Uint8Array()) | ||
}; | ||
}exports.getDefaultHOTPOptions=getDefaultHOTPOptions; |
@@ -0,0 +0,0 @@ export { SecretKey } from "./key"; |
@@ -1,21 +0,1 @@ | ||
"use strict"; | ||
const key = require("./key.js"), | ||
key_actions = require("./key.actions.js"), | ||
hotp = require("./hotp.js"), | ||
hotp_class = require("./hotp.class.js"), | ||
hotp_options = require("./hotp.options.js"), | ||
totp = require("./totp.js"), | ||
totp_class = require("./totp.class.js"), | ||
totp_options = require("./totp.options.js"), | ||
uri = require("./uri.js"); | ||
exports.SecretKey = key.SecretKey; | ||
exports.exportKey = key_actions.exportKey; | ||
exports.generateKey = key_actions.generateKey; | ||
exports.importKey = key_actions.importKey; | ||
exports.hotp = hotp.hotp; | ||
exports.HOTP = hotp_class.HOTP; | ||
exports.getDefaultHOTPOptions = hotp_options.getDefaultHOTPOptions; | ||
exports.totp = totp.totp; | ||
exports.TOTP = totp_class.TOTP; | ||
exports.getDefaultTOTPOptions = totp_options.getDefaultTOTPOptions; | ||
exports.getKeyUri = uri.getKeyUri; | ||
'use strict';const key=require('./key.js'),key_actions=require('./key.actions.js'),hotp=require('./hotp.js'),hotp_class=require('./hotp.class.js'),hotp_options=require('./hotp.options.js'),totp=require('./totp.js'),totp_class=require('./totp.class.js'),totp_options=require('./totp.options.js'),uri=require('./uri.js');exports.SecretKey=key.SecretKey;exports.exportKey=key_actions.exportKey;exports.generateKey=key_actions.generateKey;exports.importKey=key_actions.importKey;exports.hotp=hotp.hotp;exports.HOTP=hotp_class.HOTP;exports.getDefaultHOTPOptions=hotp_options.getDefaultHOTPOptions;exports.totp=totp.totp;exports.TOTP=totp_class.TOTP;exports.getDefaultTOTPOptions=totp_options.getDefaultTOTPOptions;exports.getKeyUri=uri.getKeyUri; |
@@ -0,0 +0,0 @@ import type { RandomBytes } from "./crypto/random"; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
const base32 = require("./base32.js"), | ||
key = require("./key.js"); | ||
/** | ||
'use strict';const base32=require('./base32.js'),key=require('./key.js');/** | ||
* | ||
@@ -13,3 +10,3 @@ * | ||
function generateKey(random, size = 10) { | ||
return new key.SecretKey(random(size)); | ||
return new key.SecretKey(random(size)); | ||
} | ||
@@ -24,3 +21,3 @@ /** | ||
function importKey(base32text) { | ||
return new key.SecretKey(base32.decode(base32text)); | ||
return new key.SecretKey(base32.decode(base32text)); | ||
} | ||
@@ -35,6 +32,3 @@ /** | ||
function exportKey(key) { | ||
return base32.encode(key.bytes, { pad: false }); | ||
} | ||
exports.exportKey = exportKey; | ||
exports.generateKey = generateKey; | ||
exports.importKey = importKey; | ||
return base32.encode(key.bytes, { pad: false }); | ||
}exports.exportKey=exportKey;exports.generateKey=generateKey;exports.importKey=importKey; |
@@ -0,0 +0,0 @@ /** |
@@ -1,3 +0,2 @@ | ||
"use strict"; | ||
/** | ||
'use strict';/** | ||
* | ||
@@ -9,11 +8,10 @@ * | ||
class SecretKey { | ||
/** | ||
* Creates an instance of SecretKey. | ||
* @param {Uint8Array} bytes | ||
* @memberof SecretKey | ||
*/ | ||
constructor(bytes) { | ||
this.bytes = bytes; | ||
} | ||
} | ||
exports.SecretKey = SecretKey; | ||
/** | ||
* Creates an instance of SecretKey. | ||
* @param {Uint8Array} bytes | ||
* @memberof SecretKey | ||
*/ | ||
constructor(bytes) { | ||
this.bytes = bytes; | ||
} | ||
}exports.SecretKey=SecretKey; |
@@ -0,0 +0,0 @@ import type { Hmac } from "./crypto/hmac"; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
const totp = require("./totp.js"), | ||
uri = require("./uri.js"); | ||
/** | ||
'use strict';const totp=require('./totp.js'),uri=require('./uri.js');/** | ||
* | ||
@@ -11,49 +8,43 @@ * | ||
class TOTP { | ||
/** | ||
* Creates an instance of TOTP. | ||
* @param {Hmac} _hmac | ||
* @param {TOTPOptions} options | ||
* @memberof TOTP | ||
*/ | ||
constructor(_hmac, options) { | ||
this._hmac = _hmac; | ||
this.options = options; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} name | ||
* @param {string} issuer | ||
* @return {string} {string} | ||
* @memberof TOTP | ||
*/ | ||
getUri(name, issuer) { | ||
return uri.getKeyUri( | ||
Object.assign({ type: "totp", name, issuer }, this.options) | ||
); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} code | ||
* @param {Partial<TOTPOptions>} [overrides] | ||
* @return {Promise<boolean>} {Promise<boolean>} | ||
* @memberof TOTP | ||
*/ | ||
async checkCode(code, overrides) { | ||
return code === (await this.generateCode(overrides)); | ||
} | ||
/** | ||
* | ||
* @param {Partial<TOTPOptions>} [overrides={}] | ||
* @return {Promise<string>} {Promise<string>} | ||
* @memberof TOTP | ||
*/ | ||
async generateCode(overrides = {}) { | ||
return await totp.totp( | ||
this._hmac, | ||
Object.assign(Object.assign({}, this.options), overrides) | ||
); | ||
} | ||
} | ||
exports.TOTP = TOTP; | ||
/** | ||
* Creates an instance of TOTP. | ||
* @param {Hmac} _hmac | ||
* @param {TOTPOptions} options | ||
* @memberof TOTP | ||
*/ | ||
constructor(_hmac, options) { | ||
this._hmac = _hmac; | ||
this.options = options; | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} name | ||
* @param {string} issuer | ||
* @return {string} {string} | ||
* @memberof TOTP | ||
*/ | ||
getUri(name, issuer) { | ||
return uri.getKeyUri(Object.assign({ type: "totp", name, issuer }, this.options)); | ||
} | ||
/** | ||
* | ||
* | ||
* @param {string} code | ||
* @param {Partial<TOTPOptions>} [overrides] | ||
* @return {Promise<boolean>} {Promise<boolean>} | ||
* @memberof TOTP | ||
*/ | ||
async checkCode(code, overrides) { | ||
return code === (await this.generateCode(overrides)); | ||
} | ||
/** | ||
* | ||
* @param {Partial<TOTPOptions>} [overrides={}] | ||
* @return {Promise<string>} {Promise<string>} | ||
* @memberof TOTP | ||
*/ | ||
async generateCode(overrides = {}) { | ||
return await totp.totp(this._hmac, Object.assign(Object.assign({}, this.options), overrides)); | ||
} | ||
}exports.TOTP=TOTP; |
@@ -0,0 +0,0 @@ import { Hmac } from "./crypto/hmac"; |
@@ -1,9 +0,5 @@ | ||
"use strict"; | ||
const hotp = require("./hotp.js"), | ||
key = require("./key.js"), | ||
totp_options = require("./totp.options.js"); | ||
const keyLengths = new Map([ | ||
["sha1", 20], | ||
["sha256", 32], | ||
["sha512", 64] | ||
'use strict';const hotp=require('./hotp.js'),key=require('./key.js'),totp_options=require('./totp.options.js');const keyLengths = new Map([ | ||
["sha1" , 20], | ||
["sha256" , 32], | ||
["sha512" , 64] | ||
]); | ||
@@ -18,8 +14,8 @@ /** | ||
function pad(buffer, length) { | ||
const factor = Math.ceil(length / buffer.length); | ||
const double = new Uint8Array(buffer.length * factor); | ||
for (let index = 0; index < factor; index++) { | ||
double.set(buffer, buffer.length * index); | ||
} | ||
return double.slice(0, length); | ||
const factor = Math.ceil(length / buffer.length); | ||
const double = new Uint8Array(buffer.length * factor); | ||
for (let index = 0; index < factor; index++) { | ||
double.set(buffer, buffer.length * index); | ||
} | ||
return double.slice(0, length); | ||
} | ||
@@ -36,24 +32,20 @@ /** | ||
async function totp(hmac, options) { | ||
const merged = Object.assign( | ||
Object.assign({}, totp_options.getDefaultTOTPOptions()), | ||
options | ||
); | ||
const counter = Math.floor(merged.now.getTime() / 1000 / merged.stepSeconds); | ||
let bytes = new Uint8Array(options.secret.bytes); | ||
if (merged.pad) { | ||
const length = keyLengths.get(merged.algorithm); | ||
if (length === undefined) { | ||
throw new Error(`Invalid hmac algorithm: "${merged.algorithm}"`); | ||
const merged = Object.assign(Object.assign({}, totp_options.getDefaultTOTPOptions()), options); | ||
const counter = Math.floor(merged.now.getTime() / 1000 / merged.stepSeconds); | ||
let bytes = new Uint8Array(options.secret.bytes); | ||
if (merged.pad) { | ||
const length = keyLengths.get(merged.algorithm); | ||
if (length === undefined) { | ||
throw new Error(`Invalid hmac algorithm: "${merged.algorithm}"`); | ||
} | ||
if (bytes.length < length) { | ||
bytes = pad(bytes, length); | ||
} | ||
} | ||
if (bytes.length < length) { | ||
bytes = pad(bytes, length); | ||
} | ||
} | ||
return await hotp.hotp(hmac, { | ||
secret: new key.SecretKey(bytes), | ||
algorithm: merged.algorithm, | ||
digits: merged.digits, | ||
counter | ||
}); | ||
} | ||
exports.totp = totp; | ||
return await hotp.hotp(hmac, { | ||
secret: new key.SecretKey(bytes), | ||
algorithm: merged.algorithm, | ||
digits: merged.digits, | ||
counter | ||
}); | ||
}exports.totp=totp; |
@@ -0,0 +0,0 @@ import { HmacAlgorithm } from "./crypto/hmac"; |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
const key = require("./key.js"); | ||
/** | ||
'use strict';const key=require('./key.js');/** | ||
* | ||
@@ -10,11 +8,10 @@ * | ||
function getDefaultTOTPOptions() { | ||
return { | ||
algorithm: "sha1", | ||
digits: 6, | ||
now: new Date(), | ||
secret: new key.SecretKey(new Uint8Array()), | ||
stepSeconds: 30, | ||
pad: false | ||
}; | ||
} | ||
exports.getDefaultTOTPOptions = getDefaultTOTPOptions; | ||
return { | ||
algorithm: "sha1" , | ||
digits: 6, | ||
now: new Date(), | ||
secret: new key.SecretKey(new Uint8Array()), | ||
stepSeconds: 30, | ||
pad: false | ||
}; | ||
}exports.getDefaultTOTPOptions=getDefaultTOTPOptions; |
@@ -0,0 +0,0 @@ import { HOTPOptions } from "./hotp.options"; |
@@ -1,6 +0,2 @@ | ||
"use strict"; | ||
const hotp_options = require("./hotp.options.js"), | ||
totp_options = require("./totp.options.js"), | ||
key_actions = require("./key.actions.js"); | ||
/** | ||
'use strict';const hotp_options=require('./hotp.options.js'),totp_options=require('./totp.options.js'),key_actions=require('./key.actions.js');/** | ||
* | ||
@@ -13,43 +9,34 @@ * | ||
function getKeyUri(options) { | ||
const title = options.issuer | ||
? `${encodeURIComponent(options.issuer)}:${encodeURIComponent( | ||
options.name | ||
)}` | ||
: encodeURIComponent(options.name); | ||
const url = new URL(`otpauth://${options.type}/${title}`); | ||
url.searchParams.set("secret", key_actions.exportKey(options.secret)); | ||
if (options.issuer) { | ||
url.searchParams.set("issuer", options.issuer); | ||
} | ||
let algorithm; | ||
let digits; | ||
switch (options.type) { | ||
case "hotp": { | ||
const merged = Object.assign( | ||
Object.assign({}, hotp_options.getDefaultHOTPOptions()), | ||
options | ||
); | ||
algorithm = merged.algorithm; | ||
digits = merged.digits; | ||
url.searchParams.set("counter", merged.counter.toString()); | ||
break; | ||
const title = options.issuer | ||
? `${encodeURIComponent(options.issuer)}:${encodeURIComponent(options.name)}` | ||
: encodeURIComponent(options.name); | ||
const url = new URL(`otpauth://${options.type}/${title}`); | ||
url.searchParams.set("secret", key_actions.exportKey(options.secret)); | ||
if (options.issuer) { | ||
url.searchParams.set("issuer", options.issuer); | ||
} | ||
case "totp": { | ||
const merged = Object.assign( | ||
Object.assign({}, totp_options.getDefaultTOTPOptions()), | ||
options | ||
); | ||
algorithm = merged.algorithm; | ||
digits = merged.digits; | ||
url.searchParams.set("period", merged.stepSeconds.toString()); | ||
break; | ||
let algorithm; | ||
let digits; | ||
switch (options.type) { | ||
case "hotp": { | ||
const merged = Object.assign(Object.assign({}, hotp_options.getDefaultHOTPOptions()), options); | ||
algorithm = merged.algorithm; | ||
digits = merged.digits; | ||
url.searchParams.set("counter", merged.counter.toString()); | ||
break; | ||
} | ||
case "totp": { | ||
const merged = Object.assign(Object.assign({}, totp_options.getDefaultTOTPOptions()), options); | ||
algorithm = merged.algorithm; | ||
digits = merged.digits; | ||
url.searchParams.set("period", merged.stepSeconds.toString()); | ||
break; | ||
} | ||
default: { | ||
throw new Error(`Invalid method type: "${options.type}"`); | ||
} | ||
} | ||
default: { | ||
throw new Error(`Invalid method type: "${options.type}"`); | ||
} | ||
} | ||
url.searchParams.set("algorithm", algorithm.toUpperCase()); | ||
url.searchParams.set("digits", digits.toString()); | ||
return url.toString(); | ||
} | ||
exports.getKeyUri = getKeyUri; | ||
url.searchParams.set("algorithm", algorithm.toUpperCase()); | ||
url.searchParams.set("digits", digits.toString()); | ||
return url.toString(); | ||
}exports.getKeyUri=getKeyUri; |
{ | ||
"name": "otp-io", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "🕖 Typed library to work 2fa via Google Authenticator/Time-based TOTP/Hmac-based HOTP", | ||
@@ -41,2 +41,14 @@ "scripts": { | ||
"types": "./crypto-web.d.ts" | ||
}, | ||
"./crypto": { | ||
"node": { | ||
"require": "./crypto-node.js", | ||
"import": "./crypto-node.mjs", | ||
"types": "./crypto-node.d.ts" | ||
}, | ||
"default": { | ||
"require": "./crypto-web.js", | ||
"import": "./crypto-web.mjs", | ||
"types": "./crypto-web.d.ts" | ||
} | ||
} | ||
@@ -102,24 +114,24 @@ }, | ||
"@typescript-eslint/parser": "^5.44.0", | ||
"eslint": "^8.34.0", | ||
"eslint": "^8.44.0", | ||
"eslint-config-google": "^0.14.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-config-prettier": "^8.8.0", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-prettier": "^5.0.0", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"eslint-plugin-security": "^1.7.1", | ||
"eslint-plugin-unicorn": "^45.0.2", | ||
"glob": "^8.1.0", | ||
"jest": "^29.3.1", | ||
"prettier": "^2.8.4", | ||
"rimraf": "^4.1.2", | ||
"rollup": "^3.17.1", | ||
"eslint-plugin-unicorn": "^47.0.0", | ||
"glob": "^10.3.3", | ||
"jest": "^29.6.1", | ||
"prettier": "^3.0.0", | ||
"rimraf": "^5.0.1", | ||
"rollup": "^3.26.2", | ||
"rollup-plugin-cleanup": "^3.2.1", | ||
"rollup-plugin-prettier": "^3.0.0", | ||
"rollup-plugin-typescript2": "^0.34.1", | ||
"ts-jest": "^29.0.3", | ||
"rollup-plugin-typescript2": "^0.35.0", | ||
"ts-jest": "^29.1.1", | ||
"ts-node": "^10.9.1", | ||
"typedoc": "^0.23.21", | ||
"typedoc-plugin-markdown": "^3.13.6", | ||
"typedoc-plugin-missing-exports": "^1.0.0", | ||
"typescript": "^4.9.5" | ||
"typedoc": "^0.24.8", | ||
"typedoc-plugin-markdown": "^3.15.3", | ||
"typedoc-plugin-missing-exports": "^2.0.0", | ||
"typescript": "^5.1.6" | ||
}, | ||
@@ -129,2 +141,2 @@ "engines": { | ||
} | ||
} | ||
} |
@@ -52,4 +52,6 @@ # OTP io | ||
import { totp, generateKey, getKeyUri } from "otp-io"; | ||
// 2. Import crypto adapter. Either `crypto-node` or `crypto-web` - API is identical | ||
import { hmac, randomBytes } from "otp-io/crypto-node"; | ||
// 2. Import crypto adapter. | ||
// Specify `crypto-node` or `crypto-web` if node/bundler cannot | ||
// detect correct version | ||
import { hmac, randomBytes } from "otp-io/crypto"; | ||
@@ -56,0 +58,0 @@ // 3. Get key from somewhere. Or generate it |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83
70281
82
1900
1