summaryrefslogtreecommitdiff
path: root/ext/crypto/decrypt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/crypto/decrypt.rs')
-rw-r--r--ext/crypto/decrypt.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/ext/crypto/decrypt.rs b/ext/crypto/decrypt.rs
index f487d7e34..90916f9c3 100644
--- a/ext/crypto/decrypt.rs
+++ b/ext/crypto/decrypt.rs
@@ -2,8 +2,18 @@ use std::cell::RefCell;
use std::rc::Rc;
use crate::shared::*;
+use aes::BlockEncrypt;
+use aes::NewBlockCipher;
use block_modes::BlockMode;
+use ctr::cipher::NewCipher;
+use ctr::cipher::StreamCipher;
+use ctr::flavors::Ctr128BE;
+use ctr::flavors::Ctr32BE;
+use ctr::flavors::Ctr64BE;
+use ctr::flavors::CtrFlavor;
+use ctr::Ctr;
use deno_core::error::custom_error;
+use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
@@ -39,6 +49,13 @@ pub enum DecryptAlgorithm {
iv: Vec<u8>,
length: usize,
},
+ #[serde(rename = "AES-CTR", rename_all = "camelCase")]
+ AesCtr {
+ #[serde(with = "serde_bytes")]
+ counter: Vec<u8>,
+ ctr_length: usize,
+ key_length: usize,
+ },
}
pub async fn op_crypto_decrypt(
@@ -54,6 +71,11 @@ pub async fn op_crypto_decrypt(
DecryptAlgorithm::AesCbc { iv, length } => {
decrypt_aes_cbc(key, length, iv, &data)
}
+ DecryptAlgorithm::AesCtr {
+ counter,
+ ctr_length,
+ key_length,
+ } => decrypt_aes_ctr(key, key_length, &counter, ctr_length, &data),
};
let buf = tokio::task::spawn_blocking(fun).await.unwrap()?;
Ok(buf.into())
@@ -153,3 +175,56 @@ fn decrypt_aes_cbc(
// 6.
Ok(plaintext)
}
+
+fn decrypt_aes_ctr_gen<B, F>(
+ key: &[u8],
+ counter: &[u8],
+ data: &[u8],
+) -> Result<Vec<u8>, AnyError>
+where
+ B: BlockEncrypt + NewBlockCipher,
+ F: CtrFlavor<B::BlockSize>,
+{
+ let mut cipher = Ctr::<B, F>::new(key.into(), counter.into());
+
+ let mut plaintext = data.to_vec();
+ cipher
+ .try_apply_keystream(&mut plaintext)
+ .map_err(|_| operation_error("tried to decrypt too much data"))?;
+
+ Ok(plaintext)
+}
+
+fn decrypt_aes_ctr(
+ key: RawKeyData,
+ key_length: usize,
+ counter: &[u8],
+ ctr_length: usize,
+ data: &[u8],
+) -> Result<Vec<u8>, deno_core::anyhow::Error> {
+ let key = key.as_secret_key()?;
+
+ match ctr_length {
+ 32 => match key_length {
+ 128 => decrypt_aes_ctr_gen::<aes::Aes128, Ctr32BE>(key, counter, data),
+ 192 => decrypt_aes_ctr_gen::<aes::Aes192, Ctr32BE>(key, counter, data),
+ 256 => decrypt_aes_ctr_gen::<aes::Aes256, Ctr32BE>(key, counter, data),
+ _ => Err(type_error("invalid length")),
+ },
+ 64 => match key_length {
+ 128 => decrypt_aes_ctr_gen::<aes::Aes128, Ctr64BE>(key, counter, data),
+ 192 => decrypt_aes_ctr_gen::<aes::Aes192, Ctr64BE>(key, counter, data),
+ 256 => decrypt_aes_ctr_gen::<aes::Aes256, Ctr64BE>(key, counter, data),
+ _ => Err(type_error("invalid length")),
+ },
+ 128 => match key_length {
+ 128 => decrypt_aes_ctr_gen::<aes::Aes128, Ctr128BE>(key, counter, data),
+ 192 => decrypt_aes_ctr_gen::<aes::Aes192, Ctr128BE>(key, counter, data),
+ 256 => decrypt_aes_ctr_gen::<aes::Aes256, Ctr128BE>(key, counter, data),
+ _ => Err(type_error("invalid length")),
+ },
+ _ => Err(type_error(
+ "invalid counter length. Currently supported 32/64/128 bits",
+ )),
+ }
+}