mirror of
https://github.com/Wessel/Snowflakey.git
synced 2026-06-06 11:15:47 +02:00
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import Base32 from './base32'
|
|
import { createHmac, randomBytes } from 'crypto'
|
|
|
|
export default class OTP {
|
|
public seed: string;
|
|
|
|
constructor(seed: string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz!@#$-') {
|
|
this.seed = seed;
|
|
}
|
|
|
|
validateHotp(token: string, secret: any, counter: any): boolean {
|
|
const counterInt: number = parseInt(counter, 10) || 0;
|
|
if (!secret || !token || token.length !== 6 || isNaN(parseInt(token, 10))) return false;
|
|
|
|
return this._computeHotp(secret, counterInt) === token;
|
|
}
|
|
|
|
validateTotp(token: string, secret: string): boolean {
|
|
return this.validateHotp(token, secret, Math.floor(Date.now() / 30 / 1000));
|
|
}
|
|
|
|
generateKey(name: string = 'Secret Key', issuer: string = null, hotp: boolean = false): object {
|
|
const bytes: any = randomBytes(32);
|
|
const string: string[] = Array(32)
|
|
.fill(i => this.seed[Math.floor(bytes[i] / 255.0 * (this.seed.length - 1))])
|
|
.map((f, i) => f(i))
|
|
|
|
const key = {
|
|
raw: string.join(''),
|
|
base32: Base32.encode(string)
|
|
}
|
|
|
|
return Object.defineProperty(key, 'url', {
|
|
value: 'google_url',
|
|
writable: false,
|
|
get: () => `otpauth://${hotp ? 'h' : 't'}otp/${name}?secret=${key.base32}${issuer ? `&issuer=${issuer}` : ''}`
|
|
});
|
|
}
|
|
|
|
private _computeHotp(secret: any, counter: number): string {
|
|
secret = Base32.decode(secret);
|
|
|
|
let tmp: number = counter;
|
|
const chunks: Buffer = Buffer.alloc(8);
|
|
for (let i = 0; i < 8; i++) {
|
|
chunks[7 - i] = tmp & 0xff;
|
|
tmp = tmp >> 8;
|
|
}
|
|
|
|
const digest: Buffer = createHmac('sha1', secret).update(chunks).digest();
|
|
|
|
const offset: number = digest[digest.length - 1] & 0xf;
|
|
let code: number | string | number[] = (digest[offset] & 0x7f) << 24 |
|
|
(digest[offset + 1] & 0xff) << 16 |
|
|
(digest[offset + 2] & 0xff) << 8 |
|
|
(digest[offset + 3] & 0xff);
|
|
|
|
code = new Array(7).join('0') + code.toString(10);
|
|
return code.substr(-6);
|
|
}
|
|
}
|