Skip to content

Commit 70497bb

Browse files
bartlomiejuclaude
andauthored
fix(ext/node): make setAutoPadding(false) a no-op for GCM ciphers (#32290)
## Summary - GCM is a stream cipher mode that doesn't use block padding. In Node.js, `setAutoPadding()` is a no-op for GCM modes, but Deno was throwing `setAutoPadding(false) not supported for Aes128Gcm/Aes256Gcm yet` when called on GCM deciphers. - This broke npm packages like `ssh2` that set auto-padding to false by default. - Merges the `auto_pad=false` arms into the existing `auto_pad=true` arms (using `_` wildcard) for both `Aes128Gcm` and `Aes256Gcm` in `Decipher::final()`, and removes the now-unused error variants. Closes #29425 Closes #28589 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fd9def3 commit 70497bb

2 files changed

Lines changed: 35 additions & 14 deletions

File tree

ext/node_crypto/cipher.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,6 @@ pub enum DecipherError {
505505
#[error("Failed to authenticate data")]
506506
DataAuthenticationFailed,
507507
#[class(type)]
508-
#[error("setAutoPadding(false) not supported for Aes128Gcm yet")]
509-
SetAutoPaddingFalseAes128GcmUnsupported,
510-
#[class(type)]
511-
#[error("setAutoPadding(false) not supported for Aes256Gcm yet")]
512-
SetAutoPaddingFalseAes256GcmUnsupported,
513-
#[class(type)]
514508
#[error("Unknown cipher {0}")]
515509
UnknownCipher(String),
516510
}
@@ -806,7 +800,7 @@ impl Decipher {
806800
);
807801
Ok(())
808802
}
809-
(Aes128Gcm(decipher, auth_tag_length), true) => {
803+
(Aes128Gcm(decipher, auth_tag_length), _) => {
810804
let tag = decipher.finish();
811805
let tag_slice = tag.as_slice();
812806
let truncated_tag = if let Some(len) = auth_tag_length {
@@ -820,10 +814,7 @@ impl Decipher {
820814
Err(DecipherError::DataAuthenticationFailed)
821815
}
822816
}
823-
(Aes128Gcm(..), false) => {
824-
Err(DecipherError::SetAutoPaddingFalseAes128GcmUnsupported)
825-
}
826-
(Aes256Gcm(decipher, auth_tag_length), true) => {
817+
(Aes256Gcm(decipher, auth_tag_length), _) => {
827818
let tag = decipher.finish();
828819
let tag_slice = tag.as_slice();
829820
let truncated_tag = if let Some(len) = auth_tag_length {
@@ -837,9 +828,6 @@ impl Decipher {
837828
Err(DecipherError::DataAuthenticationFailed)
838829
}
839830
}
840-
(Aes256Gcm(..), false) => {
841-
Err(DecipherError::SetAutoPaddingFalseAes256GcmUnsupported)
842-
}
843831
(Aes256Cbc(decryptor), true) => {
844832
assert_block_len!(input.len(), 16);
845833
let _ = (*decryptor)

tests/unit_node/crypto/crypto_cipher_gcm_test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,39 @@ Deno.test({
146146
},
147147
});
148148

149+
Deno.test({
150+
name: "aes-128-gcm and aes-256-gcm with setAutoPadding(false)",
151+
fn() {
152+
for (const bits of ["128", "256"] as const) {
153+
const algo = `aes-${bits}-gcm` as const;
154+
const keyLen = bits === "128" ? 16 : 32;
155+
const key = Buffer.alloc(keyLen, 0xaa);
156+
const iv = Buffer.alloc(12, 0xbb);
157+
const plaintext = "Hello, GCM with setAutoPadding(false)!";
158+
159+
// Encrypt
160+
const cipher = crypto.createCipheriv(algo, key, iv);
161+
cipher.setAutoPadding(false);
162+
const encrypted = Buffer.concat([
163+
cipher.update(plaintext, "utf8"),
164+
cipher.final(),
165+
]);
166+
const authTag = cipher.getAuthTag();
167+
168+
// Decrypt
169+
const decipher = crypto.createDecipheriv(algo, key, iv);
170+
decipher.setAutoPadding(false);
171+
decipher.setAuthTag(authTag);
172+
const decrypted = Buffer.concat([
173+
decipher.update(encrypted),
174+
decipher.final(),
175+
]);
176+
177+
assertEquals(decrypted.toString("utf8"), plaintext);
178+
}
179+
},
180+
});
181+
149182
Deno.test({
150183
name: "aes gcm with invalid key length",
151184
fn() {

0 commit comments

Comments
 (0)