summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/crypto/00_crypto.js4
-rw-r--r--ext/crypto/decrypt.rs155
-rw-r--r--ext/crypto/lib.rs126
3 files changed, 160 insertions, 125 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js
index f15238b3a..ca7960427 100644
--- a/ext/crypto/00_crypto.js
+++ b/ext/crypto/00_crypto.js
@@ -572,7 +572,7 @@
// 3-5.
const hashAlgorithm = key[_algorithm].hash.name;
- const plainText = await core.opAsync("op_crypto_decrypt_key", {
+ const plainText = await core.opAsync("op_crypto_decrypt", {
key: keyData,
algorithm: "RSA-OAEP",
hash: hashAlgorithm,
@@ -593,7 +593,7 @@
);
}
- const plainText = await core.opAsync("op_crypto_decrypt_key", {
+ const plainText = await core.opAsync("op_crypto_decrypt", {
key: keyData,
algorithm: "AES-CBC",
iv: normalizedAlgorithm.iv,
diff --git a/ext/crypto/decrypt.rs b/ext/crypto/decrypt.rs
new file mode 100644
index 000000000..f487d7e34
--- /dev/null
+++ b/ext/crypto/decrypt.rs
@@ -0,0 +1,155 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
+use crate::shared::*;
+use block_modes::BlockMode;
+use deno_core::error::custom_error;
+use deno_core::error::AnyError;
+use deno_core::OpState;
+use deno_core::ZeroCopyBuf;
+use rsa::pkcs1::FromRsaPrivateKey;
+use rsa::PaddingScheme;
+use serde::Deserialize;
+use sha1::Digest;
+use sha1::Sha1;
+use sha2::Sha256;
+use sha2::Sha384;
+use sha2::Sha512;
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DecryptOptions {
+ key: RawKeyData,
+ #[serde(flatten)]
+ algorithm: DecryptAlgorithm,
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase", tag = "algorithm")]
+pub enum DecryptAlgorithm {
+ #[serde(rename = "RSA-OAEP")]
+ RsaOaep {
+ hash: ShaHash,
+ #[serde(with = "serde_bytes")]
+ label: Vec<u8>,
+ },
+ #[serde(rename = "AES-CBC", rename_all = "camelCase")]
+ AesCbc {
+ #[serde(with = "serde_bytes")]
+ iv: Vec<u8>,
+ length: usize,
+ },
+}
+
+pub async fn op_crypto_decrypt(
+ _state: Rc<RefCell<OpState>>,
+ opts: DecryptOptions,
+ data: ZeroCopyBuf,
+) -> Result<ZeroCopyBuf, AnyError> {
+ let key = opts.key;
+ let fun = move || match opts.algorithm {
+ DecryptAlgorithm::RsaOaep { hash, label } => {
+ decrypt_rsa_oaep(key, hash, label, &data)
+ }
+ DecryptAlgorithm::AesCbc { iv, length } => {
+ decrypt_aes_cbc(key, length, iv, &data)
+ }
+ };
+ let buf = tokio::task::spawn_blocking(fun).await.unwrap()?;
+ Ok(buf.into())
+}
+
+fn decrypt_rsa_oaep(
+ key: RawKeyData,
+ hash: ShaHash,
+ label: Vec<u8>,
+ data: &[u8],
+) -> Result<Vec<u8>, deno_core::anyhow::Error> {
+ let key = key.as_rsa_private_key()?;
+
+ let private_key = rsa::RsaPrivateKey::from_pkcs1_der(key)?;
+ let label = Some(String::from_utf8_lossy(&label).to_string());
+
+ let padding = match hash {
+ ShaHash::Sha1 => PaddingScheme::OAEP {
+ digest: Box::new(Sha1::new()),
+ mgf_digest: Box::new(Sha1::new()),
+ label,
+ },
+ ShaHash::Sha256 => PaddingScheme::OAEP {
+ digest: Box::new(Sha256::new()),
+ mgf_digest: Box::new(Sha256::new()),
+ label,
+ },
+ ShaHash::Sha384 => PaddingScheme::OAEP {
+ digest: Box::new(Sha384::new()),
+ mgf_digest: Box::new(Sha384::new()),
+ label,
+ },
+ ShaHash::Sha512 => PaddingScheme::OAEP {
+ digest: Box::new(Sha512::new()),
+ mgf_digest: Box::new(Sha512::new()),
+ label,
+ },
+ };
+
+ private_key
+ .decrypt(padding, data)
+ .map_err(|e| custom_error("DOMExceptionOperationError", e.to_string()))
+}
+
+fn decrypt_aes_cbc(
+ key: RawKeyData,
+ length: usize,
+ iv: Vec<u8>,
+ data: &[u8],
+) -> Result<Vec<u8>, deno_core::anyhow::Error> {
+ let key = key.as_secret_key()?;
+
+ // 2.
+ let plaintext = match length {
+ 128 => {
+ // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
+ type Aes128Cbc =
+ block_modes::Cbc<aes::Aes128, block_modes::block_padding::Pkcs7>;
+ let cipher = Aes128Cbc::new_from_slices(key, &iv)?;
+
+ cipher.decrypt_vec(data).map_err(|_| {
+ custom_error(
+ "DOMExceptionOperationError",
+ "Decryption failed".to_string(),
+ )
+ })?
+ }
+ 192 => {
+ // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
+ type Aes192Cbc =
+ block_modes::Cbc<aes::Aes192, block_modes::block_padding::Pkcs7>;
+ let cipher = Aes192Cbc::new_from_slices(key, &iv)?;
+
+ cipher.decrypt_vec(data).map_err(|_| {
+ custom_error(
+ "DOMExceptionOperationError",
+ "Decryption failed".to_string(),
+ )
+ })?
+ }
+ 256 => {
+ // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
+ type Aes256Cbc =
+ block_modes::Cbc<aes::Aes256, block_modes::block_padding::Pkcs7>;
+ let cipher = Aes256Cbc::new_from_slices(key, &iv)?;
+
+ cipher.decrypt_vec(data).map_err(|_| {
+ custom_error(
+ "DOMExceptionOperationError",
+ "Decryption failed".to_string(),
+ )
+ })?
+ }
+ _ => unreachable!(),
+ };
+
+ // 6.
+ Ok(plaintext)
+}
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index 1bca433ff..c509cedd7 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -16,7 +16,6 @@ use std::cell::RefCell;
use std::num::NonZeroU32;
use std::rc::Rc;
-use block_modes::BlockMode;
use p256::elliptic_curve::sec1::FromEncodedPoint;
use p256::pkcs8::FromPrivateKey;
use rand::rngs::OsRng;
@@ -52,6 +51,7 @@ use std::path::PathBuf;
pub use rand; // Re-export rand
+mod decrypt;
mod encrypt;
mod export_key;
mod generate_key;
@@ -59,6 +59,7 @@ mod import_key;
mod key;
mod shared;
+pub use crate::decrypt::op_crypto_decrypt;
pub use crate::encrypt::op_crypto_encrypt;
pub use crate::export_key::op_crypto_export_key;
pub use crate::generate_key::op_crypto_generate_key;
@@ -91,7 +92,7 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
("op_crypto_import_key", op_sync(op_crypto_import_key)),
("op_crypto_export_key", op_sync(op_crypto_export_key)),
("op_crypto_encrypt", op_async(op_crypto_encrypt)),
- ("op_crypto_decrypt_key", op_async(op_crypto_decrypt_key)),
+ ("op_crypto_decrypt", op_async(op_crypto_decrypt)),
("op_crypto_subtle_digest", op_async(op_crypto_subtle_digest)),
("op_crypto_random_uuid", op_sync(op_crypto_random_uuid)),
])
@@ -779,127 +780,6 @@ impl<'a> TryFrom<rsa::pkcs8::der::asn1::Any<'a>>
}
}
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DecryptArg {
- key: KeyData,
- algorithm: Algorithm,
- // RSA-OAEP
- hash: Option<CryptoHash>,
- label: Option<ZeroCopyBuf>,
- // AES-CBC
- iv: Option<ZeroCopyBuf>,
- length: Option<usize>,
-}
-
-pub async fn op_crypto_decrypt_key(
- _state: Rc<RefCell<OpState>>,
- args: DecryptArg,
- zero_copy: ZeroCopyBuf,
-) -> Result<ZeroCopyBuf, AnyError> {
- let data = &*zero_copy;
- let algorithm = args.algorithm;
-
- match algorithm {
- Algorithm::RsaOaep => {
- let private_key: RsaPrivateKey =
- RsaPrivateKey::from_pkcs1_der(&*args.key.data)?;
- let label = args.label.map(|l| String::from_utf8_lossy(&*l).to_string());
- let padding = match args
- .hash
- .ok_or_else(|| type_error("Missing argument hash".to_string()))?
- {
- CryptoHash::Sha1 => PaddingScheme::OAEP {
- digest: Box::new(Sha1::new()),
- mgf_digest: Box::new(Sha1::new()),
- label,
- },
- CryptoHash::Sha256 => PaddingScheme::OAEP {
- digest: Box::new(Sha256::new()),
- mgf_digest: Box::new(Sha256::new()),
- label,
- },
- CryptoHash::Sha384 => PaddingScheme::OAEP {
- digest: Box::new(Sha384::new()),
- mgf_digest: Box::new(Sha384::new()),
- label,
- },
- CryptoHash::Sha512 => PaddingScheme::OAEP {
- digest: Box::new(Sha512::new()),
- mgf_digest: Box::new(Sha512::new()),
- label,
- },
- };
-
- Ok(
- private_key
- .decrypt(padding, data)
- .map_err(|e| {
- custom_error("DOMExceptionOperationError", e.to_string())
- })?
- .into(),
- )
- }
- Algorithm::AesCbc => {
- let key = &*args.key.data;
- let length = args
- .length
- .ok_or_else(|| type_error("Missing argument length".to_string()))?;
- let iv = args
- .iv
- .ok_or_else(|| type_error("Missing argument iv".to_string()))?;
-
- // 2.
- let plaintext = match length {
- 128 => {
- // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
- type Aes128Cbc =
- block_modes::Cbc<aes::Aes128, block_modes::block_padding::Pkcs7>;
- let cipher = Aes128Cbc::new_from_slices(key, &iv)?;
-
- cipher.decrypt_vec(data).map_err(|_| {
- custom_error(
- "DOMExceptionOperationError",
- "Decryption failed".to_string(),
- )
- })?
- }
- 192 => {
- // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
- type Aes192Cbc =
- block_modes::Cbc<aes::Aes192, block_modes::block_padding::Pkcs7>;
- let cipher = Aes192Cbc::new_from_slices(key, &iv)?;
-
- cipher.decrypt_vec(data).map_err(|_| {
- custom_error(
- "DOMExceptionOperationError",
- "Decryption failed".to_string(),
- )
- })?
- }
- 256 => {
- // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
- type Aes256Cbc =
- block_modes::Cbc<aes::Aes256, block_modes::block_padding::Pkcs7>;
- let cipher = Aes256Cbc::new_from_slices(key, &iv)?;
-
- cipher.decrypt_vec(data).map_err(|_| {
- custom_error(
- "DOMExceptionOperationError",
- "Decryption failed".to_string(),
- )
- })?
- }
- _ => unreachable!(),
- };
-
- // 6.
- Ok(plaintext.into())
- }
- _ => Err(type_error("Unsupported algorithm".to_string())),
- }
-}
-
pub fn op_crypto_random_uuid(
state: &mut OpState,
_: (),