Skip to content

Commit

Permalink
build: fix build to use WebCryptoAPI and mock for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ythepaut committed Apr 27, 2024
1 parent eb471aa commit ee447a1
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 24 deletions.
1 change: 1 addition & 0 deletions build/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 91 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@peculiar/webcrypto": "^1.4.6",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
Expand Down
10 changes: 10 additions & 0 deletions setup.jest.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import { Crypto } from "@peculiar/webcrypto";
import { TextEncoder, TextDecoder } from "util";

Object.assign(global, { TextDecoder, TextEncoder });

const crypto = new Crypto();

Object.defineProperty(global.self, "crypto", {
value: {
subtle: crypto.subtle,
getRandomValues: crypto.getRandomValues
},
});
5 changes: 2 additions & 3 deletions src/operations/hmac.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { subtle } from "crypto";
import { ByteArray } from "../types";

/**
Expand All @@ -9,15 +8,15 @@ import { ByteArray } from "../types";
* @returns The computed tag.
*/
async function hmac(key: ByteArray, input: ByteArray): Promise<ByteArray> {
const importedKey = await subtle.importKey(
const importedKey = await window.crypto.subtle.importKey(
"raw",
key,
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);

const tag = await subtle.sign("HMAC", importedKey, input);
const tag = await window.crypto.subtle.sign("HMAC", importedKey, input);

return new Uint8Array(tag);
}
Expand Down
5 changes: 2 additions & 3 deletions src/operations/kdf.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { subtle } from "crypto";
import { ByteArray } from "../types";

interface KDFContext {
Expand Down Expand Up @@ -28,15 +27,15 @@ async function kdf(
outputLength: number,
salt: ByteArray | null = null
): Promise<ByteArray> {
const extractKey = await subtle.importKey("raw", key, { name: "HKDF" }, false, [
const extractKey = await window.crypto.subtle.importKey("raw", key, { name: "HKDF" }, false, [
"deriveKey",
"deriveBits"
]);

const contextBuffer = contextToBuffer(context);
const saltBuffer = Buffer.from(salt ?? []);

const derived = await subtle.deriveBits(
const derived = await window.crypto.subtle.deriveBits(
{
name: "HKDF",
info: contextBuffer,
Expand Down
21 changes: 13 additions & 8 deletions src/operations/rsa.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { subtle } from "crypto";
import { ByteArray, bytesToBase64 } from "../types";
import DecryptionException from "../exceptions/DecryptionException";

Expand All @@ -13,7 +12,7 @@ interface KeyPair {
* @returns An RSA key pair.
*/
async function generateRSAKeyPair(): Promise<KeyPair> {
const cryptoKeyPair = await subtle.generateKey(
const cryptoKeyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
Expand All @@ -24,9 +23,11 @@ async function generateRSAKeyPair(): Promise<KeyPair> {
["encrypt", "decrypt"]
);

const pub: ByteArray = new Uint8Array(await subtle.exportKey("spki", cryptoKeyPair.publicKey));
const pub: ByteArray = new Uint8Array(
await window.crypto.subtle.exportKey("spki", cryptoKeyPair.publicKey)
);
const secret: ByteArray = new Uint8Array(
await subtle.exportKey("pkcs8", cryptoKeyPair.privateKey)
await window.crypto.subtle.exportKey("pkcs8", cryptoKeyPair.privateKey)
);

return { pub, secret };
Expand All @@ -52,15 +53,15 @@ function exportAsPem(key: ByteArray, keyType: "PUBLIC" | "SECRET"): string {
* @returns The encrypted data.
*/
async function rsaEncrypt(pub: ByteArray, data: ByteArray): Promise<ByteArray> {
const publicKey = await subtle.importKey(
const publicKey = await window.crypto.subtle.importKey(
"spki",
pub,
{ name: "RSA-OAEP", hash: "SHA-256" },
true,
["encrypt"]
);

const encryptedData = await subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data);
const encryptedData = await window.crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data);

return new Uint8Array(encryptedData);
}
Expand All @@ -74,15 +75,19 @@ async function rsaEncrypt(pub: ByteArray, data: ByteArray): Promise<ByteArray> {
*/
async function rsaDecrypt(secret: ByteArray, cipher: ByteArray): Promise<ByteArray> {
try {
const privateKey = await subtle.importKey(
const privateKey = await window.crypto.subtle.importKey(
"pkcs8",
secret,
{ name: "RSA-OAEP", hash: "SHA-256" },
true,
["decrypt"]
);

const decryptedData = await subtle.decrypt({ name: "RSA-OAEP" }, privateKey, cipher);
const decryptedData = await window.crypto.subtle.decrypt(
{ name: "RSA-OAEP" },
privateKey,
cipher
);

return new Uint8Array(decryptedData);
} catch (error) {
Expand Down
15 changes: 6 additions & 9 deletions src/operations/sha2.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { ByteArray } from "../types";
import { createHash, Hash } from "crypto";

type Algorithm = "SHA-256" | "SHA-512";

function sha2(input: string, algorithm: Algorithm): ByteArray {
const hash: Hash = createHash(algorithm);
hash.update(input);
return new Uint8Array(hash.digest());
async function sha2(input: ByteArray, algorithm: Algorithm): Promise<ByteArray> {
return new Uint8Array(await window.crypto.subtle.digest(algorithm, input));
}

function sha256(input: string): ByteArray {
return sha2(input, "SHA-256");
async function sha256(input: ByteArray): Promise<ByteArray> {
return await sha2(input, "SHA-256");
}

function sha512(input: string): ByteArray {
return sha2(input, "SHA-512");
async function sha512(input: ByteArray): Promise<ByteArray> {
return await sha2(input, "SHA-512");
}

export { sha256, sha512 };
2 changes: 1 addition & 1 deletion tests/operations/sha2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ByteArray, bytesToHex } from "../../src/types";
import { sha256, sha512 } from "../../src/operations/sha2";

describe("SHA2", () => {
const input: string = "hash me!";
const input: ByteArray = new TextEncoder().encode("hash me!");

it("should compute the SHA-256 hash", async () => {
const hash: ByteArray = await sha256(input);
Expand Down

0 comments on commit ee447a1

Please sign in to comment.