Improve and generalize sha256 handling
This commit is contained in:
parent
5650e731c5
commit
aa9ec80ece
|
@ -1,20 +1,48 @@
|
|||
use clap::{Parser, arg};
|
||||
use rust_brainwallet_search::brainwallet_single_sha256_check_btc;
|
||||
use rust_brainwallet_search::brainwallet_sha256_check_btc;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Opts {
|
||||
#[arg(short, long, help = "Input file with newline-separated text snippet candidates")]
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Input file with newline-separated text snippet candidates"
|
||||
)]
|
||||
input_file: String,
|
||||
|
||||
#[arg(short, long, help = "Output file in CSV format with information on matches")]
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Output file in CSV format with information on matches"
|
||||
)]
|
||||
output_file: String,
|
||||
|
||||
#[arg(long, help = "BTC Bloom filter file with known addresses")]
|
||||
bloom_file: String,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "How many times to use the hashing function",
|
||||
default_value_t = 1
|
||||
)]
|
||||
hashing_rounds: usize,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "How many times to repeat the input during hashing",
|
||||
default_value_t = 1
|
||||
)]
|
||||
hasher_input_repetition_count: usize,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opts: Opts = Opts::parse();
|
||||
brainwallet_single_sha256_check_btc(&opts.input_file, &opts.output_file, &opts.bloom_file);
|
||||
brainwallet_sha256_check_btc(
|
||||
&opts.input_file,
|
||||
&opts.output_file,
|
||||
&opts.bloom_file,
|
||||
opts.hashing_rounds,
|
||||
opts.hasher_input_repetition_count,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -43,17 +43,16 @@ impl Counter {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_bloom_and_record_hits(
|
||||
pub fn check_brainwallet_bloom_and_record_hits(
|
||||
bloom: &Bloom<String>,
|
||||
query: String,
|
||||
writer: &Mutex<csv::Writer<std::fs::File>>,
|
||||
source_id: String,
|
||||
source_id2: String,
|
||||
hashing_rounds: String,
|
||||
compressed_status: String,
|
||||
prng_index: String,
|
||||
prng_round_offset: String,
|
||||
bit_length: String,
|
||||
path: String,
|
||||
passphrase: String,
|
||||
print_hit: bool,
|
||||
) {
|
||||
if bloom.check(&query) {
|
||||
|
@ -67,11 +66,10 @@ pub fn check_bloom_and_record_hits(
|
|||
wtr.write_record([
|
||||
source_id,
|
||||
source_id2,
|
||||
hashing_rounds,
|
||||
compressed_status,
|
||||
bit_length,
|
||||
prng_index,
|
||||
prng_round_offset,
|
||||
path,
|
||||
passphrase,
|
||||
query,
|
||||
])
|
||||
.unwrap();
|
||||
|
@ -79,33 +77,41 @@ pub fn check_bloom_and_record_hits(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn brainwallet_single_sha256_check_btc(
|
||||
pub fn brainwallet_sha256_check_btc(
|
||||
input_file: &String,
|
||||
output_file: &String,
|
||||
btc_bloom: &String,
|
||||
hashing_rounds: usize,
|
||||
hasher_repetition_count: usize,
|
||||
) {
|
||||
|
||||
if hashing_rounds == 0 {
|
||||
panic!("Invalid number of hashing rounds");
|
||||
}
|
||||
let file = File::open(input_file).unwrap();
|
||||
let wtr = Mutex::new(csv::Writer::from_path(output_file).unwrap());
|
||||
|
||||
println!("Loading bloom filter dump ...");
|
||||
let bloom = address_filter::bloom::load(std::path::Path::new(&btc_bloom.to_string()))
|
||||
.expect("Couldn't load bloom filter dump");
|
||||
println!("... done.");
|
||||
|
||||
let wtr = Mutex::new(csv::Writer::from_path(output_file).unwrap());
|
||||
|
||||
// log every 2^16 lines
|
||||
let c = Counter::new(0b0000_1111_1111_1111_1111);
|
||||
|
||||
let secp = secp_engine();
|
||||
let bitcoin_mainnet_constant = bitcoin::network::Network::Bitcoin;
|
||||
|
||||
let file = File::open(input_file).unwrap();
|
||||
// minor performance tuning: use larger buffer size then default 8KiB
|
||||
const BUF_READER_CAPACITY: usize = 1_048_576; // 1MiB
|
||||
|
||||
// TODO this intentionally aborts hard on any problematic line
|
||||
// replace with a more robust handling
|
||||
let passphrases: Vec<String> = BufReader::new(file)
|
||||
// silently drop any problematic lines
|
||||
// TODO replace with a mode that flags problematic inputs and keeps statistics on them
|
||||
let passphrases: Vec<String> = BufReader::with_capacity(BUF_READER_CAPACITY, file)
|
||||
.lines()
|
||||
.map(|l| l.expect("Could not parse line"))
|
||||
.filter_map(|l| l.ok())
|
||||
.collect();
|
||||
let source_id = "brainwallet-single-sha256-direct";
|
||||
let source_id = "brainwallet-sha256";
|
||||
|
||||
passphrases.par_iter().for_each(|passphrase| {
|
||||
// Count lines and print progress
|
||||
|
@ -120,9 +126,22 @@ pub fn brainwallet_single_sha256_check_btc(
|
|||
// contains those.
|
||||
//
|
||||
// TODO consider a different data conversion approach
|
||||
hasher.update(passphrase.clone());
|
||||
//
|
||||
// Optionally hash the data multiple times, which concatenates the output N times
|
||||
for _i in 0..hasher_repetition_count {
|
||||
hasher.update(passphrase.clone());
|
||||
}
|
||||
// read hash digest and consume hasher
|
||||
let entropy = hasher.finalize();
|
||||
let mut intermediary = hasher.finalize();
|
||||
|
||||
// if we're asked to do more than one hashing round, repeat the hashing
|
||||
// this is inefficient and designed for a low number of rounds
|
||||
for _i in 1..hashing_rounds {
|
||||
intermediary = Sha256::digest(intermediary);
|
||||
}
|
||||
|
||||
// read hash digest and consume hasher
|
||||
let entropy = intermediary;
|
||||
|
||||
let secret_key = bitcoin::secp256k1::SecretKey::from_slice(&entropy[..]).unwrap();
|
||||
|
||||
|
@ -149,15 +168,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
|||
let address_from_compressed_pubkey =
|
||||
Address::p2pkh(&pubkey_compressed, bitcoin_mainnet_constant).to_string();
|
||||
|
||||
check_bloom_and_record_hits(
|
||||
check_brainwallet_bloom_and_record_hits(
|
||||
&bloom,
|
||||
address_from_compressed_pubkey.to_string(),
|
||||
&wtr,
|
||||
source_id.to_string(),
|
||||
"direct".to_string(),
|
||||
hashing_rounds.to_string(),
|
||||
"compressed".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"256".to_string(),
|
||||
passphrase.to_string(),
|
||||
true,
|
||||
|
@ -167,15 +185,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
|||
let address_from_uncompressed_pubkey =
|
||||
Address::p2pkh(&pubkey_uncompressed, bitcoin_mainnet_constant).to_string();
|
||||
|
||||
check_bloom_and_record_hits(
|
||||
check_brainwallet_bloom_and_record_hits(
|
||||
&bloom,
|
||||
address_from_uncompressed_pubkey.to_string(),
|
||||
&wtr,
|
||||
source_id.to_string(),
|
||||
"direct".to_string(),
|
||||
hashing_rounds.to_string(),
|
||||
"uncompressed".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"256".to_string(),
|
||||
passphrase.to_string(),
|
||||
true,
|
||||
|
@ -187,15 +204,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
|||
bitcoin::network::Network::Bitcoin,
|
||||
)
|
||||
.to_string();
|
||||
check_bloom_and_record_hits(
|
||||
check_brainwallet_bloom_and_record_hits(
|
||||
&bloom,
|
||||
address.to_string(),
|
||||
&wtr,
|
||||
source_id.to_string(),
|
||||
"direct".to_string(),
|
||||
hashing_rounds.to_string(),
|
||||
"compressed".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"256".to_string(),
|
||||
passphrase.to_string(),
|
||||
true,
|
||||
|
@ -207,15 +223,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
|||
bitcoin::network::Network::Bitcoin,
|
||||
)
|
||||
.to_string();
|
||||
check_bloom_and_record_hits(
|
||||
check_brainwallet_bloom_and_record_hits(
|
||||
&bloom,
|
||||
address.to_string(),
|
||||
&wtr,
|
||||
source_id.to_string(),
|
||||
"direct".to_string(),
|
||||
hashing_rounds.to_string(),
|
||||
"compressed".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"256".to_string(),
|
||||
passphrase.to_string(),
|
||||
true,
|
||||
|
|
Loading…
Reference in New Issue