use crate::seqstring::global_string;
use crate::stack::{Stack, pop, push};
use crate::value::Value;
use sha2::Sha256;
use super::{AES_KEY_SIZE, MIN_PBKDF2_ITERATIONS};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_crypto_pbkdf2_sha256(stack: Stack) -> Stack {
assert!(!stack.is_null(), "crypto.pbkdf2-sha256: stack is null");
let (stack, iterations_val) = unsafe { pop(stack) };
let (stack, salt_val) = unsafe { pop(stack) };
let (stack, password_val) = unsafe { pop(stack) };
match (password_val, salt_val, iterations_val) {
(Value::String(password), Value::String(salt), Value::Int(iterations)) => {
if iterations < MIN_PBKDF2_ITERATIONS {
let stack = unsafe { push(stack, Value::String(global_string(String::new()))) };
return unsafe { push(stack, Value::Bool(false)) };
}
let key = derive_key_pbkdf2(password.as_str(), salt.as_str(), iterations as u32);
let key_hex = hex::encode(key);
let stack = unsafe { push(stack, Value::String(global_string(key_hex))) };
unsafe { push(stack, Value::Bool(true)) }
}
_ => panic!("crypto.pbkdf2-sha256: expected String, String, Int on stack"),
}
}
pub(super) fn derive_key_pbkdf2(password: &str, salt: &str, iterations: u32) -> [u8; AES_KEY_SIZE] {
let mut key = [0u8; AES_KEY_SIZE];
pbkdf2::pbkdf2_hmac::<Sha256>(password.as_bytes(), salt.as_bytes(), iterations, &mut key);
key
}