diff options
Diffstat (limited to 'ext/node/crypto/mod.rs')
-rw-r--r-- | ext/node/crypto/mod.rs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/ext/node/crypto/mod.rs b/ext/node/crypto/mod.rs index 53d064d86..be4035561 100644 --- a/ext/node/crypto/mod.rs +++ b/ext/node/crypto/mod.rs @@ -240,3 +240,58 @@ pub fn op_node_decipheriv_final( .map_err(|_| type_error("Cipher context is already in use"))?; context.r#final(input, output) } + +fn pbkdf2_sync( + password: &[u8], + salt: &[u8], + iterations: u32, + digest: &str, + derived_key: &mut [u8], +) -> Result<(), AnyError> { + macro_rules! pbkdf2_hmac { + ($digest:ty) => {{ + pbkdf2::pbkdf2_hmac::<$digest>(password, salt, iterations, derived_key) + }}; + } + + match digest { + "md4" => pbkdf2_hmac!(md4::Md4), + "md5" => pbkdf2_hmac!(md5::Md5), + "ripemd160" => pbkdf2_hmac!(ripemd::Ripemd160), + "sha1" => pbkdf2_hmac!(sha1::Sha1), + "sha224" => pbkdf2_hmac!(sha2::Sha224), + "sha256" => pbkdf2_hmac!(sha2::Sha256), + "sha384" => pbkdf2_hmac!(sha2::Sha384), + "sha512" => pbkdf2_hmac!(sha2::Sha512), + _ => return Err(type_error("Unknown digest")), + } + + Ok(()) +} + +#[op] +pub fn op_node_pbkdf2( + password: StringOrBuffer, + salt: StringOrBuffer, + iterations: u32, + digest: &str, + derived_key: &mut [u8], +) -> bool { + pbkdf2_sync(&password, &salt, iterations, digest, derived_key).is_ok() +} + +#[op] +pub async fn op_node_pbkdf2_async( + password: StringOrBuffer, + salt: StringOrBuffer, + iterations: u32, + digest: String, + keylen: usize, +) -> Result<ZeroCopyBuf, AnyError> { + tokio::task::spawn_blocking(move || { + let mut derived_key = vec![0; keylen]; + pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key) + .map(|_| derived_key.into()) + }) + .await? +} |