acid/firmware2/password-hash/src/bin.rs
2026-01-20 02:55:17 +01:00

58 lines
1.5 KiB
Rust

#![feature(allocator_api)]
use std::{
alloc::Global,
ffi::CString,
io::{Write, stdin},
iter::zip,
str::FromStr,
};
use itertools::Itertools;
use password_hash::derive_encryption_key;
use spectre_api_sys::SpectreAlgorithm;
macro_rules! read_line {
($lines:expr, $label:expr) => {{
print!("{}: ", $label);
std::io::stdout().flush().unwrap();
CString::from_str(
&$lines
.next()
.transpose()
.ok()
.flatten()
.unwrap_or_else(|| panic!("Expected {}.", $label)),
)
.unwrap()
}};
}
fn main() {
let mut lines = stdin().lines();
let username = read_line!(lines, "username");
let secret = read_line!(lines, "secret");
let user_key = unsafe {
&*spectre_api_sys::spectre_user_key(
username.as_ptr(),
secret.as_ptr(),
SpectreAlgorithm::Current,
)
};
let salt = username.as_bytes(); // TODO: Derive the same salt that spectre passes to scrypt.
let encryption_key = derive_encryption_key(salt, secret.as_bytes(), Global);
let mut encrypted_user_key = encryption_key;
assert_eq!(encrypted_user_key.len(), user_key.bytes.len());
for (dst_byte, user_byte) in zip(&mut encrypted_user_key, &user_key.bytes) {
*dst_byte ^= *user_byte;
}
println!(
"\nEncrypted User Key:\n{:02x}",
encrypted_user_key.iter().format("")
);
}