import { Injectable } from '@nestjs/common'; import * as crypto from 'crypto'; import { v4 } from 'uuid'; const IV_LENGTH = 16; const ALGORITHM = 'aes-256-cbc'; @Injectable() export class TokenService { public generateString(length: number): string { return crypto.randomBytes(length).toString('hex').slice(0, length); } public createUUID(): string { return v4(); } // https://stackoverflow.com/q/52212430 /** * Symmetric encryption function * @param text String to encrypt * @param key Encryption key * @returns Encrypted text */ public encrypt(text: string, key: string): string { const iv = crypto.randomBytes(IV_LENGTH); const cipher = crypto.createCipheriv( ALGORITHM, Buffer.from(key, 'hex'), iv, ); let encrypted = cipher.update(text); encrypted = Buffer.concat([encrypted, cipher.final()]); return `${iv.toString('hex')}:${encrypted.toString('hex')}`; } /** * Symmetric decryption function * @param text Encrypted string * @param key Decryption key * @returns Decrypted text */ public decrypt(text: string, key: string): string { const [iv, encryptedText] = text .split(':') .map((part) => Buffer.from(part, 'hex')); const decipher = crypto.createDecipheriv( ALGORITHM, Buffer.from(key, 'hex'), iv, ); let decrypted = decipher.update(encryptedText); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); } public async encryptChallenge( challenge: Record, ): Promise { return this.encrypt( JSON.stringify(challenge), process.env.CHALLENGE_SECRET, ); } public async decryptChallenge( challenge: string, ): Promise> { return JSON.parse(this.decrypt(challenge, process.env.CHALLENGE_SECRET)); } }