diff options
Diffstat (limited to 'ext/node/crypto/cipher.rs')
-rw-r--r-- | ext/node/crypto/cipher.rs | 73 |
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(()) + } + } + } +} |