From 3f15e300625723df10c564c4e29ec276288a931b Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 13 Sep 2024 01:13:56 +0900 Subject: [PATCH] fix(ext/node): fix Decipheriv when autoPadding disabled (#25598) This change fixes Decipheriv behavior when autoPadding disabled and enabled. By this change, the example given in https://github.com/denoland/deno/issues/20924#issuecomment-2345931295 works in the same way as Node. closes #20924 --- ext/node/polyfills/internal/crypto/cipher.ts | 7 +++- tests/unit_node/crypto/crypto_cipher_test.ts | 38 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index a1449cd870ffba..c1c5ce8901bef4 100644 --- a/ext/node/polyfills/internal/crypto/cipher.ts +++ b/ext/node/polyfills/internal/crypto/cipher.ts @@ -306,6 +306,10 @@ class BlockModeCache { this.cache = this.cache.subarray(len); return out; } + + set lastChunkIsNonZero(value: boolean) { + this.#lastChunkIsNonZero = value; + } } export class Decipheriv extends Transform implements Cipher { @@ -338,7 +342,7 @@ export class Decipheriv extends Transform implements Cipher { }, ...options, }); - this.#cache = new BlockModeCache(true); + this.#cache = new BlockModeCache(this.#autoPadding); this.#context = op_node_create_decipheriv(cipher, toU8(key), toU8(iv)); this.#needsBlockCache = !(cipher == "aes-128-gcm" || cipher == "aes-256-gcm"); @@ -386,6 +390,7 @@ export class Decipheriv extends Transform implements Cipher { setAutoPadding(autoPadding?: boolean): this { this.#autoPadding = Boolean(autoPadding); + this.#cache.lastChunkIsNonZero = this.#autoPadding; return this; } diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index 20b9d052f17abc..65a5b29eeb6cd4 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -378,3 +378,41 @@ Deno.test({ assertEquals(info2.ivLength, 16); }, }); + +Deno.test({ + name: + "createDecipheriv - handling of the last chunk when auto padding enabled/disabled", + fn() { + const algorithm = "aes-256-cbc"; + const key = Buffer.from( + "84dcdd964968734fdf0de4a2cba471c2e0a753930b841c014b1e77f456b5797b", + "hex", + ); + const val = Buffer.from( + "feabbdf66e2c71cc780d0cd2765dcce283e8ae7e58fcc1a9acafc678581e0e06", + "hex", + ); + const iv = Buffer.alloc(16, 0); + + { + const decipher = crypto.createDecipheriv(algorithm, key, iv); + decipher.setAutoPadding(false); + assertEquals( + decipher.update(val, undefined, "hex"), + "ed2c908f26571bf8e50d60b77fb9c25f95b933b59111543c6fac41ad6b47e681", + ); + assertEquals(decipher.final("hex"), ""); + } + + { + const decipher = crypto.createDecipheriv(algorithm, key, iv); + assertEquals( + decipher.update(val, undefined, "hex"), + "ed2c908f26571bf8e50d60b77fb9c25f", + ); + assertThrows(() => { + decipher.final(); + }); + } + }, +});