working
This commit is contained in:
9
rust/Cargo.toml
Normal file
9
rust/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "rust"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rayon = "1.5"
|
||||
sha2 = "0.10"
|
||||
|
||||
30
rust/confession_fake.txt
Normal file
30
rust/confession_fake.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
This is the secret confession of Richard Buckland
|
||||
to be revealed by anonymous email if I should
|
||||
mysteriously vanish. I have left the last few hex
|
||||
digits of the SHA256 hash of this message with my
|
||||
trusted solicitor, Dennis Denuto, which will verify
|
||||
that this is indeed my intended and unaltered
|
||||
confession written by me Richard Buckland.
|
||||
|
||||
Dennis has not seen this confession he has only seen
|
||||
the last few digits of the hash. I have also sent copies
|
||||
of the last few digits to my bank manager and to my priest
|
||||
Father Brown.
|
||||
|
||||
On the 10th of February I saw Mark Zukerberg near my
|
||||
house and we struck up a conversation. He explained all
|
||||
the things he was doing to ensure that Facebook respects
|
||||
privacy - both of its users and of others. It was very
|
||||
impressive.
|
||||
|
||||
I feel awful that I have been criticising Facebook publicly
|
||||
for so long. I apologised to him in our conversation and
|
||||
now I want to confess to the world that actually Facebook
|
||||
has more than enough privacy features, and that the reason
|
||||
I spend so much time criticising Facebook is that I am
|
||||
envious of Mark and wish I was a clever and smart and wise
|
||||
as he is. I feel so bad for having been so mean to him for
|
||||
so many years that I am considering retreating to the outback.
|
||||
I may well cut off all contact with the world and live as a
|
||||
hermit from now on. So do not worry if I vanish it is just
|
||||
that I feel so guilty that I have been so unfair to Facebook.
|
||||
22
rust/confession_real.txt
Normal file
22
rust/confession_real.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
This is the secret confession of Richard Buckland
|
||||
to be revealed by anonymous email if I should
|
||||
mysteriously vanish. I have left the last few hex
|
||||
digits of the SHA256 hash of this message with my
|
||||
trusted solicitor, Dennis Denuto, which will verify
|
||||
that this is indeed my intended and unaltered
|
||||
confession written by me Richard Buckland.
|
||||
|
||||
Dennis has not seen this confession he has only seen
|
||||
the last few digits of the hash. I have also sent copies
|
||||
of the last few digits to my bank manager and to my priest
|
||||
Father Brown.
|
||||
|
||||
On the 10th of February I saw Mark Zukerberg peeping
|
||||
through my window and recording my private and personal
|
||||
conversation with my friend.
|
||||
|
||||
I confronted him and he was very embarrassed. He
|
||||
promised to pay me $1 million a year if I would stay
|
||||
silent and not tell anyone I had seen him do this. I
|
||||
agreed but now I worry that it would be cheaper for him
|
||||
to make me vanish than to keep paying me.
|
||||
124
rust/src/main.rs
Normal file
124
rust/src/main.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
use rayon::prelude::*;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::time::Instant;
|
||||
use std::env;
|
||||
|
||||
// Function to calculate the hash for the given file content
|
||||
fn calculate_hash(file_lines: &[String], num_chars: usize) -> String {
|
||||
let content = file_lines.join(""); // Join lines with no separator (newlines are preserved)
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(content.as_bytes());
|
||||
let result = hasher.finalize();
|
||||
format!("{:x}", result)[64 - num_chars..].to_string() // Get the last `num_chars` hex digits
|
||||
}
|
||||
|
||||
// Function to generate a modified fake file by adding spaces based on the bit pattern
|
||||
fn modify_and_hash(
|
||||
fake_og: &[String],
|
||||
num_chars: usize,
|
||||
bit_pattern: u64,
|
||||
real_hash: &str,
|
||||
) -> Option<Vec<String>> {
|
||||
let fake_modified: Vec<String> = fake_og
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, line)| {
|
||||
let trimmed_line = line.trim_end(); // Remove trailing whitespace
|
||||
let spaces_to_add = if (bit_pattern >> idx) & 1 == 1 { " " } else { "" };
|
||||
format!("{}{}\n", trimmed_line, spaces_to_add)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Calculate the hash for the modified fake file
|
||||
let fake_hash = calculate_hash(&fake_modified, num_chars);
|
||||
|
||||
// Return the modified file if the hash matches
|
||||
if fake_hash == real_hash {
|
||||
Some(fake_modified)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Get command line arguments
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 4 {
|
||||
eprintln!("Usage: {} <real_file> <fake_file> <num_chars>", args[0]);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let real_file = &args[1];
|
||||
let fake_file = &args[2];
|
||||
let num_chars: usize = args[3].parse().expect("Invalid number of characters");
|
||||
|
||||
// Read the real and fake files
|
||||
let real_og: Vec<String> = fs::read_to_string(real_file)
|
||||
.expect("Failed to read real file")
|
||||
.lines()
|
||||
.map(|line| format!("{}\n", line)) // Preserve newlines
|
||||
.collect();
|
||||
|
||||
let fake_og: Vec<String> = fs::read_to_string(fake_file)
|
||||
.expect("Failed to read fake file")
|
||||
.lines()
|
||||
.map(|line| format!("{}\n", line)) // Preserve newlines
|
||||
.collect();
|
||||
|
||||
// Calculate the hash of the real file (unmodified)
|
||||
let real_hash = calculate_hash(&real_og, num_chars);
|
||||
println!("Real file hash: {}", real_hash);
|
||||
|
||||
let mut found_collision = false;
|
||||
let mut hash_counter = 0;
|
||||
let start_time = Instant::now(); // Start the timer
|
||||
|
||||
// Search for a matching hash in parallel
|
||||
while !found_collision {
|
||||
// Generate a batch of bit patterns
|
||||
let batch_size = 100;
|
||||
let bit_patterns: Vec<u64> = (hash_counter..hash_counter + batch_size as u64).collect();
|
||||
|
||||
// Process the batch in parallel
|
||||
let results: Vec<Option<Vec<String>>> = bit_patterns
|
||||
.par_iter()
|
||||
.map(|&pattern| modify_and_hash(&fake_og, num_chars, pattern, &real_hash))
|
||||
.collect();
|
||||
|
||||
// Check if a collision was found
|
||||
for result in results {
|
||||
if let Some(fake_modified) = result {
|
||||
let elapsed_time = start_time.elapsed();
|
||||
println!(
|
||||
"\nCollision found! The fake file's hash matches the real file's hash: {}",
|
||||
real_hash
|
||||
);
|
||||
println!(
|
||||
"Total hashes processed: {} in {:.2?} seconds.",
|
||||
hash_counter, elapsed_time
|
||||
);
|
||||
|
||||
// Write the modified fake file to the output
|
||||
let out_file = format!("{}.out", fake_file);
|
||||
let mut file = fs::File::create(out_file).expect("Failed to create output file");
|
||||
for line in fake_modified {
|
||||
file.write_all(line.as_bytes()).expect("Failed to write to file");
|
||||
}
|
||||
|
||||
found_collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the hash counter
|
||||
hash_counter += batch_size;
|
||||
let elapsed_time = start_time.elapsed();
|
||||
print!(
|
||||
"\rProcessed {} hashes in {:.2?} seconds.",
|
||||
hash_counter, elapsed_time
|
||||
);
|
||||
std::io::stdout().flush().unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user