summaryrefslogtreecommitdiff
path: root/ext/node/crypto/cipher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/crypto/cipher.rs')
-rw-r--r--ext/node/crypto/cipher.rs73
1 files changed, 70 insertions, 3 deletions
diff --git a/ext/node/crypto/cipher.rs b/ext/node/crypto/cipher.rs
index 0833cb591..54cd61132 100644
--- a/ext/node/crypto/cipher.rs
+++ b/ext/node/crypto/cipher.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use aes::cipher::block_padding::Pkcs7;
+use aes::cipher::BlockDecryptMut;
use aes::cipher::BlockEncryptMut;
use aes::cipher::KeyIvInit;
use deno_core::error::type_error;
@@ -17,8 +18,8 @@ enum Cipher {
}
enum Decipher {
- // TODO(kt3k): implement Deciphers
- // Aes128Cbc(Box<cbc::Decryptor<aes::Aes128>>),
+ Aes128Cbc(Box<cbc::Decryptor<aes::Aes128>>),
+ // TODO(kt3k): add more algorithms Aes192Cbc, Aes256Cbc, Aes128ECB, Aes128GCM, etc.
}
pub struct CipherContext {
@@ -26,7 +27,7 @@ pub struct CipherContext {
}
pub struct DecipherContext {
- _decipher: Rc<RefCell<Decipher>>,
+ decipher: Rc<RefCell<Decipher>>,
}
impl CipherContext {
@@ -52,6 +53,29 @@ impl CipherContext {
}
}
+impl DecipherContext {
+ pub fn new(algorithm: &str, key: &[u8], iv: &[u8]) -> Result<Self, AnyError> {
+ Ok(Self {
+ decipher: Rc::new(RefCell::new(Decipher::new(algorithm, key, iv)?)),
+ })
+ }
+
+ pub fn decrypt(&self, input: &[u8], output: &mut [u8]) {
+ self.decipher.borrow_mut().decrypt(input, output);
+ }
+
+ pub fn r#final(
+ self,
+ input: &[u8],
+ output: &mut [u8],
+ ) -> Result<(), AnyError> {
+ Rc::try_unwrap(self.decipher)
+ .map_err(|_| type_error("Decipher context is already in use"))?
+ .into_inner()
+ .r#final(input, output)
+ }
+}
+
impl Resource for CipherContext {
fn name(&self) -> Cow<str> {
"cryptoCipher".into()
@@ -106,3 +130,46 @@ impl Cipher {
}
}
}
+
+impl Decipher {
+ fn new(
+ algorithm_name: &str,
+ key: &[u8],
+ iv: &[u8],
+ ) -> Result<Self, AnyError> {
+ use Decipher::*;
+ Ok(match algorithm_name {
+ "aes-128-cbc" => {
+ Aes128Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into())))
+ }
+ _ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))),
+ })
+ }
+
+ /// decrypt decrypts the data in the middle of the input.
+ fn decrypt(&mut self, input: &[u8], output: &mut [u8]) {
+ use Decipher::*;
+ match self {
+ Aes128Cbc(decryptor) => {
+ assert!(input.len() % 16 == 0);
+ for (input, output) in input.chunks(16).zip(output.chunks_mut(16)) {
+ decryptor.decrypt_block_b2b_mut(input.into(), output.into());
+ }
+ }
+ }
+ }
+
+ /// r#final decrypts the last block of the input data.
+ fn r#final(self, input: &[u8], output: &mut [u8]) -> Result<(), AnyError> {
+ assert!(input.len() == 16);
+ use Decipher::*;
+ match self {
+ Aes128Cbc(decryptor) => {
+ let _ = (*decryptor)
+ .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
+ .map_err(|_| type_error("Cannot unpad the input data"))?;
+ Ok(())
+ }
+ }
+ }
+}