2023-05-05 10:35:38 +02:00

75 lines
1.9 KiB
TypeScript

import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import { BackendVariables } from "@Common/config/variables/Variables";
import crypto from "crypto";
@Service()
export default class CryptoService extends BaseService {
private key: CryptoKey;
private jwkKey: any;
constructor(protected variables: BackendVariables) {
super();
this.key = new CryptoKey();
this.jwkKey = {
kty: "oct",
k: variables.KEY_DATA,
alg: "A256GCM",
ext: true,
};
}
private async getKey() {
if (!this.key) this.key = await crypto.subtle.importKey("jwk", this.jwkKey, {name: "AES-GCM"}, false, ["encrypt", "decrypt"]);
return this.key;
}
public getTextEncoderDecoder() {
return { encoder: new TextEncoder(), decoder: new TextDecoder("utf-8") }
}
/**
* @description : encrypt data
* @throws {Error} If data cannot be encrypted
*/
public async encrypt(data: any) {
const { encoder, decoder } = this.getTextEncoderDecoder();
const encodedData = encoder.encode(data);
const iv = crypto.getRandomValues(new Uint8Array(16));
const key = await this.getKey();
const cipherData = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv,
},
key,
encodedData,
);
const cipherText = decoder.decode(cipherData);
const ivStringified = decoder.decode(iv);
return { cipherText, ivStringified };
}
/**
* @description : decrypt data with an initialization vector
* @throws {Error} If data cannot be decrypted
*/
public async decrypt(cipherText: string, ivStringified: string): Promise<string> {
const { encoder, decoder } = this.getTextEncoderDecoder();
const cipherData = encoder.encode(cipherText);
const iv = encoder.encode(ivStringified);
const key = await this.getKey();
const decryptedData = await crypto.subtle.decrypt(
{
name: "AES-GCM",
iv,
},
key,
cipherData,
);
return decoder.decode(decryptedData);
}
}