feat: create encryption and otp utils
This commit is contained in:
parent
975f5bc536
commit
96bb7e9a3d
3 changed files with 82 additions and 0 deletions
32
src/server/utils/__tests__/encryption.test.ts
Normal file
32
src/server/utils/__tests__/encryption.test.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { faker } from '@faker-js/faker';
|
||||
import { setConfig } from '../../core/TipiConfig';
|
||||
import { encrypt, decrypt } from '../encryption';
|
||||
|
||||
describe('Test: encrypt', () => {
|
||||
it('should encrypt the provided data', () => {
|
||||
// arrange
|
||||
setConfig('jwtSecret', faker.random.word());
|
||||
const data = faker.random.word();
|
||||
const salt = faker.random.word();
|
||||
|
||||
// act
|
||||
const encryptedData = encrypt(data, salt);
|
||||
|
||||
// assert
|
||||
expect(encryptedData).not.toEqual(data);
|
||||
});
|
||||
|
||||
it('should decrypt the provided data', () => {
|
||||
// arrange
|
||||
setConfig('jwtSecret', faker.random.word());
|
||||
const data = faker.random.word();
|
||||
const salt = faker.random.word();
|
||||
|
||||
// act
|
||||
const encryptedData = encrypt(data, salt);
|
||||
const decryptedData = decrypt(encryptedData, salt);
|
||||
|
||||
// assert
|
||||
expect(decryptedData).toEqual(data);
|
||||
});
|
||||
});
|
45
src/server/utils/encryption.ts
Normal file
45
src/server/utils/encryption.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import crypto from 'crypto';
|
||||
import { getConfig } from '../core/TipiConfig';
|
||||
|
||||
const algorithm = 'aes-256-gcm';
|
||||
const keyLength = 32;
|
||||
|
||||
/**
|
||||
* Given a string, encrypts it using the provided salt
|
||||
*
|
||||
* @param {string} data - The data to encrypt
|
||||
* @param {string} salt - The salt to use to encrypt the data
|
||||
* @returns {string} - The encrypted data
|
||||
*/
|
||||
export const encrypt = (data: string, salt: string) => {
|
||||
const key = crypto.pbkdf2Sync(getConfig().jwtSecret, salt, 100000, keyLength, 'sha256');
|
||||
const iv = crypto.randomBytes(12);
|
||||
|
||||
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
||||
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
||||
|
||||
const tag = cipher.getAuthTag();
|
||||
return `${iv.toString('hex')}:${encrypted.toString('hex')}:${tag.toString('hex')}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an encrypted string, decrypts it using the provided salt
|
||||
*
|
||||
* @param {string} encryptedData - The data to decrypt
|
||||
* @param {string} salt - The salt used to encrypt the data
|
||||
* @returns {string} - The decrypted data
|
||||
*/
|
||||
export const decrypt = (encryptedData: string, salt: string) => {
|
||||
const key = crypto.pbkdf2Sync(getConfig().jwtSecret, salt, 100000, keyLength, 'sha256');
|
||||
const parts = encryptedData.split(':');
|
||||
const iv = Buffer.from(parts.shift() as string, 'hex');
|
||||
const encrypted = Buffer.from(parts.shift() as string, 'hex');
|
||||
const tag = Buffer.from(parts.shift() as string, 'hex');
|
||||
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
||||
|
||||
decipher.setAuthTag(tag);
|
||||
let decrypted = decipher.update(encrypted);
|
||||
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
||||
|
||||
return decrypted.toString();
|
||||
};
|
5
src/server/utils/totp.ts
Normal file
5
src/server/utils/totp.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { Authenticator } from '@otplib/core';
|
||||
import { keyDecoder, keyEncoder } from '@otplib/plugin-thirty-two';
|
||||
import { createDigest, createRandomBytes } from '@otplib/plugin-crypto';
|
||||
|
||||
export const TotpAuthenticator = new Authenticator({ createDigest, createRandomBytes, keyEncoder, keyDecoder });
|
Loading…
Add table
Reference in a new issue