diff --git a/test_util/std b/test_util/std new file mode 160000 index 00000000000000..e0ef24091e87f8 --- /dev/null +++ b/test_util/std @@ -0,0 +1 @@ +Subproject commit e0ef24091e87f84d44d495d432d611625b281249 diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index d22028624173da..11d643b2c3cf33 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -3,7 +3,11 @@ 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 "@std/assert/mod.ts"; +import { + assertEquals, + assertStrictEquals, + assertThrows, +} from "@std/assert/mod.ts"; const rsaPrivateKey = Deno.readTextFileSync( new URL("../testdata/rsa_private.pem", import.meta.url), @@ -256,3 +260,100 @@ Deno.test({ ); }, }); + +function setAutoPaddingTest( + { algorithm, keyLength, pad }: { + algorithm: string; + keyLength: number; + pad: boolean; + }, +) { + const key = crypto.randomBytes(keyLength); + const iv = algorithm.endsWith("ecb") ? null : crypto.randomBytes(16); + const data = pad + ? "0123456789abcdef0123456789abcde" // Not a multiple of block size + : "0123456789abcdef0123456789abcdef"; // Multiple of block size + + const cipher = crypto.createCipheriv(algorithm, key, iv); + cipher.setAutoPadding(pad); + const encrypted = cipher.update(data, "utf8", "latin1") + + cipher.final("latin1"); + + const decipher = crypto.createDecipheriv(algorithm, key, iv); + decipher.setAutoPadding(pad); + const decrypted = decipher.update(encrypted, "latin1", "utf8") + + decipher.final("utf8"); + + assertStrictEquals(decrypted, data); +} + +/** + * @todo(iuioiua) Add `*-gcm` algorithms once `Cipher.getAuthTag()` and + * `Decipher.setAuthTag()` are implemented. + */ +[ + { + algorithm: "aes-128-cbc", + keyLength: 16, + pad: false, + }, + { + algorithm: "aes-128-cbc", + keyLength: 16, + pad: true, + }, + { + algorithm: "aes-128-ecb", + keyLength: 16, + pad: false, + }, + { + algorithm: "aes-128-ecb", + keyLength: 16, + pad: true, + }, + { + algorithm: "aes-192-ecb", + keyLength: 24, + pad: false, + }, + { + algorithm: "aes-192-ecb", + keyLength: 24, + pad: true, + }, + { + algorithm: "aes256", + keyLength: 32, + pad: false, + }, + { + algorithm: "aes256", + keyLength: 32, + pad: true, + }, + { + algorithm: "aes-256-cbc", + keyLength: 32, + pad: false, + }, + { + algorithm: "aes-256-cbc", + keyLength: 32, + pad: true, + }, + { + algorithm: "aes-256-ecb", + keyLength: 32, + pad: false, + }, + { + algorithm: "aes-256-ecb", + keyLength: 32, + pad: true, + }, +].forEach((options) => { + Deno.test(`cipher.setAutoPadding() and decipher.setAutoPadding() - ${options.algorithm} ${options.pad ? "with" : "without"} padding`, () => { + setAutoPaddingTest(options); + }); +}); diff --git a/tests/unit_node/crypto_cipher_test.ts b/tests/unit_node/crypto_cipher_test.ts deleted file mode 100644 index 9163e7f979a35a..00000000000000 --- a/tests/unit_node/crypto_cipher_test.ts +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2018-2024 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, - assertStrictEquals, - assertThrows, -} from "@test_util/std/assert/mod.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 public encrypt (options) and private decrypt", - fn() { - const encrypted = crypto.publicEncrypt( - { key: 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", - ], - [ - ["aes-192-ecb", 24, 0], - "aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7", - "2e0f33b51bb184654311ead507ea55fc", - ], - [ - ["aes-256-ecb", 32, 0], - "dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087", - "0ac1d7e8655254c6814b46753932df88", - ], - [ - ["aes256", 32, 16], - "dc95c078a2408989ad48a2149284208708c374848c228233c2b34f332bd2e9d38b70c515a6663d38cdb8e6532b266491", - "2e62607a5e8b715e4cb229a12169f2b2", - ], - [ - ["aes-256-cbc", 32, 16], - "dc95c078a2408989ad48a2149284208708c374848c228233c2b34f332bd2e9d38b70c515a6663d38cdb8e6532b266491", - "2e62607a5e8b715e4cb229a12169f2b2", - ], - ] 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", - ], - [ - ["aes-192-ecb", 24, 0], - "aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7ab40eb56b6fc2aacf2e9254685cce891", - ], - [ - ["aes-256-ecb", 32, 0], - "dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a214928420877c45b49560579dd1ffc7ec626de2a968", - ], - [ - ["aes256", 32, 16], - "dc95c078a2408989ad48a2149284208708c374848c228233c2b34f332bd2e9d38b70c515a6663d38cdb8e6532b2664915d0dcc192580aee9ef8a8568193f1b44bfca557c6bab7dc79da07ffd42191b2659e6bee99cb2a6a7299f0e9a21686fc7", - ], - [ - ["aes-256-cbc", 32, 16], - "dc95c078a2408989ad48a2149284208708c374848c228233c2b34f332bd2e9d38b70c515a6663d38cdb8e6532b2664915d0dcc192580aee9ef8a8568193f1b44bfca557c6bab7dc79da07ffd42191b2659e6bee99cb2a6a7299f0e9a21686fc7", - ], - ] 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)); - }, -}); - -Deno.test({ - name: "createCipheriv - invalid algorithm", - fn() { - assertThrows( - () => - crypto.createCipheriv("foo", new Uint8Array(16), new Uint8Array(16)), - TypeError, - "Unknown cipher", - ); - }, -}); - -Deno.test({ - name: "createDecipheriv - invalid algorithm", - fn() { - assertThrows( - () => - crypto.createDecipheriv("foo", new Uint8Array(16), new Uint8Array(16)), - TypeError, - "Unknown cipher", - ); - }, -}); - -function setAutoPaddingTest( - { algorithm, keyLength, pad }: { - algorithm: string; - keyLength: number; - pad: boolean; - }, -) { - const key = crypto.randomBytes(keyLength); - const iv = algorithm.endsWith("ecb") ? null : crypto.randomBytes(16); - const data = pad - ? "0123456789abcdef0123456789abcde" // Not a multiple of block size - : "0123456789abcdef0123456789abcdef"; // Multiple of block size - - const cipher = crypto.createCipheriv(algorithm, key, iv); - cipher.setAutoPadding(pad); - const encrypted = cipher.update(data, "utf8", "latin1") + - cipher.final("latin1"); - - const decipher = crypto.createDecipheriv(algorithm, key, iv); - decipher.setAutoPadding(pad); - const decrypted = decipher.update(encrypted, "latin1", "utf8") + - decipher.final("utf8"); - - assertStrictEquals(decrypted, data); -} - -/** - * @todo(iuioiua) Add `*-gcm` algorithms once `Cipher.getAuthTag()` and - * `Decipher.setAuthTag()` are implemented. - */ -[ - { - algorithm: "aes-128-cbc", - keyLength: 16, - pad: false, - }, - { - algorithm: "aes-128-cbc", - keyLength: 16, - pad: true, - }, - { - algorithm: "aes-128-ecb", - keyLength: 16, - pad: false, - }, - { - algorithm: "aes-128-ecb", - keyLength: 16, - pad: true, - }, - { - algorithm: "aes-192-ecb", - keyLength: 24, - pad: false, - }, - { - algorithm: "aes-192-ecb", - keyLength: 24, - pad: true, - }, - { - algorithm: "aes256", - keyLength: 32, - pad: false, - }, - { - algorithm: "aes256", - keyLength: 32, - pad: true, - }, - { - algorithm: "aes-256-cbc", - keyLength: 32, - pad: false, - }, - { - algorithm: "aes-256-cbc", - keyLength: 32, - pad: true, - }, - { - algorithm: "aes-256-ecb", - keyLength: 32, - pad: false, - }, - { - algorithm: "aes-256-ecb", - keyLength: 32, - pad: true, - }, -].forEach((options) => { - Deno.test(`cipher.setAutoPadding() and decipher.setAutoPadding() - ${options.algorithm} ${options.pad ? "with" : "without"} padding`, () => { - setAutoPaddingTest(options); - }); -}); diff --git a/tests/wpt/suite b/tests/wpt/suite new file mode 160000 index 00000000000000..fb81ba9b33964b --- /dev/null +++ b/tests/wpt/suite @@ -0,0 +1 @@ +Subproject commit fb81ba9b33964b3177b4f6c1715d5f46c325b443