use crate::{CryptoError, Result};
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> [u8; 32] {
let mut mac = HmacSha256::new_from_slice(key).expect("HMAC accepts any key length");
mac.update(msg);
mac.finalize().into_bytes().into()
}
pub fn pbkdf2_sha1(password: &[u8], salt: &[u8], rounds: u32, out_len: usize) -> Vec<u8> {
let mut out = vec![0u8; out_len];
pbkdf2::pbkdf2_hmac::<sha1::Sha1>(password, salt, rounds, &mut out);
out
}
pub fn pkcs7_unpad(data: &[u8], block: usize) -> Result<Vec<u8>> {
let n = *data.last().ok_or(CryptoError::BadPadding)? as usize;
if n == 0 || n > block || n > data.len() {
return Err(CryptoError::BadPadding);
}
if data[data.len() - n..].iter().any(|&b| b as usize != n) {
return Err(CryptoError::BadPadding);
}
Ok(data[..data.len() - n].to_vec())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pkcs7_strips() {
let padded = b"hello\x03\x03\x03";
assert_eq!(pkcs7_unpad(padded, 8).unwrap(), b"hello");
}
#[test]
fn pkcs7_rejects_bad() {
assert!(pkcs7_unpad(b"hello\x03\x02\x03", 8).is_err());
}
}