use crate::error::InklogError;
use base64::{engine::general_purpose, Engine as _};
use pbkdf2::pbkdf2_hmac;
use sha2::Sha256;
use zeroize::Zeroizing;
pub fn get_encryption_key(env_var: &str) -> Result<[u8; 32], InklogError> {
let env_value = Zeroizing::new(std::env::var(env_var).map_err(|_| {
InklogError::ConfigError(
"Encryption key environment variable not set. Please configure INKLOG_ENCRYPTION_KEY."
.to_string(),
)
})?);
let raw_bytes = env_value.as_bytes();
if raw_bytes.len() == 32 {
let mut result = [0u8; 32];
result.copy_from_slice(raw_bytes);
return Ok(result);
}
if let Ok(decoded) = general_purpose::STANDARD.decode(env_value.as_str()) {
if decoded.len() == 32 {
let mut result = [0u8; 32];
result.copy_from_slice(&decoded);
return Ok(result);
}
return Err(InklogError::ConfigError(format!(
"Encryption key from Base64 must be exactly 32 bytes (256 bits), got {} bytes. \
Please provide a valid 32-byte key encoded in Base64.",
decoded.len()
)));
}
if !raw_bytes.is_empty() && raw_bytes.len() < 128 {
return derive_key_from_password(env_value.as_str());
}
Err(InklogError::ConfigError(format!(
"Encryption key must be exactly 32 bytes (256 bits) for raw keys, or a password string (1-127 chars) for key derivation. Got {} bytes. \
Please provide a valid 32-byte key in raw or Base64 format, or use a password string.",
raw_bytes.len()
)))
}
pub fn derive_key_from_password(password: &str) -> Result<[u8; 32], InklogError> {
let mut key = [0u8; 32];
let salt = b"inklog-encryption-salt-v1";
pbkdf2_hmac::<Sha256>(
password.as_bytes(),
salt,
100_000, &mut key,
);
Ok(key)
}