use crate::CoreError;
use base64::{engine::general_purpose, Engine as _};
use zeroize::Zeroizing;
fn xor(data: &[u8], name: &str) -> Result<Zeroizing<Vec<u8>>, CoreError> {
if name.is_empty() {
return Err(CoreError::Crypto("env var name must not be empty".into()));
}
Ok(Zeroizing::new(
data.iter()
.zip(name.bytes().cycle())
.map(|(byte, key)| byte ^ key)
.collect(),
))
}
pub fn encode_password_for_environment(name: &str, password: &str) -> Result<String, CoreError> {
Ok(general_purpose::STANDARD.encode(xor(password.as_bytes(), name)?.as_slice()))
}
pub fn decode_password_from_environment(name: &str, value: &str) -> Result<String, CoreError> {
if name.is_empty() {
return Err(CoreError::Crypto("env var name must not be empty".into()));
}
let value = value.trim();
let mut bytes = Zeroizing::new(Vec::with_capacity(base64::decoded_len_estimate(
value.len(),
)));
general_purpose::STANDARD
.decode_vec(value, &mut bytes)
.map_err(|_| CoreError::Keyfile("invalid base64 in wallet password env var".into()))?;
let decoded = xor(&bytes, name)?;
std::str::from_utf8(&decoded)
.map(str::to_owned)
.map_err(|_| CoreError::Keyfile("invalid wallet password env var: corrupt UTF-8".into()))
}