summaryrefslogtreecommitdiff
path: root/ext/crypto/lib.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2021-08-26 16:18:07 +0530
committerGitHub <noreply@github.com>2021-08-26 12:48:07 +0200
commit23a9bc099d21ef7d45fe0f76e2fc53740ca98f6a (patch)
tree1fffaf83c0b6582acf33b042275e1b792a42e3e1 /ext/crypto/lib.rs
parent5d7d9d64434bd0a9f1fcf391dabc51693e8cf1ae (diff)
feat(ext/crypto): implement importKey and deriveBits for PBKDF2 (#11642)
Diffstat (limited to 'ext/crypto/lib.rs')
-rw-r--r--ext/crypto/lib.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index 9224562f6..b68bd7887 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -15,6 +15,7 @@ use serde::Deserialize;
use std::cell::RefCell;
use std::convert::TryInto;
+use std::num::NonZeroU32;
use std::rc::Rc;
use lazy_static::lazy_static;
@@ -27,6 +28,7 @@ use rand::SeedableRng;
use ring::digest;
use ring::hmac::Algorithm as HmacAlgorithm;
use ring::hmac::Key as HmacKey;
+use ring::pbkdf2;
use ring::rand as RingRand;
use ring::rand::SecureRandom;
use ring::signature::EcdsaKeyPair;
@@ -74,6 +76,7 @@ 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_derive_bits", op_async(op_crypto_derive_bits)),
("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)),
@@ -521,6 +524,49 @@ pub async fn op_crypto_verify_key(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
+pub struct DeriveKeyArg {
+ key: KeyData,
+ algorithm: Algorithm,
+ hash: Option<CryptoHash>,
+ length: usize,
+ iterations: Option<u32>,
+}
+
+pub async fn op_crypto_derive_bits(
+ _state: Rc<RefCell<OpState>>,
+ args: DeriveKeyArg,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<ZeroCopyBuf, AnyError> {
+ let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
+ let salt = &*zero_copy;
+ let algorithm = args.algorithm;
+ match algorithm {
+ Algorithm::Pbkdf2 => {
+ // The caller must validate these cases.
+ assert!(args.length > 0);
+ assert!(args.length % 8 == 0);
+
+ let algorithm = match args.hash.ok_or_else(not_supported)? {
+ CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1,
+ CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256,
+ CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384,
+ CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512,
+ };
+
+ // This will never panic. We have already checked length earlier.
+ let iterations =
+ NonZeroU32::new(args.iterations.ok_or_else(not_supported)?).unwrap();
+ let secret = args.key.data;
+ let mut out = vec![0; args.length / 8];
+ pbkdf2::derive(algorithm, iterations, salt, &secret, &mut out);
+ Ok(out.into())
+ }
+ _ => Err(type_error("Unsupported algorithm".to_string())),
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
pub struct EncryptArg {
key: KeyData,
algorithm: Algorithm,