summaryrefslogtreecommitdiff
path: root/ext/crypto/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/crypto/lib.rs')
-rw-r--r--ext/crypto/lib.rs129
1 files changed, 128 insertions, 1 deletions
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index e77b34987..9224562f6 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -74,6 +74,8 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
("op_crypto_generate_key", op_async(op_crypto_generate_key)),
("op_crypto_sign_key", op_async(op_crypto_sign_key)),
("op_crypto_verify_key", op_async(op_crypto_verify_key)),
+ ("op_crypto_encrypt_key", op_async(op_crypto_encrypt_key)),
+ ("op_crypto_decrypt_key", op_async(op_crypto_decrypt_key)),
("op_crypto_subtle_digest", op_async(op_crypto_subtle_digest)),
("op_crypto_random_uuid", op_sync(op_crypto_random_uuid)),
])
@@ -128,7 +130,7 @@ pub async fn op_crypto_generate_key(
let algorithm = args.name;
let key = match algorithm {
- Algorithm::RsassaPkcs1v15 | Algorithm::RsaPss => {
+ Algorithm::RsassaPkcs1v15 | Algorithm::RsaPss | Algorithm::RsaOaep => {
let public_exponent = args.public_exponent.ok_or_else(not_supported)?;
let modulus_length = args.modulus_length.ok_or_else(not_supported)?;
@@ -517,6 +519,131 @@ pub async fn op_crypto_verify_key(
Ok(verification)
}
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct EncryptArg {
+ key: KeyData,
+ algorithm: Algorithm,
+ hash: Option<CryptoHash>,
+ label: Option<ZeroCopyBuf>,
+}
+
+pub async fn op_crypto_encrypt_key(
+ _state: Rc<RefCell<OpState>>,
+ args: EncryptArg,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<ZeroCopyBuf, AnyError> {
+ let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
+ let data = &*zero_copy;
+ let algorithm = args.algorithm;
+
+ match algorithm {
+ Algorithm::RsaOaep => {
+ let public_key: RsaPublicKey =
+ RsaPrivateKey::from_pkcs8_der(&*args.key.data)?.to_public_key();
+ let label = args.label.map(|l| String::from_utf8_lossy(&*l).to_string());
+ let mut rng = OsRng;
+ 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(
+ public_key
+ .encrypt(&mut rng, padding, data)
+ .map_err(|e| {
+ custom_error("DOMExceptionOperationError", e.to_string())
+ })?
+ .into(),
+ )
+ }
+ _ => Err(type_error("Unsupported algorithm".to_string())),
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DecryptArg {
+ key: KeyData,
+ algorithm: Algorithm,
+ hash: Option<CryptoHash>,
+ label: Option<ZeroCopyBuf>,
+}
+
+pub async fn op_crypto_decrypt_key(
+ _state: Rc<RefCell<OpState>>,
+ args: DecryptArg,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<ZeroCopyBuf, AnyError> {
+ let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
+ let data = &*zero_copy;
+ let algorithm = args.algorithm;
+
+ match algorithm {
+ Algorithm::RsaOaep => {
+ let private_key: RsaPrivateKey =
+ RsaPrivateKey::from_pkcs8_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(),
+ )
+ }
+ _ => Err(type_error("Unsupported algorithm".to_string())),
+ }
+}
+
pub fn op_crypto_random_uuid(
state: &mut OpState,
_: (),