diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2021-08-25 01:29:02 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-24 21:59:02 +0200 |
commit | 85a56e7144cb2e213eb670f754027d19e31c315a (patch) | |
tree | bc9757ef1340a14cd0efce3856bda3ef5ba9f2fa /ext/crypto/lib.rs | |
parent | 4853be20f2d649842ebc97124d8479c7aad7cc9b (diff) |
feat(ext/crypto): implement encrypt, decrypt & generateKey for RSA-OAEP (#11654)
Diffstat (limited to 'ext/crypto/lib.rs')
-rw-r--r-- | ext/crypto/lib.rs | 129 |
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, _: (), |