58 lines
1.5 KiB
Rust
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("")
|
|
);
|
|
}
|