From f0af2c1b75c366b228925a8b88cf3bf19066dc41 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 27 Mar 2015 00:16:51 -0400 Subject: make the decrypt primitives return options based on valid padding --- src/aes.rs | 18 ++++++++++-------- tests/lib.rs | 8 ++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/aes.rs b/src/aes.rs index 05922e7..a4b5059 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -12,21 +12,23 @@ pub enum BlockCipherMode { CBC, } -pub fn decrypt_aes_128_ecb (bytes: &[u8], key: &[u8]) -> Vec { - return openssl::crypto::symm::decrypt( +pub fn decrypt_aes_128_ecb (bytes: &[u8], key: &[u8]) -> Option> { + // openssl already doesn't return differentiable results for invalid + // padding, so we can't either + return Some(openssl::crypto::symm::decrypt( openssl::crypto::symm::Type::AES_128_ECB, key, vec![], bytes - ) + )); } -pub fn decrypt_aes_128_cbc (bytes: &[u8], key: &[u8], iv: &[u8]) -> Vec { +pub fn decrypt_aes_128_cbc (bytes: &[u8], key: &[u8], iv: &[u8]) -> Option> { let mut prev = iv.clone(); let mut plaintext = vec![]; for block in bytes.chunks(16) { let plaintext_block = fixed_xor( - &decrypt_aes_128_ecb(&pad_pkcs7(block, 16)[..], key)[..], + &decrypt_aes_128_ecb(&pad_pkcs7(block, 16)[..], key).unwrap()[..], prev ); for c in plaintext_block { @@ -34,7 +36,7 @@ pub fn decrypt_aes_128_cbc (bytes: &[u8], key: &[u8], iv: &[u8]) -> Vec { } prev = block.clone(); } - return unpad_pkcs7(&plaintext[..]).expect("invalid padding").to_vec(); + return unpad_pkcs7(&plaintext[..]).map(|v| v.to_vec()); } pub fn encrypt_aes_128_ecb (bytes: &[u8], key: &[u8]) -> Vec { @@ -318,8 +320,8 @@ fn test_encrypt_decrypt () { let ciphertext_ecb = encrypt_aes_128_ecb(&plaintext[..], &key[..]); let ciphertext_cbc = encrypt_aes_128_cbc(&plaintext[..], &key[..], &iv[..]); - let plaintext2_ecb = decrypt_aes_128_ecb(&ciphertext_ecb[..], &key[..]); - let plaintext2_cbc = decrypt_aes_128_cbc(&ciphertext_cbc[..], &key[..], &iv[..]); + let plaintext2_ecb = decrypt_aes_128_ecb(&ciphertext_ecb[..], &key[..]).unwrap(); + let plaintext2_cbc = decrypt_aes_128_cbc(&ciphertext_cbc[..], &key[..], &iv[..]).unwrap(); let ciphertext2_ecb = encrypt_aes_128_ecb(&plaintext2_ecb[..], &key[..]); let ciphertext2_cbc = encrypt_aes_128_cbc(&plaintext2_cbc[..], &key[..], &iv[..]); diff --git a/tests/lib.rs b/tests/lib.rs index cc37ec4..3dbfa55 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -107,7 +107,7 @@ fn problem_7 () { let key = b"YELLOW SUBMARINE"; let plaintext = read("data/7.out.txt"); let got = matasano::decrypt_aes_128_ecb(&ciphertext[..], key); - assert_eq!(got, plaintext); + assert_eq!(got, Some(plaintext)); } #[test] @@ -139,7 +139,7 @@ fn problem_10 () { let key = b"YELLOW SUBMARINE"; let plaintext = read("data/10.out.txt"); let got = matasano::decrypt_aes_128_cbc(&ciphertext[..], key, &[0; 16]); - assert_eq!(got, plaintext); + assert_eq!(got, Some(plaintext)); } #[test] @@ -228,7 +228,7 @@ fn problem_13 () { matasano::encrypt_aes_128_ecb(profile_for(email).as_bytes(), &key[..]) }; let decrypter = |ciphertext: &[u8]| -> Option> { - let plaintext = matasano::decrypt_aes_128_ecb(ciphertext, &key[..]); + let plaintext = matasano::decrypt_aes_128_ecb(ciphertext, &key[..]).unwrap(); let plaintext_str = std::str::from_utf8(&plaintext[..]).unwrap(); if let Some(params) = matasano::parse_query_string(plaintext_str) { return Some( @@ -327,7 +327,7 @@ fn problem_16 () { }; let verify = |ciphertext: &[u8]| -> bool { - let plaintext = matasano::decrypt_aes_128_cbc(ciphertext, &key[..], &iv[..]); + let plaintext = matasano::decrypt_aes_128_cbc(ciphertext, &key[..], &iv[..]).unwrap(); return (0..(plaintext.len() - admin.len())).any(|i| { plaintext .iter() -- cgit v1.2.3-54-g00ecf