add crypto services to decrypt files path (#28)

Co-authored-by: OxSaitama <arnaud.daubernatali@smart-chain.fr>
This commit is contained in:
Arnaud D. Natali 2023-05-09 11:35:53 +02:00 committed by GitHub
parent 36e60ecfc7
commit 9934816b77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 160 additions and 1 deletions

View File

@ -21,7 +21,7 @@
"dotenv": "^16.0.3",
"eslint": "8.36.0",
"eslint-config-next": "13.2.4",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.35",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.38",
"next": "13.2.4",
"prettier": "^2.8.7",
"react": "18.2.0",

View File

@ -0,0 +1,87 @@
import { File } from "le-coffre-resources/dist/SuperAdmin";
import Container, { Service } from "typedi";
import BaseSuperAdmin from "../BaseSuperAdmin";
import CryptoService from "@Front/Services/CryptoService/CryptoService";
// TODO Type get query params -> Where + inclue + orderby
export interface IGetFilesparams {
where?: {};
include?: {};
}
// TODO Type getbyuid query params
export type IPutFilesParams = {};
export interface IPostFilesParams {}
@Service()
export default class Files extends BaseSuperAdmin {
private static instance: Files;
private readonly baseURl = this.namespaceUrl.concat("/files");
private constructor(private cryptoService: CryptoService) {
super();
}
public static getInstance() {
if (!this.instance) {
return new this(Container.get(CryptoService));
} else {
return this.instance;
}
}
public async get(q: IGetFilesparams): Promise<File[]> {
const url = new URL(this.baseURl);
Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try {
const files = await this.getRequest<File[]>(url);
files.forEach(async(file) => {
file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv);
})
return files
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
/**
* @description : Create a File
*/
public async post(body: any): Promise<File> {
const url = new URL(this.baseURl);
try {
return await this.postRequest<File>(url, body);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
public async getByUid(uid: string, q?: any): Promise<File> {
const url = new URL(this.baseURl.concat(`/${uid}`));
const query = { q };
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try {
const file = await this.getRequest<File>(url);
file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv);
return file;
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
public async put(uid: string, body: IPutFilesParams): Promise<File> {
const url = new URL(this.baseURl.concat(`/${uid}`));
try {
return await this.putRequest<File>(url, body);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
}

View File

@ -143,8 +143,10 @@ export const fileMock: File = {
created_at: new Date(),
updated_at: new Date(),
document: document,
file_name: "file_1",
file_path:
"https://minteed-stg-euwest3-s3.s3.eu-west-3.amazonaws.com/Qmf_Yb_Eh_X9st_F_Srq_Ve_Bj_Yb_Aj56xv_AV_Nj6_Wjypo_B4r5ubce_U_ae3303e7ab.pdf",
iv: "1"
};
export const fileMock2: File = {
@ -152,8 +154,10 @@ export const fileMock2: File = {
created_at: new Date(),
updated_at: new Date(),
document: document,
file_name: "file_2",
file_path:
"https://minteed-prod-euwest3-s3.s3.eu-west-3.amazonaws.com/Qm_Wq_En1_DCA_8yt_RX_Qx_QFA_9_Fm_ZKZH_Qqb_VH_1_Q_Mnv_G_Jtt1_FS_Xp_2a35a36e19",
iv: "2"
};
export const identityFile: File = {
@ -161,7 +165,9 @@ export const identityFile: File = {
created_at: new Date(),
updated_at: new Date(),
document: document,
file_name: "file_3",
file_path: "https://minteed-stg-euwest3-s3.s3.eu-west-3.amazonaws.com/cni_fake_c7259d4923.png",
iv: "3"
};
export const documentIdentity: Document = {

View File

@ -19,6 +19,8 @@ export class FrontendVariables {
public IDNOT_CLIENT_ID!: string;
public KEY_DATA!: string;
private constructor() {}
public static getInstance(): FrontendVariables {

View File

@ -0,0 +1,64 @@
import { Service } from "typedi";
import { FrontendVariables } from "@Front/Config/VariablesFront";
import crypto from "crypto";
@Service()
export default class CryptoService {
private jwkKey: JsonWebKey;
private subtle: SubtleCrypto = crypto.webcrypto.subtle
constructor(protected variables: FrontendVariables) {
this.jwkKey = {
kty: "oct",
k: variables.KEY_DATA,
alg: "A256GCM",
ext: true,
};
}
private async getKey() {
return await this.subtle.importKey("jwk", this.jwkKey, {name: "AES-GCM"}, false, ["encrypt", "decrypt"]);
}
/**
* @description : encrypt data
* @throws {Error} If data cannot be encrypted
*/
public async encrypt(data: string) {
const encodedData = Buffer.from(data);
const iv = crypto.getRandomValues(new Uint8Array(16));
const key = await this.getKey();
const cipherData = await this.subtle.encrypt(
{
name: "AES-GCM",
iv,
},
key,
encodedData,
);
const cipherText = Buffer.from(cipherData).toString('base64');
const ivStringified = Buffer.from(iv).toString('base64');
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 cipherData = Buffer.from(cipherText, 'base64');
const iv = Buffer.from(ivStringified, 'base64');
const key = await this.getKey();
const decryptedData = await this.subtle.decrypt(
{
name: "AES-GCM",
iv,
},
key,
cipherData,
);
return Buffer.from(decryptedData).toString('utf-8');
}
}