import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import * as CryptoJS from 'crypto-js'; import { ConfigService } from '@nestjs/config'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; @Injectable() export class PasswordEncryptionService { constructor(private readonly configService: ConfigService) {} encrypt(plainText: string, secretKey: string): string { const keyBytes = CryptoJS.enc.Utf8.parse(secretKey); const encrypted = CryptoJS.AES.encrypt(plainText, keyBytes, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, }); return encrypted.ciphertext.toString(CryptoJS.enc.Hex); } decrypt(encryptedText: string, secretKey: string): string { const keyBytes = CryptoJS.enc.Utf8.parse(secretKey); const decrypted = CryptoJS.AES.decrypt( { ciphertext: CryptoJS.enc.Hex.parse(encryptedText), } as any, keyBytes, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, }, ); return decrypted.toString(CryptoJS.enc.Utf8); } generateEncryptedPassword( plainTextPassword: string, ticketKey: string, ): string { try { const accessSecret = this.configService.get( 'auth-config.SECRET_KEY', ); // The accessSecret must be 32 bytes, ensure it is properly padded or truncated const paddedAccessSecret = accessSecret .padEnd(32, EnableDisableStatusEnum.DISABLED) .slice(0, 32); const plainTextTicketKey = this.decrypt(ticketKey, paddedAccessSecret); return this.encrypt(plainTextPassword, plainTextTicketKey); } catch (error) { throw new HttpException( `Error encrypting password: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } }