Skip to content

Commit

Permalink
add encryption tests
Browse files Browse the repository at this point in the history
  • Loading branch information
VictoriqueMoe committed Mar 29, 2024
1 parent 19ad455 commit 3d50a24
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
1 change: 1 addition & 0 deletions .test.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ BLOCKED_MIME_TYPES=application/x-dosexec,application/x-executable,application/x-
USE_CLOUDFLARE=false
MAX_URL_LENGTH=4096
BASE_URL=localhost:8080
SALT=12345678
7 changes: 7 additions & 0 deletions src/model/db/__test__/mocks/FileUploadModel.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export const fileUploadModelMock500MB = Builder(FileUploadModel)
.createdAt(new Date())
.build();

export const fileUploadModelMock500MBProtected = Builder(FileUploadModel, fileUploadModelMock500MB)
.settings({
password: "foo",
})
.encrypted(true)
.build();

export const fileUploadModelMockCustomExpire = Builder(FileUploadModel)
.fileExtension("jpg")
.fileName("foo")
Expand Down
157 changes: 157 additions & 0 deletions src/services/__test__/unit/EncryptionService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { envs, initDotEnv } from "../../../__test__/testUtils.spec.js";
import { PlatformTest } from "@tsed/common";
import { EncryptionService } from "../../EncryptionService.js";
import { FileUtils } from "../../../utils/Utils.js";
import fs from "node:fs/promises";
import {
fileUploadModelMock500MB,
fileUploadModelMock500MBProtected,
} from "../../../model/db/__test__/mocks/FileUploadModel.mock.js";
import argon2 from "argon2";
import crypto from "node:crypto";

describe("unit tests", () => {
beforeEach(() => {
PlatformTest.create({
envs,
});
initDotEnv();
});

afterEach(() => {
vi.clearAllMocks();
PlatformTest.reset();
});

vi.mock("node:fs/promises");

vi.mock("argon2", async importOriginal => {
return {
...(await importOriginal<typeof import("argon2")>()),
};
});

vi.mock("node:crypto", async importOriginal => {
const fakeIv = Buffer.from("hello");
return {
...(await importOriginal<typeof import("node:crypto")>()),
randomBytes: (size: number, callback: (err: Error | null, buf: Buffer) => void): void => {
callback(null, fakeIv);
},
};
});

describe("encrypt", () => {
it(
"should encrypt a file",
PlatformTest.inject([EncryptionService], async (encryptionService: EncryptionService) => {
// given
const fileToEnc = "fake.jpg";
const encryptedBytes = Buffer.from("encryptedFake");
const filePathSpy = vi.spyOn(FileUtils, "getFilePath").mockReturnValue(fileToEnc);
const readFileMock = vi.mocked(fs.readFile).mockResolvedValue(Buffer.from(fileToEnc));
const writeFileSpy = vi.mocked(fs.writeFile);
vi.spyOn(Buffer, "concat").mockReturnValue(encryptedBytes);

// when
const result = await encryptionService.encrypt(fileToEnc, "foo");

// then
expect(filePathSpy).toBeCalledWith(fileToEnc);
expect(readFileMock).toBeCalledWith(fileToEnc);
expect(writeFileSpy).toBeCalledWith(fileToEnc, encryptedBytes);
expect(result).toBe(encryptedBytes);
}),
);
it(
"should encrypt a buffer",
PlatformTest.inject([EncryptionService], async (encryptionService: EncryptionService) => {
// given
const fileToEnc = Buffer.from("fakeImage");
const encryptedBytes = Buffer.from("encryptedFake");
vi.spyOn(Buffer, "concat").mockReturnValue(encryptedBytes);

// when
const result = await encryptionService.encrypt(fileToEnc, "foo");

// then
expect(result).toBe(encryptedBytes);
}),
);
});
describe("decrypt", () => {
it(
"should decrypt a file",
PlatformTest.inject([EncryptionService], async (encryptionService: EncryptionService) => {
// given
const decryptedBuffer = Buffer.from("decrypted");
const source = fileUploadModelMock500MBProtected;
const fileToDecrypt = source.fullLocationOnDisk;
const filePathSpy = vi.spyOn(FileUtils, "getFilePath").mockReturnValue(fileToDecrypt);
const password = "foo";
const fileToDecryptBuffer = Buffer.from(fileToDecrypt);
const readFileMock = vi.mocked(fs.readFile).mockResolvedValue(fileToDecryptBuffer);
const argonVerifySpy = vi.spyOn(argon2, "verify").mockResolvedValue(true);
const fakeIV = "aaaaaaaaaaaaaaaa";
vi.spyOn(fileToDecryptBuffer, "subarray").mockReturnValue(Buffer.from(fakeIV));
vi.spyOn(Buffer, "concat").mockReturnValue(decryptedBuffer);

// when
const result = await encryptionService.decrypt(source, password);

// then
expect(filePathSpy).toBeCalledWith(source);
expect(readFileMock).toBeCalledWith(fileToDecrypt);
expect(argonVerifySpy).toBeCalledWith(source.settings?.password, password);
expect(result).toBe(decryptedBuffer);
}),
);
it(
"should verify protected file",
PlatformTest.inject([EncryptionService], async (encryptionService: EncryptionService) => {
// given
const source = fileUploadModelMock500MBProtected;
source.encrypted = false;
const fileToCheck = source.fullLocationOnDisk;
const filePathSpy = vi.spyOn(FileUtils, "getFilePath").mockReturnValue(fileToCheck);
const password = "foo";
const argonVerifySpy = vi.spyOn(argon2, "verify").mockResolvedValue(true);
const fileToDecryptBuffer = Buffer.from(fileToCheck);
const readFileMock = vi.mocked(fs.readFile).mockResolvedValue(fileToDecryptBuffer);
const decipherivSpy = vi.spyOn(crypto, "createDecipheriv");

// when
const result = await encryptionService.decrypt(source, password);

// then
expect(filePathSpy).toBeCalledWith(source);
expect(readFileMock).toBeCalledWith(fileToCheck);
expect(argonVerifySpy).toBeCalledWith(source.settings?.password, password);
expect(result).toBe(fileToDecryptBuffer);
expect(decipherivSpy).not.toHaveBeenCalled();
}),
);
it(
"should return a non-protected file",
PlatformTest.inject([EncryptionService], async (encryptionService: EncryptionService) => {
// given
const source = fileUploadModelMock500MB;
const fileToCheck = source.fullLocationOnDisk;
const fileBuffer = Buffer.from(fileToCheck);
const filePathSpy = vi.spyOn(FileUtils, "getFilePath").mockReturnValue(fileToCheck);
const readFileMock = vi.mocked(fs.readFile).mockResolvedValue(fileBuffer);
const decipherivSpy = vi.spyOn(crypto, "createDecipheriv");

// when
const result = await encryptionService.decrypt(source);

// then
expect(filePathSpy).toBeCalledWith(source);
expect(readFileMock).toBeCalledWith(fileToCheck);
expect(result).toBe(fileBuffer);
expect(decipherivSpy).not.toHaveBeenCalled();
}),
);
});
});
1 change: 1 addition & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { configDefaults, defineConfig } from "vitest/config";

export default defineConfig({
test: {
unstubEnvs: true,
globals: true,
root: "./",
exclude: [...configDefaults.exclude, "node_modules/*", "src/__test__"],
Expand Down

0 comments on commit 3d50a24

Please sign in to comment.