use age_core::secrecy::{ExposeSecret, SecretBox};
use hmac::{
digest::{CtOutput, MacError},
Hmac, Mac,
};
use scrypt::{errors::InvalidParams, scrypt as scrypt_inner, Params as ScryptParams};
use sha2::Sha256;
use std::io::{self, Write};
#[cfg(feature = "armor")]
#[cfg_attr(docsrs, doc(cfg(feature = "armor")))]
pub mod armor;
pub mod stream;
pub(crate) struct HmacKey(pub(crate) SecretBox<[u8; 32]>);
pub(crate) struct HmacWriter {
inner: Hmac<Sha256>,
}
impl HmacWriter {
pub(crate) fn new(key: HmacKey) -> Self {
HmacWriter {
inner: Hmac::new_from_slice(key.0.expose_secret()).expect("key is the correct length"),
}
}
pub(crate) fn finalize(self) -> CtOutput<Hmac<Sha256>> {
self.inner.finalize()
}
pub(crate) fn verify(self, mac: &[u8]) -> Result<(), MacError> {
self.inner.verify_slice(mac)
}
}
impl Write for HmacWriter {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.inner.update(data);
Ok(data.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
pub(crate) fn scrypt(salt: &[u8], log_n: u8, password: &str) -> Result<[u8; 32], InvalidParams> {
let params = ScryptParams::new(log_n, 8, 1, 32)?;
let mut output = [0; 32];
scrypt_inner(password.as_bytes(), salt, ¶ms, &mut output)
.expect("output is the correct length");
Ok(output)
}