seq_runtime/crypto/
pbkdf.rs1use crate::seqstring::global_string;
4use crate::stack::{Stack, pop, push};
5use crate::value::Value;
6
7use sha2::Sha256;
8
9use super::{AES_KEY_SIZE, MIN_PBKDF2_ITERATIONS};
10
11#[unsafe(no_mangle)]
27pub unsafe extern "C" fn patch_seq_crypto_pbkdf2_sha256(stack: Stack) -> Stack {
28 assert!(!stack.is_null(), "crypto.pbkdf2-sha256: stack is null");
29
30 let (stack, iterations_val) = unsafe { pop(stack) };
31 let (stack, salt_val) = unsafe { pop(stack) };
32 let (stack, password_val) = unsafe { pop(stack) };
33
34 match (password_val, salt_val, iterations_val) {
35 (Value::String(password), Value::String(salt), Value::Int(iterations)) => {
36 if iterations < MIN_PBKDF2_ITERATIONS {
38 let stack = unsafe { push(stack, Value::String(global_string(String::new()))) };
39 return unsafe { push(stack, Value::Bool(false)) };
40 }
41
42 let key = derive_key_pbkdf2(password.as_str(), salt.as_str(), iterations as u32);
43 let key_hex = hex::encode(key);
44 let stack = unsafe { push(stack, Value::String(global_string(key_hex))) };
45 unsafe { push(stack, Value::Bool(true)) }
46 }
47 _ => panic!("crypto.pbkdf2-sha256: expected String, String, Int on stack"),
48 }
49}
50
51pub(super) fn derive_key_pbkdf2(password: &str, salt: &str, iterations: u32) -> [u8; AES_KEY_SIZE] {
52 let mut key = [0u8; AES_KEY_SIZE];
53 pbkdf2::pbkdf2_hmac::<Sha256>(password.as_bytes(), salt.as_bytes(), iterations, &mut key);
54 key
55}