From b3ce1dfaef6b549115017ef2f637f7813a2bd6e4 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Mon, 8 Sep 2025 17:25:30 +0800 Subject: [PATCH] feat: finish p16 --- cryptopal_book/src/challenge_16.md | 2 +- problems/p16/Cargo.toml | 2 ++ problems/p16/src/main.rs | 49 ++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/cryptopal_book/src/challenge_16.md b/cryptopal_book/src/challenge_16.md index 6571f74..9cc80f9 100644 --- a/cryptopal_book/src/challenge_16.md +++ b/cryptopal_book/src/challenge_16.md @@ -26,7 +26,7 @@ 如果你正确编写了第一个函数,应该*不*可能向其提供会生成第二个函数正在寻找的字符串的用户输入。我们必须破解密码才能做到这一点。 -相反,修改密文(不知道AES密钥)来完成这个目标。 +相反,修改**密文**(不知道AES密钥)来完成这个目标。 你依赖的事实是,在CBC模式中,密文块中的1位错误: diff --git a/problems/p16/Cargo.toml b/problems/p16/Cargo.toml index ed22fc5..b195a35 100644 --- a/problems/p16/Cargo.toml +++ b/problems/p16/Cargo.toml @@ -4,3 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +common = { path = "../../common/" } +rand = { workspace = true } diff --git a/problems/p16/src/main.rs b/problems/p16/src/main.rs index e7a11a9..313f442 100644 --- a/problems/p16/src/main.rs +++ b/problems/p16/src/main.rs @@ -1,3 +1,48 @@ -fn main() { - println!("Hello, world!"); +use common::{aes_cbc_dec, aes_cbc_enc, pkcs7_padding, pkcs7_unpadding}; +use rand::{Rng, rng}; +fn append_and_enc(input: String, key: &[u8; 16]) -> Vec { + let input = input.replace(";", "\\;").replace("=", "\\="); + let prefix = "comment1=cooking%20MCs;userdata=".to_string(); + let suffix = ";comment2=%20like%20a%20pound%20of%20bacon"; + // println!("{}, {}", prefix.len(), suffix.len()); // 32, 42 + + let mut buffer = prefix + &input + suffix; + let input = unsafe { buffer.as_mut_vec() }; + pkcs7_padding(input, 16); + + let iv = [0u8; 16]; + + aes_cbc_enc(input, key, &iv).unwrap() +} + +fn verify(cipher: &[u8], key: &[u8; 16]) -> bool { + let iv = [0u8; 16]; + let plaintext = aes_cbc_dec(cipher, key, &iv).unwrap(); + let plaintext = pkcs7_unpadding(&plaintext).unwrap(); + let plaintext = String::from_utf8_lossy(&plaintext); + println!("{}", plaintext); + plaintext.contains(";admin=true;") +} + +fn main() { + let mut rng = rng(); + let key: [u8; 16] = rng.random(); + + // 构造输入,第一个块用于反转破坏 + let input = "A".repeat(16) + &"A".repeat(5) + "XadminXtrue"; + let mut cipher = append_and_enc(input, &key); + + // 计算目标位置:prefix(32) + padding(16) + target_start = 48 + 1 = 49 + // 目标在第4块,需要修改第3块 + let block_to_modify = 2 * 16; // 第3块起始位置 + + // 修改密文来翻转目标位 + cipher[block_to_modify + 5] ^= b'X' ^ b';'; // X -> ; + cipher[block_to_modify + 11] ^= b'X' ^ b'='; // X -> = + + if verify(&cipher, &key) { + println!("Attack successful!"); + } else { + println!("Attack failed"); + } }