Skip to main content
Glama
pbkdf2.rs3.25 kB
use std::num::NonZeroU32; use aws_lc_rs::pbkdf2; use indexmap::IndexSet; use serde::{ Deserialize, Serialize, }; use super::{ check_usages_subset, CryptoHash, CryptoKey, CryptoKeyKind, ImportKeyInput, KeyType, KeyUsage, DERIVE_BITS_MAX, }; use crate::convert_v8::{ DOMException, DOMExceptionName, }; pub(crate) struct Pbkdf2Key { secret: Vec<u8>, } #[derive(Deserialize, Debug)] pub(crate) struct ImportKeyAlgorithm; #[derive(Deserialize, Debug)] pub(crate) struct Pbkdf2Params { #[serde(with = "super::nullary_algorithm")] hash: CryptoHash, iterations: u32, salt: serde_bytes::ByteBuf, } #[derive(Serialize, Debug)] #[serde(rename = "PBKDF2")] #[serde(tag = "name")] pub(crate) struct Pbkdf2Algorithm {} pub(crate) fn derive_bits( algorithm: Pbkdf2Params, key: &CryptoKey, length: Option<usize>, ) -> anyhow::Result<Vec<u8>> { let Pbkdf2Params { hash, iterations, salt, } = algorithm; let Some(iterations) = NonZeroU32::new(iterations) else { anyhow::bail!(DOMException::new( "iterations cannot be zero", DOMExceptionName::OperationError )) }; let Some(length) = length else { anyhow::bail!(DOMException::new( "length cannot be null", DOMExceptionName::OperationError )) }; anyhow::ensure!( length % 8 == 0, DOMException::new( "length must be a multiple of 8", DOMExceptionName::OperationError ) ); anyhow::ensure!( length <= DERIVE_BITS_MAX, DOMException::new( format!("cannot generate more than {DERIVE_BITS_MAX} bits"), DOMExceptionName::OperationError ) ); let CryptoKeyKind::Pbkdf2 { key, .. } = &key.kind else { anyhow::bail!(DOMException::new( "Key algorithm mismatch", DOMExceptionName::InvalidAccessError )) }; let algorithm = match hash { CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1, CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256, CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384, CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512, }; let secret = &key.secret; let mut out = vec![0; length / 8]; pbkdf2::derive(algorithm, iterations, &salt, secret, &mut out); Ok(out) } pub(crate) fn import_key( format: ImportKeyInput, extractable: bool, usages: IndexSet<KeyUsage>, ) -> anyhow::Result<CryptoKey> { let ImportKeyInput::Raw(secret) = format else { anyhow::bail!(DOMException::new( "unsupported input format", DOMExceptionName::NotSupportedError )) }; check_usages_subset(&usages, &[KeyUsage::DeriveKey, KeyUsage::DeriveBits])?; anyhow::ensure!( !extractable, DOMException::new( "PBKDF2 keys cannot be extractable", DOMExceptionName::SyntaxError ) ); Ok(CryptoKey { kind: CryptoKeyKind::Pbkdf2 { algorithm: Pbkdf2Algorithm {}, key: Pbkdf2Key { secret }, }, r#type: KeyType::Secret, extractable, usages, }) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server