mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-25 09:16:15 -04:00
feat(new-tool): added otp generator
This commit is contained in:
parent
ea5e7a7fc7
commit
5f16885923
6 changed files with 506 additions and 1 deletions
124
src/tools/otp-code-generator-and-validator/otp.service.test.ts
Normal file
124
src/tools/otp-code-generator-and-validator/otp.service.test.ts
Normal file
|
@ -0,0 +1,124 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
generateHOTP,
|
||||
hexToBytes,
|
||||
verifyHOTP,
|
||||
generateTOTP,
|
||||
verifyTOTP,
|
||||
buildKeyUri,
|
||||
base32toHex,
|
||||
} from './otp.service';
|
||||
|
||||
describe('otp functions', () => {
|
||||
describe('hexToBytes', () => {
|
||||
it('convert an hexstring to a byte array', () => {
|
||||
expect(hexToBytes('1')).to.eql([1]);
|
||||
expect(hexToBytes('ffffff')).to.eql([255, 255, 255]);
|
||||
expect(hexToBytes('000000000')).to.eql([0, 0, 0, 0, 0]);
|
||||
expect(hexToBytes('a3218bcef89')).to.eql([163, 33, 139, 206, 248, 9]);
|
||||
expect(hexToBytes('063679ca')).toEqual([6, 54, 121, 202]);
|
||||
expect(hexToBytes('0102030405060708090a0b0c0d0e0f')).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
|
||||
});
|
||||
});
|
||||
describe('base32tohex', () => {
|
||||
it('convert a base32 to hex string', () => {
|
||||
expect(base32toHex('ABCDEF')).to.eql('00443205');
|
||||
expect(base32toHex('7777')).to.eql('ffff0f');
|
||||
expect(base32toHex('JBSWY3DPEHPK3PXP')).to.eql('48656c6c6f21deadbeef');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateHOTP', () => {
|
||||
it('generates HOTP codes for a given counter', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
const hotpCodes = ['282760', '996554', '602287', '143627', '960129'];
|
||||
|
||||
for (const [counter, code] of hotpCodes.entries()) {
|
||||
expect(generateHOTP({ key, counter })).to.eql(code);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('verifyHOTP', () => {
|
||||
it('validate hotp for a given secret', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
const hotpCodes = ['282760', '996554', '602287', '143627', '960129'];
|
||||
|
||||
for (const [counter, token] of hotpCodes.entries()) {
|
||||
expect(verifyHOTP({ token, key, counter, window: 0 })).to.eql(true);
|
||||
}
|
||||
|
||||
expect(verifyHOTP({ token: 'INVALID', key })).to.eql(false);
|
||||
});
|
||||
|
||||
it('does not validate hotp out of sync', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
const token = '282760';
|
||||
|
||||
expect(verifyHOTP({ token, key, counter: 5, window: 2 })).to.eql(false);
|
||||
expect(verifyHOTP({ token, key, counter: 5, window: 5 })).to.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateTOTP', () => {
|
||||
it('generates TOTP codes', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
|
||||
const codes = [
|
||||
{ token: '282760', now: 0 },
|
||||
{ token: '341128', now: 1465324707000 },
|
||||
{ token: '089029', now: 1365324707000 },
|
||||
];
|
||||
|
||||
for (const { token, now } of codes) {
|
||||
expect(generateTOTP({ key, now })).to.eql(token);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('verifyTOTP', () => {
|
||||
it('verify TOTP in sync codes against a key', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
|
||||
const codes = [
|
||||
{ token: '282760', now: 0 },
|
||||
{ token: '341128', now: 1465324707000 },
|
||||
{ token: '089029', now: 1365324707000 },
|
||||
];
|
||||
|
||||
for (const { token, now } of codes) {
|
||||
expect(verifyTOTP({ key, token, now })).to.eql(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not validate totp out of sync', () => {
|
||||
const key = 'JBSWY3DPEHPK3PXP';
|
||||
const token = '635183';
|
||||
const now = 1661266455000;
|
||||
|
||||
expect(verifyTOTP({ key, token, now, window: 2 })).to.eql(true);
|
||||
expect(verifyTOTP({ key, token, now, window: 1 })).to.eql(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildKeyUri', () => {
|
||||
it('build a key uri string', () => {
|
||||
expect(buildKeyUri({ secret: 'JBSWY3DPEHPK3PXP' })).to.eql(
|
||||
'otpauth://totp/IT-Tools:demo-user?issuer=IT-Tools&secret=JBSWY3DPEHPK3PXP&algorithm=SHA1&digits=6&period=30',
|
||||
);
|
||||
|
||||
expect(
|
||||
buildKeyUri({
|
||||
secret: 'JBSWY3DPEHPK3PXP',
|
||||
app: 'app-name',
|
||||
account: 'account',
|
||||
algorithm: 'algo',
|
||||
digits: 7,
|
||||
period: 10,
|
||||
}),
|
||||
).to.eql(
|
||||
'otpauth://totp/app-name:account?issuer=app-name&secret=JBSWY3DPEHPK3PXP&algorithm=algo&digits=7&period=10',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue