summaryrefslogtreecommitdiff
path: root/cli/tests/unit_node/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/unit_node/crypto')
-rw-r--r--cli/tests/unit_node/crypto/crypto_cipher_test.ts186
-rw-r--r--cli/tests/unit_node/crypto/crypto_hash_test.ts24
-rw-r--r--cli/tests/unit_node/crypto/crypto_key_test.ts204
-rw-r--r--cli/tests/unit_node/crypto/crypto_sign_test.ts91
4 files changed, 505 insertions, 0 deletions
diff --git a/cli/tests/unit_node/crypto/crypto_cipher_test.ts b/cli/tests/unit_node/crypto/crypto_cipher_test.ts
new file mode 100644
index 000000000..a8a5130cf
--- /dev/null
+++ b/cli/tests/unit_node/crypto/crypto_cipher_test.ts
@@ -0,0 +1,186 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+import crypto from "node:crypto";
+import { Buffer } from "node:buffer";
+import { Readable } from "node:stream";
+import { buffer, text } from "node:stream/consumers";
+import {
+ assertEquals,
+ assertThrows,
+} from "../../../../test_util/std/testing/asserts.ts";
+
+const rsaPrivateKey = Deno.readTextFileSync(
+ new URL("../testdata/rsa_private.pem", import.meta.url),
+);
+const rsaPublicKey = Deno.readTextFileSync(
+ new URL("../testdata/rsa_public.pem", import.meta.url),
+);
+
+const input = new TextEncoder().encode("hello world");
+
+function zeros(length: number): Uint8Array {
+ return new Uint8Array(length);
+}
+
+Deno.test({
+ name: "rsa public encrypt and private decrypt",
+ fn() {
+ const encrypted = crypto.publicEncrypt(Buffer.from(rsaPublicKey), input);
+ const decrypted = crypto.privateDecrypt(
+ Buffer.from(rsaPrivateKey),
+ Buffer.from(encrypted),
+ );
+ assertEquals(decrypted, input);
+ },
+});
+
+Deno.test({
+ name: "rsa private encrypt and private decrypt",
+ fn() {
+ const encrypted = crypto.privateEncrypt(rsaPrivateKey, input);
+ const decrypted = crypto.privateDecrypt(
+ rsaPrivateKey,
+ Buffer.from(encrypted),
+ );
+ assertEquals(decrypted, input);
+ },
+});
+
+Deno.test({
+ name: "rsa public decrypt fail",
+ fn() {
+ const encrypted = crypto.publicEncrypt(rsaPublicKey, input);
+ assertThrows(() =>
+ crypto.publicDecrypt(rsaPublicKey, Buffer.from(encrypted))
+ );
+ },
+});
+
+Deno.test({
+ name: "createCipheriv - multiple chunk inputs",
+ fn() {
+ const cipher = crypto.createCipheriv(
+ "aes-128-cbc",
+ new Uint8Array(16),
+ new Uint8Array(16),
+ );
+ assertEquals(
+ cipher.update(new Uint8Array(16), undefined, "hex"),
+ "66e94bd4ef8a2c3b884cfa59ca342b2e",
+ );
+ assertEquals(
+ cipher.update(new Uint8Array(19), undefined, "hex"),
+ "f795bd4a52e29ed713d313fa20e98dbc",
+ );
+ assertEquals(
+ cipher.update(new Uint8Array(55), undefined, "hex"),
+ "a10cf66d0fddf3405370b4bf8df5bfb347c78395e0d8ae2194da0a90abc9888a94ee48f6c78fcd518a941c3896102cb1",
+ );
+ assertEquals(cipher.final("hex"), "e11901dde4a2f99fe4efc707e48c6aed");
+ },
+});
+
+Deno.test({
+ name: "createCipheriv - algorithms",
+ fn() {
+ const table = [
+ [
+ ["aes-128-cbc", 16, 16],
+ "66e94bd4ef8a2c3b884cfa59ca342b2ef795bd4a52e29ed713d313fa20e98dbca10cf66d0fddf3405370b4bf8df5bfb3",
+ "d5f65ecda64511e9d3d12206411ffd72",
+ ],
+ [
+ ["aes-128-ecb", 16, 0],
+ "66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2e",
+ "baf823258ca2e6994f638daa3515e986",
+ ],
+ ] as const;
+ for (
+ const [[alg, keyLen, ivLen], expectedUpdate, expectedFinal] of table
+ ) {
+ const cipher = crypto.createCipheriv(alg, zeros(keyLen), zeros(ivLen));
+ assertEquals(cipher.update(zeros(50), undefined, "hex"), expectedUpdate);
+ assertEquals(cipher.final("hex"), expectedFinal);
+ }
+ },
+});
+
+Deno.test({
+ name: "createCipheriv - input encoding",
+ fn() {
+ const cipher = crypto.createCipheriv(
+ "aes-128-cbc",
+ new Uint8Array(16),
+ new Uint8Array(16),
+ );
+ assertEquals(
+ cipher.update("hello, world! hello, world!", "utf-8", "hex"),
+ "ca7df4d74f51b77a7440ead38343ab0f",
+ );
+ assertEquals(cipher.final("hex"), "d0da733dec1fa61125c80a6f97e6166e");
+ },
+});
+
+Deno.test({
+ name: "createCipheriv - transform stream",
+ async fn() {
+ const result = await buffer(
+ Readable.from("foo".repeat(15)).pipe(crypto.createCipheriv(
+ "aes-128-cbc",
+ new Uint8Array(16),
+ new Uint8Array(16),
+ )),
+ );
+ // deno-fmt-ignore
+ assertEquals([...result], [
+ 129, 19, 202, 142, 137, 51, 23, 53, 198, 33,
+ 214, 125, 17, 5, 128, 57, 162, 217, 220, 53,
+ 172, 51, 85, 113, 71, 250, 44, 156, 80, 4,
+ 158, 92, 185, 173, 67, 47, 255, 71, 78, 187,
+ 80, 206, 42, 5, 34, 104, 1, 54
+ ]);
+ },
+});
+
+Deno.test({
+ name: "createDecipheriv - algorithms",
+ fn() {
+ const table = [
+ [
+ ["aes-128-cbc", 16, 16],
+ "66e94bd4ef8a2c3b884cfa59ca342b2ef795bd4a52e29ed713d313fa20e98dbca10cf66d0fddf3405370b4bf8df5bfb347c78395e0d8ae2194da0a90abc9888a94ee48f6c78fcd518a941c3896102cb1e11901dde4a2f99fe4efc707e48c6aed",
+ ],
+ [
+ ["aes-128-ecb", 16, 0],
+ "66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2e66e94bd4ef8a2c3b884cfa59ca342b2ec29a917cbaf72fa9bc32129bb0d17663",
+ ],
+ ] as const;
+ for (
+ const [[alg, keyLen, ivLen], input] of table
+ ) {
+ const cipher = crypto.createDecipheriv(alg, zeros(keyLen), zeros(ivLen));
+ assertEquals(cipher.update(input, "hex"), Buffer.alloc(80));
+ assertEquals(cipher.final(), Buffer.alloc(10));
+ }
+ },
+});
+
+Deno.test({
+ name: "createDecipheriv - transform stream",
+ async fn() {
+ const stream = Readable.from([
+ // deno-fmt-ignore
+ new Uint8Array([
+ 129, 19, 202, 142, 137, 51, 23, 53, 198, 33,
+ 214, 125, 17, 5, 128, 57, 162, 217, 220, 53,
+ 172, 51, 85, 113, 71, 250, 44, 156, 80, 4,
+ 158, 92, 185, 173, 67, 47, 255, 71, 78, 187,
+ 80, 206, 42, 5, 34, 104, 1, 54
+ ]),
+ ]).pipe(crypto.createDecipheriv(
+ "aes-128-cbc",
+ new Uint8Array(16),
+ new Uint8Array(16),
+ ));
+ assertEquals(await text(stream), "foo".repeat(15));
+ },
+});
diff --git a/cli/tests/unit_node/crypto/crypto_hash_test.ts b/cli/tests/unit_node/crypto/crypto_hash_test.ts
new file mode 100644
index 000000000..679577770
--- /dev/null
+++ b/cli/tests/unit_node/crypto/crypto_hash_test.ts
@@ -0,0 +1,24 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+import { createHash, createHmac } from "node:crypto";
+import { assertEquals } from "../../../../test_util/std/testing/asserts.ts";
+
+// https://github.com/denoland/deno/issues/18140
+Deno.test({
+ name: "createHmac digest",
+ fn() {
+ assertEquals(
+ createHmac("sha256", "secret").update("hello").digest("hex"),
+ "88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b",
+ );
+ },
+});
+
+Deno.test({
+ name: "createHash digest",
+ fn() {
+ assertEquals(
+ createHash("sha256").update("hello").digest("hex"),
+ "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
+ );
+ },
+});
diff --git a/cli/tests/unit_node/crypto/crypto_key_test.ts b/cli/tests/unit_node/crypto/crypto_key_test.ts
new file mode 100644
index 000000000..672c9fa7f
--- /dev/null
+++ b/cli/tests/unit_node/crypto/crypto_key_test.ts
@@ -0,0 +1,204 @@
+// deno-lint-ignore-file no-explicit-any
+
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+import {
+ createSecretKey,
+ generateKeyPair,
+ generateKeyPairSync,
+ KeyObject,
+ randomBytes,
+} from "node:crypto";
+import { promisify } from "node:util";
+import { Buffer } from "node:buffer";
+import {
+ assertEquals,
+ assertThrows,
+} from "../../../../test_util/std/testing/asserts.ts";
+import { createHmac } from "node:crypto";
+
+const generateKeyPairAsync = promisify(
+ (
+ type: any,
+ options: any,
+ callback: (
+ err: Error | null,
+ key: { publicKey: KeyObject; privateKey: KeyObject },
+ ) => void,
+ ) =>
+ generateKeyPair(
+ type,
+ options,
+ (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => {
+ callback(err, { publicKey, privateKey });
+ },
+ ),
+);
+
+Deno.test({
+ name: "create secret key",
+ fn() {
+ const key = createSecretKey(Buffer.alloc(0));
+ assertEquals(key.type, "secret");
+ assertEquals(key.asymmetricKeyType, undefined);
+ assertEquals(key.symmetricKeySize, 0);
+ },
+});
+
+Deno.test({
+ name: "export secret key",
+ fn() {
+ const material = Buffer.from(randomBytes(32));
+ const key = createSecretKey(material);
+ assertEquals(Buffer.from(key.export()), material);
+ },
+});
+
+Deno.test({
+ name: "export jwk secret key",
+ fn() {
+ const material = Buffer.from("secret");
+ const key = createSecretKey(material);
+ assertEquals(key.export({ format: "jwk" }), {
+ kty: "oct",
+ k: "c2VjcmV0",
+ });
+ },
+});
+
+Deno.test({
+ name: "createHmac with secret key",
+ fn() {
+ const key = createSecretKey(Buffer.from("secret"));
+ assertEquals(
+ createHmac("sha256", key).update("hello").digest().toString("hex"),
+ "88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b",
+ );
+ },
+});
+
+for (const type of ["rsa", "rsa-pss", "dsa"]) {
+ for (const modulusLength of [2048, 3072]) {
+ Deno.test({
+ name: `generate ${type} key`,
+ fn() {
+ const { publicKey, privateKey } = generateKeyPairSync(type as any, {
+ modulusLength,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+
+ Deno.test({
+ name: `generate ${type} key async`,
+ async fn() {
+ const x = await generateKeyPairAsync(type as any, {
+ modulusLength,
+ });
+ const { publicKey, privateKey } = x;
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+ }
+}
+
+for (const namedCurve of ["P-384", "P-256"]) {
+ Deno.test({
+ name: `generate ec key ${namedCurve}`,
+ fn() {
+ const { publicKey, privateKey } = generateKeyPairSync("ec", {
+ namedCurve,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+
+ Deno.test({
+ name: `generate ec key ${namedCurve} async`,
+ async fn() {
+ const { publicKey, privateKey } = await generateKeyPairAsync("ec", {
+ namedCurve,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+
+ Deno.test({
+ name: `generate ec key ${namedCurve} paramEncoding=explicit fails`,
+ fn() {
+ assertThrows(() => {
+ // @ts-ignore: @types/node is broken?
+ generateKeyPairSync("ec", {
+ namedCurve,
+ paramEncoding: "explicit",
+ });
+ });
+ },
+ });
+}
+
+for (
+ const groupName of ["modp5", "modp14", "modp15", "modp16", "modp17", "modp18"]
+) {
+ Deno.test({
+ name: `generate dh key ${groupName}`,
+ fn() {
+ // @ts-ignore: @types/node is broken?
+ const { publicKey, privateKey } = generateKeyPairSync("dh", {
+ group: groupName,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+
+ Deno.test({
+ name: `generate dh key ${groupName} async`,
+ async fn() {
+ // @ts-ignore: @types/node is broken?
+ const { publicKey, privateKey } = await generateKeyPairAsync("dh", {
+ group: groupName,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+}
+
+for (const primeLength of [1024, 2048, 4096]) {
+ Deno.test({
+ name: `generate dh key ${primeLength}`,
+ fn() {
+ // @ts-ignore: @types/node is broken?
+ const { publicKey, privateKey } = generateKeyPairSync("dh", {
+ primeLength,
+ generator: 2,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+
+ Deno.test({
+ name: `generate dh key ${primeLength} async`,
+ async fn() {
+ // @ts-ignore: @types/node is broken?
+ const { publicKey, privateKey } = await generateKeyPairAsync("dh", {
+ primeLength,
+ generator: 2,
+ });
+
+ assertEquals(publicKey.type, "public");
+ assertEquals(privateKey.type, "private");
+ },
+ });
+}
diff --git a/cli/tests/unit_node/crypto/crypto_sign_test.ts b/cli/tests/unit_node/crypto/crypto_sign_test.ts
new file mode 100644
index 000000000..9988ed71c
--- /dev/null
+++ b/cli/tests/unit_node/crypto/crypto_sign_test.ts
@@ -0,0 +1,91 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+import {
+ assert,
+ assertEquals,
+} from "../../../../test_util/std/testing/asserts.ts";
+import { createSign, createVerify, sign, verify } from "node:crypto";
+import { Buffer } from "node:buffer";
+
+const rsaPrivatePem = Buffer.from(
+ await Deno.readFile(
+ new URL("../testdata/rsa_private.pem", import.meta.url),
+ ),
+);
+const rsaPublicPem = Buffer.from(
+ await Deno.readFile(
+ new URL("../testdata/rsa_public.pem", import.meta.url),
+ ),
+);
+
+const table = [
+ {
+ algorithms: ["sha224", "RSA-SHA224"],
+ signature:
+ "7ad162b288bd7f4ba9b8a31295ad4136d143a5fd11eb99a72379dc9b53e3e8b5c1b7c9dd8a3864a1f626d921e550c48056982bd8fe7e75333885311b5515de1ecbbfcc6a1dd930f422dff87bfceb7eb38882ac6b4fd9dea9efd462776775976e81b1d677f8db41f5ac8686abfa9838069125be939c59e404aa50550872d84befb8b5f6ce2dd051c62a8ba268f876b6f17a27af43b79938222e4ab8b90c4f5540d0f8b02508ef3e68279d685746956b924f00c92438b7981a3cfcb1e2a97305402d381ea62aeaa803f8707961bc3e10a258352e210772e9846ca4024e3dc0a956a50d6db1c03d2943826cc98c6f36d7bafacf1c94b6c438c7664c300a3be172b1",
+ },
+ {
+ algorithms: ["sha256", "RSA-SHA256"],
+ signature:
+ "080313284d7398e1e0e27f6e44f198ceecedddc801e81af63a867d9245ad744e29018099c9ac3c27061c33cabfe27af1db38f44bac09cdcd2c4ab3b00a2a3020f68368f2239db5f911a2dbb7ea2dee322ca7d26d0c88d197482ca4aa1c29ac87b9e6c20075dc974ae71d2d76d2a5b2a15bd541033519465c3aea815cc73b0f1c3ffeedcfb93d6788416623789f86786870d23e86b982ab0df157d7a596097bd3cca3e752f3f47eff4b83754296868b52bc8ff741492dc8a401fe6dc035569e45d1fa1a71c8988d3aadce68fb1bf5c3e756c586af20c8e75c037436ff4c8389e6ce9d943ef7e2566977b84577272181fcec403077cc29e7db1166fff900b36a1d",
+ },
+ {
+ algorithms: ["sha384", "RSA-SHA384"],
+ signature:
+ "2f77a5b7ac0168efd652c30ecb082075f3de30629e9c1f51b7e7e671f24b5c3a2606bb72159a217438220fc7aaba887d4b817e3f43fe0cc8f840747368df8cd65ec760c21a3f9296d01caedc80a335030e31d31ac451277fc4bcc1679c168b2c3185dfee21286514113c080af5238a61a677b03777344f476f25053108588aa6bdc02a6138c6b59a20de4d11e3d668482f17e748e75747f83c0512206283acfc64ed0ad963dddc9ec24589cfd459ee806b8e0e67b93cea16651e967762a5deef890f438ffb9db39247469289db06e2ed7fe262aa1df4ab9607e5b5219a17ddc9694283a61bf8643f58fd702f2c5d3b2d53dc7f36bb5e96461174d376950d6d19",
+ },
+ {
+ algorithms: ["sha512", "RSA-SHA512"],
+ signature:
+ "072e20a433f255ab2f7e5e9ce69255d5c6d7c15a36af75c8389b9672c41abc6a9532fbd057d9d64270bb2483d3c9923f8f419fba4b59b838dcda82a1322009d245c06e2802a74febaea9cebc0b7f46f8761331c5f52ffb650245b5aefefcc604f209b44f6560fe45370cb239d236622e5f72fbb45377f08a0c733e16a8f15830897679ad4349d2e2e5e50a99796820302f4f47881ed444aede56a6d3330b71acaefc4218ae2e4a3bdfbb0c9432ffc5e5bac8c168278b2205d68a5d6905ccbb91282d519c11eccca52d42c86787de492b2a89679dce98cd14c37b0c183af8427e7a1ec86b1ed3f9b5bebf83f1ef81eb18748e69c716a0f263a8598fe627158647",
+ },
+];
+
+const data = Buffer.from("some data to sign");
+
+Deno.test({
+ name:
+ "crypto.Sign|sign - RSA PEM with SHA224, SHA256, SHA384, SHA512 digests",
+ fn() {
+ for (const testCase of table) {
+ for (const algorithm of testCase.algorithms) {
+ assertEquals(
+ createSign(algorithm)
+ .update(data)
+ .sign(rsaPrivatePem, "hex"),
+ testCase.signature,
+ );
+ assertEquals(
+ sign(algorithm, data, rsaPrivatePem),
+ Buffer.from(testCase.signature, "hex"),
+ );
+ }
+ }
+ },
+});
+
+Deno.test({
+ name:
+ "crypto.Verify|verify - RSA PEM with SHA224, SHA256, SHA384, SHA512 digests",
+ fn() {
+ for (const testCase of table) {
+ for (const algorithm of testCase.algorithms) {
+ assert(
+ createVerify(algorithm).update(data).verify(
+ rsaPublicPem,
+ testCase.signature,
+ "hex",
+ ),
+ );
+ assert(
+ verify(
+ algorithm,
+ data,
+ rsaPublicPem,
+ Buffer.from(testCase.signature, "hex"),
+ ),
+ );
+ }
+ }
+ },
+});