@@ 0,0 1,16 @@
+use std::error::Error;
+
+use cryptopals::aes::pkcs7_validation;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ println!(
+ "{}",
+ String::from_utf8(
+ pkcs7_validation(b"ICE ICE BABY\x04\x04\x04\x04".to_vec(), 16)
+ .expect("valid padding detected as invalid")
+ )
+ .unwrap()
+ );
+
+ Ok(())
+}
@@ 86,8 86,8 @@ pub fn cbc_decrypt(ciphertext: Vec<u8>, key: Vec<u8>, iv: Vec<u8>) -> Vec<u8> {
plaintext
}
-pub fn pkcs7(bytes: Vec<u8>, blocksize: u32) -> Vec<u8> {
- let padding_size = blocksize - (bytes.len() as u32 % blocksize);
+pub fn pkcs7(bytes: Vec<u8>, block_size: usize) -> Vec<u8> {
+ let padding_size = block_size - (bytes.len() % block_size);
let mut padded = bytes;
for _ in 0..padding_size {
padded.push(padding_size as u8);
@@ 96,6 96,28 @@ pub fn pkcs7(bytes: Vec<u8>, blocksize: u32) -> Vec<u8> {
padded
}
+pub fn pkcs7_validation<'a>(bytes: Vec<u8>, block_size: usize) -> Result<Vec<u8>, &'a str> {
+ if bytes.len() % block_size != 0 {
+ return Err("invalid length");
+ }
+
+ let final_block = bytes[bytes.len() - block_size..].to_vec();
+ let final_byte = final_block[final_block.len() - 1];
+
+ if final_byte > 16 {
+ return Err("invalid padding");
+ }
+
+ let padding_start = block_size - (final_byte as usize);
+ let supposed_padding = final_block[padding_start..].to_vec();
+
+ if !supposed_padding.iter().all(|&x| x == final_byte) {
+ return Err("invalid padding");
+ }
+
+ Ok(bytes[..bytes.len() - block_size + padding_start].to_vec())
+}
+
pub fn random_key() -> Vec<u8> {
let mut key = vec![0; 16];
rand_bytes(&mut key).unwrap();
@@ 124,4 146,15 @@ mod tests {
assert_eq!(plaintext, decrypted);
}
+
+ #[test]
+ fn test_pkcs7_validation() {
+ assert_eq!(
+ pkcs7_validation(b"ICE ICE BABY\x04\x04\x04\x04".to_vec(), 16),
+ Ok(b"ICE ICE BABY".to_vec())
+ );
+
+ assert!(pkcs7_validation(b"ICE ICE BABY\x05\x05\x05\x05".to_vec(), 16).is_err());
+ assert!(pkcs7_validation(b"ICE ICE BABY\x01\x02\x03\x04".to_vec(), 16).is_err());
+ }
}