Skip to content

Commit

Permalink
fix(ext/node): implement aes-128-ctr, aes-192-ctr, and `aes-256-c…
Browse files Browse the repository at this point in the history
…tr` (#27630)

Fixes #24864

Need to add some tests, also unsure about the right counter size (went
with 128 bit to be safe)

---------

Co-authored-by: Yoshiya Hinosawa <[email protected]>
  • Loading branch information
nathanwhit and kt3k authored Jan 28, 2025
1 parent 0e47205 commit 094e268
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 77 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ cbc = { version = "=0.1.2", features = ["alloc"] }
chrono = { version = "0.4", default-features = false, features = ["std", "serde"] }
color-print = "0.3.5"
console_static_text = "=0.8.1"
ctr = { version = "0.9.2", features = ["alloc"] }
dashmap = "5.5.3"
data-encoding = "2.3.3"
data-url = "=0.3.1"
Expand Down
2 changes: 1 addition & 1 deletion ext/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ aes-kw = { version = "0.2.1", features = ["alloc"] }
base64.workspace = true
cbc.workspace = true
const-oid = "0.9.0"
ctr = "0.9.1"
ctr.workspace = true
curve25519-dalek = "4.1.3"
deno_core.workspace = true
deno_error.workspace = true
Expand Down
1 change: 1 addition & 0 deletions ext/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ brotli.workspace = true
bytes.workspace = true
cbc.workspace = true
const-oid = "0.9.5"
ctr.workspace = true
data-encoding.workspace = true
deno_core.workspace = true
deno_error.workspace = true
Expand Down
92 changes: 92 additions & 0 deletions ext/node/ops/crypto/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use aes::cipher::BlockDecryptMut;
use aes::cipher::BlockEncryptMut;
use aes::cipher::KeyIvInit;
use aes::cipher::KeySizeUser;
use aes::cipher::StreamCipher;
use deno_core::Resource;
use digest::generic_array::GenericArray;
use digest::KeyInit;
Expand All @@ -26,6 +27,9 @@ enum Cipher {
Aes128Gcm(Box<Aes128Gcm>),
Aes256Gcm(Box<Aes256Gcm>),
Aes256Cbc(Box<cbc::Encryptor<aes::Aes256>>),
Aes128Ctr(Box<ctr::Ctr128BE<aes::Aes128>>),
Aes192Ctr(Box<ctr::Ctr128BE<aes::Aes192>>),
Aes256Ctr(Box<ctr::Ctr128BE<aes::Aes256>>),
// TODO(kt3k): add more algorithms Aes192Cbc, etc.
}

Expand All @@ -37,6 +41,9 @@ enum Decipher {
Aes128Gcm(Box<Aes128Gcm>),
Aes256Gcm(Box<Aes256Gcm>),
Aes256Cbc(Box<cbc::Decryptor<aes::Aes256>>),
Aes128Ctr(Box<ctr::Ctr128BE<aes::Aes128>>),
Aes192Ctr(Box<ctr::Ctr128BE<aes::Aes192>>),
Aes256Ctr(Box<ctr::Ctr128BE<aes::Aes256>>),
// TODO(kt3k): add more algorithms Aes192Cbc, Aes128GCM, etc.
}

Expand Down Expand Up @@ -220,6 +227,33 @@ impl Cipher {

Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into())))
}
"aes-256-ctr" => {
if key.len() != 32 {
return Err(CipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(CipherError::InvalidInitializationVector);
}
Aes256Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
"aes-192-ctr" => {
if key.len() != 24 {
return Err(CipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(CipherError::InvalidInitializationVector);
}
Aes192Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
"aes-128-ctr" => {
if key.len() != 16 {
return Err(CipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(CipherError::InvalidInitializationVector);
}
Aes128Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
_ => return Err(CipherError::UnknownCipher(algorithm_name.to_string())),
})
}
Expand Down Expand Up @@ -279,6 +313,15 @@ impl Cipher {
encryptor.encrypt_block_b2b_mut(input.into(), output.into());
}
}
Aes256Ctr(encryptor) => {
encryptor.apply_keystream_b2b(input, output).unwrap();
}
Aes192Ctr(encryptor) => {
encryptor.apply_keystream_b2b(input, output).unwrap();
}
Aes128Ctr(encryptor) => {
encryptor.apply_keystream_b2b(input, output).unwrap();
}
}
}

Expand Down Expand Up @@ -359,6 +402,7 @@ impl Cipher {
);
Ok(None)
}
(Aes256Ctr(_) | Aes128Ctr(_) | Aes192Ctr(_), _) => Ok(None),
}
}

Expand Down Expand Up @@ -444,6 +488,33 @@ impl Decipher {

Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into())))
}
"aes-256-ctr" => {
if key.len() != 32 {
return Err(DecipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(DecipherError::InvalidInitializationVector);
}
Aes256Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
"aes-192-ctr" => {
if key.len() != 24 {
return Err(DecipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(DecipherError::InvalidInitializationVector);
}
Aes192Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
"aes-128-ctr" => {
if key.len() != 16 {
return Err(DecipherError::InvalidKeyLength);
}
if iv.len() != 16 {
return Err(DecipherError::InvalidInitializationVector);
}
Aes128Ctr(Box::new(ctr::Ctr128BE::new(key.into(), iv.into())))
}
_ => {
return Err(DecipherError::UnknownCipher(algorithm_name.to_string()))
}
Expand Down Expand Up @@ -505,6 +576,15 @@ impl Decipher {
decryptor.decrypt_block_b2b_mut(input.into(), output.into());
}
}
Aes256Ctr(decryptor) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
}
Aes192Ctr(decryptor) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
}
Aes128Ctr(decryptor) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
}
}
}

Expand Down Expand Up @@ -615,6 +695,18 @@ impl Decipher {
);
Ok(())
}
(Aes256Ctr(mut decryptor), _) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
Ok(())
}
(Aes192Ctr(mut decryptor), _) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
Ok(())
}
(Aes128Ctr(mut decryptor), _) => {
decryptor.apply_keystream_b2b(input, output).unwrap();
Ok(())
}
}
}
}
8 changes: 6 additions & 2 deletions ext/node/polyfills/internal/crypto/cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ export class Cipheriv extends Transform implements Cipher {
this.#cache = new BlockModeCache(false);
this.#context = op_node_create_cipheriv(cipher, toU8(key), toU8(iv));
this.#needsBlockCache =
!(cipher == "aes-128-gcm" || cipher == "aes-256-gcm");
!(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" ||
cipher == "aes-128-ctr" || cipher == "aes-192-ctr" ||
cipher == "aes-256-ctr");
if (this.#context == 0) {
throw new TypeError("Unknown cipher");
}
Expand Down Expand Up @@ -344,7 +346,9 @@ export class Decipheriv extends Transform implements Cipher {
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");
!(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" ||
cipher == "aes-128-ctr" || cipher == "aes-192-ctr" ||
cipher == "aes-256-ctr");
if (this.#context == 0) {
throw new TypeError("Unknown cipher");
}
Expand Down
Loading

0 comments on commit 094e268

Please sign in to comment.