Finish challenge 25 and update License

main
Felix Martin 2022-08-14 12:01:51 -04:00
parent 5158c16d56
commit 1eb76f52b1
7 changed files with 75 additions and 33 deletions

28
LICENSE
View File

@ -1,11 +1,25 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
GLWT(Good Luck With That) Public License
Copyright (c) Everyone, except Author
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy, distribute, modify, merge, sell, publish,
sublicense or whatever they want with this software but at their OWN RISK.
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
Preamble
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
The author has absolutely no clue what the code in this project does.
It might just work or not, there is no third option.
0. You just DO WHAT THE FUCK YOU WANT TO.
GOOD LUCK WITH THAT PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION, AND MODIFICATION
0. You just DO WHATEVER YOU WANT TO as long as you NEVER LEAVE A
TRACE TO TRACK THE AUTHOR of the original product to blame for or hold
responsible.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Good luck and Godspeed.

View File

@ -148,11 +148,7 @@ impl Bytes {
}
pub fn xor(Bytes(a): &Bytes, Bytes(b): &Bytes) -> Bytes {
Bytes(
Iterator::zip(a.iter(), b.iter())
.map(|z| *(z.0) ^ *(z.1))
.collect(),
)
Bytes(crate::utils::xor(a, b))
}
pub fn xor_byte(Bytes(a): &Bytes, byte: u8) -> Bytes {

View File

@ -1,12 +1,6 @@
use crate::bytes::Bytes;
use openssl::symm;
fn xor(a: &[u8], b: &[u8]) -> Vec<u8> {
Iterator::zip(a.iter(), b.iter())
.map(|z| *(z.0) ^ *(z.1))
.collect()
}
pub fn enrypt_aes_128_ecb_block(key: &[u8], data: &[u8]) -> Vec<u8> {
let cipher_type = symm::Cipher::aes_128_ecb();
let block_size = cipher_type.block_size();
@ -35,7 +29,7 @@ pub fn encrypt(Bytes(key): &Bytes, Bytes(iv): &Bytes, Bytes(data): &Bytes) -> By
let mut result: Vec<u8> = vec![];
let mut prev_cipher: Vec<u8> = iv.to_vec(); // first xor input is IV
for data in data.chunks(block_size) {
let xored = xor(&prev_cipher, data);
let xored = crate::utils::xor(&prev_cipher, data);
let mut cipher = enrypt_aes_128_ecb_block(key, &xored);
prev_cipher = cipher.to_vec(); // cipher is input for next xor
result.append(&mut cipher);
@ -51,7 +45,7 @@ pub fn decrypt(Bytes(key): &Bytes, Bytes(iv): &Bytes, Bytes(data): &Bytes) -> By
let mut prev_cipher: Vec<u8> = iv.to_vec(); // first xor input is IV
for cipher in data.chunks(block_size) {
let xored = decrypt_aes_128_ecb_block(key, &cipher);
let data = xor(&xored, &prev_cipher);
let data = crate::utils::xor(&xored, &prev_cipher);
result.extend(data.to_vec());
prev_cipher = cipher.to_vec();
}

View File

@ -1,13 +1,6 @@
use crate::bytes::Bytes;
use crate::cbc;
use openssl::symm;
fn xor(a: &Vec<u8>, b: &Vec<u8>) -> Vec<u8> {
Iterator::zip(a.iter(), b.iter())
.map(|z| *(z.0) ^ *(z.1))
.collect()
}
pub fn encrypt(key: &Bytes, nonce: u64, data: &Bytes) -> Bytes {
decrypt(key, nonce, data)
}
@ -20,8 +13,8 @@ pub fn decrypt(Bytes(key): &Bytes, nonce: u64, Bytes(data): &Bytes) -> Bytes {
for cipher in data.chunks(block_size) {
let mut keyinput = nonce.to_le_bytes().to_vec();
keyinput.append(&mut counter.to_le_bytes().to_vec());
let keystream = cbc::enrypt_aes_128_ecb_block(key, &keyinput);
let mut data = xor(&keystream, &cipher.to_vec());
let keystream = crate::cbc::enrypt_aes_128_ecb_block(key, &keyinput);
let mut data = crate::utils::xor(&keystream, &cipher.to_vec());
result.append(&mut data);
counter += 1;
}

View File

@ -40,7 +40,8 @@ fn main() {
set3::challenge23();
set3::challenge24();
set4::challenge25();
set4::challenge26();
} else {
set4::challenge25();
set4::challenge26();
}
}

View File

@ -1,9 +1,47 @@
use crate::{bytes::Bytes, utils};
use crate::{bytes::Bytes, ctr, utils};
pub fn challenge25() {
let cipher = utils::read_base64("data/25.txt");
let key = Bytes::from_utf8("YELLOW SUBMARINE");
let _cleartext = crate::ecb::decrypt(&key, &cipher);
let plaintext = crate::ecb::decrypt(&key, &cipher);
println!("[xxxx] Challenge 25: wip");
let key = Bytes::random(16);
let nonce: u64 = 0; // otherwise edit would require the nonce too?
// Now, write the code that allows you to "seek" into the ciphertext,
// decrypt, and re-encrypt with different plaintext. Expose this as a
// function, like, "edit(ciphertext, key, offset, newtext)".
fn edit(ciphertext: &Bytes, key: &Bytes, offset: usize, newtext: &Vec<u8>) -> Bytes {
let mut plaintext = ctr::decrypt(key, 0, ciphertext);
if offset + newtext.len() > plaintext.len() {
panic!("challenge25 - edit - out of bounds");
}
for i in 0..newtext.len() {
plaintext.0[offset + i] = newtext[i];
}
ctr::encrypt(key, 0, &plaintext)
}
// Imagine the "edit" function was exposed to attackers by means of an API
// call that didn't reveal the key or the original plaintext; the attacker
// has the ciphertext and controls the offset and "new text". Recover the
// original plaintext.
let ciphertext = ctr::encrypt(&key, nonce, &plaintext);
let newtext = vec![b'a'; ciphertext.len()];
let cipher_newtext = edit(&ciphertext, &key, 0, &newtext);
let keystream = crate::utils::xor(&newtext, &cipher_newtext.0);
let recovered_plaintext = Bytes(crate::utils::xor(&keystream, &ciphertext.0));
assert_eq!(plaintext, recovered_plaintext);
println!("[okay] Challenge 25: recovered AES CTR plaintext via edit");
// A folkloric supposed benefit of CTR mode is the ability to easily "seek
// forward" into the ciphertext; to access byte N of the ciphertext, all you
// need to be able to do is generate byte N of the keystream. Imagine if
// you'd relied on that advice to, say, encrypt a disk.
}
pub fn challenge26() {
println!("[xxxx] Challenge 26: TBD");
}

View File

@ -39,3 +39,9 @@ pub fn read_hex_lines(path: &str) -> Vec<Bytes> {
.map(|line| Bytes::from_hex(&line.unwrap()))
.collect()
}
pub fn xor(a: &[u8], b: &[u8]) -> Vec<u8> {
Iterator::zip(a.iter(), b.iter())
.map(|z| *(z.0) ^ *(z.1))
.collect()
}