summaryrefslogtreecommitdiff
path: root/ext/crypto/encrypt.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-01-05 20:42:30 +0530
committerGitHub <noreply@github.com>2022-01-05 20:42:30 +0530
commitc74eb7a889322e88173cb044a670602d124fcc67 (patch)
treeb5502919639a3f1b6285e8c44dcb4e0465d530f1 /ext/crypto/encrypt.rs
parent9778545048a9908f62c24b93ae3ec0762e3db2d9 (diff)
feat(ext/crypto): implement AES-GCM encryption (#13119)
Diffstat (limited to 'ext/crypto/encrypt.rs')
-rw-r--r--ext/crypto/encrypt.rs82
1 files changed, 80 insertions, 2 deletions
diff --git a/ext/crypto/encrypt.rs b/ext/crypto/encrypt.rs
index 99f4762d0..f1d88438b 100644
--- a/ext/crypto/encrypt.rs
+++ b/ext/crypto/encrypt.rs
@@ -6,6 +6,13 @@ use crate::shared::*;
use aes::cipher::NewCipher;
use aes::BlockEncrypt;
use aes::NewBlockCipher;
+use aes_gcm::aead::generic_array::typenum::U12;
+use aes_gcm::aes::Aes192;
+use aes_gcm::AeadInPlace;
+use aes_gcm::Aes128Gcm;
+use aes_gcm::Aes256Gcm;
+use aes_gcm::NewAead;
+use aes_gcm::Nonce;
use ctr::Ctr;
use block_modes::BlockMode;
@@ -53,6 +60,15 @@ pub enum EncryptAlgorithm {
iv: Vec<u8>,
length: usize,
},
+ #[serde(rename = "AES-GCM", rename_all = "camelCase")]
+ AesGcm {
+ #[serde(with = "serde_bytes")]
+ iv: Vec<u8>,
+ #[serde(with = "serde_bytes")]
+ additional_data: Option<Vec<u8>>,
+ length: usize,
+ tag_length: usize,
+ },
#[serde(rename = "AES-CTR", rename_all = "camelCase")]
AesCtr {
#[serde(with = "serde_bytes")]
@@ -74,6 +90,12 @@ pub async fn op_crypto_encrypt(
EncryptAlgorithm::AesCbc { iv, length } => {
encrypt_aes_cbc(key, length, iv, &data)
}
+ EncryptAlgorithm::AesGcm {
+ iv,
+ additional_data,
+ length,
+ tag_length,
+ } => encrypt_aes_gcm(key, length, tag_length, iv, additional_data, &data),
EncryptAlgorithm::AesCtr {
counter,
ctr_length,
@@ -89,7 +111,7 @@ fn encrypt_rsa_oaep(
hash: ShaHash,
label: Vec<u8>,
data: &[u8],
-) -> Result<Vec<u8>, deno_core::anyhow::Error> {
+) -> Result<Vec<u8>, AnyError> {
let label = String::from_utf8_lossy(&label).to_string();
let public_key = key.as_rsa_public_key()?;
@@ -129,7 +151,7 @@ fn encrypt_aes_cbc(
length: usize,
iv: Vec<u8>,
data: &[u8],
-) -> Result<Vec<u8>, deno_core::anyhow::Error> {
+) -> Result<Vec<u8>, AnyError> {
let key = key.as_secret_key()?;
let ciphertext = match length {
128 => {
@@ -161,6 +183,62 @@ fn encrypt_aes_cbc(
Ok(ciphertext)
}
+fn encrypt_aes_gcm(
+ key: RawKeyData,
+ length: usize,
+ tag_length: usize,
+ iv: Vec<u8>,
+ additional_data: Option<Vec<u8>>,
+ data: &[u8],
+) -> Result<Vec<u8>, AnyError> {
+ let key = key.as_secret_key()?;
+ let additional_data = additional_data.unwrap_or_default();
+
+ // Fixed 96-bit nonce
+ if iv.len() != 12 {
+ return Err(type_error("iv length not equal to 12"));
+ }
+
+ let nonce = Nonce::from_slice(&iv);
+
+ let mut ciphertext = data.to_vec();
+ let tag = match length {
+ 128 => {
+ let cipher = Aes128Gcm::new_from_slice(key)
+ .map_err(|_| operation_error("Encryption failed"))?;
+ cipher
+ .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext)
+ .map_err(|_| operation_error("Encryption failed"))?
+ }
+ 192 => {
+ type Aes192Gcm = aes_gcm::AesGcm<Aes192, U12>;
+
+ let cipher = Aes192Gcm::new_from_slice(key)
+ .map_err(|_| operation_error("Encryption failed"))?;
+ cipher
+ .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext)
+ .map_err(|_| operation_error("Encryption failed"))?
+ }
+ 256 => {
+ let cipher = Aes256Gcm::new_from_slice(key)
+ .map_err(|_| operation_error("Encryption failed"))?;
+ cipher
+ .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext)
+ .map_err(|_| operation_error("Encryption failed"))?
+ }
+ _ => return Err(type_error("invalid length")),
+ };
+
+ // Truncated tag to the specified tag length.
+ // `tag` is fixed to be 16 bytes long and (tag_length / 8) is always <= 16
+ let tag = &tag[..(tag_length / 8)];
+
+ // C | T
+ ciphertext.extend_from_slice(tag);
+
+ Ok(ciphertext)
+}
+
fn encrypt_aes_ctr_gen<B, F>(
key: &[u8],
counter: &[u8],