Improve and generalize sha256 handling
This commit is contained in:
parent
5650e731c5
commit
aa9ec80ece
|
@ -1,20 +1,48 @@
|
||||||
use clap::{Parser, arg};
|
use clap::{Parser, arg};
|
||||||
use rust_brainwallet_search::brainwallet_single_sha256_check_btc;
|
use rust_brainwallet_search::brainwallet_sha256_check_btc;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
struct Opts {
|
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,
|
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,
|
output_file: String,
|
||||||
|
|
||||||
#[arg(long, help = "BTC Bloom filter file with known addresses")]
|
#[arg(long, help = "BTC Bloom filter file with known addresses")]
|
||||||
bloom_file: String,
|
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() {
|
fn main() {
|
||||||
let opts: Opts = Opts::parse();
|
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>,
|
bloom: &Bloom<String>,
|
||||||
query: String,
|
query: String,
|
||||||
writer: &Mutex<csv::Writer<std::fs::File>>,
|
writer: &Mutex<csv::Writer<std::fs::File>>,
|
||||||
source_id: String,
|
source_id: String,
|
||||||
source_id2: String,
|
source_id2: String,
|
||||||
|
hashing_rounds: String,
|
||||||
compressed_status: String,
|
compressed_status: String,
|
||||||
prng_index: String,
|
|
||||||
prng_round_offset: String,
|
|
||||||
bit_length: String,
|
bit_length: String,
|
||||||
path: String,
|
passphrase: String,
|
||||||
print_hit: bool,
|
print_hit: bool,
|
||||||
) {
|
) {
|
||||||
if bloom.check(&query) {
|
if bloom.check(&query) {
|
||||||
|
@ -67,11 +66,10 @@ pub fn check_bloom_and_record_hits(
|
||||||
wtr.write_record([
|
wtr.write_record([
|
||||||
source_id,
|
source_id,
|
||||||
source_id2,
|
source_id2,
|
||||||
|
hashing_rounds,
|
||||||
compressed_status,
|
compressed_status,
|
||||||
bit_length,
|
bit_length,
|
||||||
prng_index,
|
passphrase,
|
||||||
prng_round_offset,
|
|
||||||
path,
|
|
||||||
query,
|
query,
|
||||||
])
|
])
|
||||||
.unwrap();
|
.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,
|
input_file: &String,
|
||||||
output_file: &String,
|
output_file: &String,
|
||||||
btc_bloom: &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 ...");
|
println!("Loading bloom filter dump ...");
|
||||||
let bloom = address_filter::bloom::load(std::path::Path::new(&btc_bloom.to_string()))
|
let bloom = address_filter::bloom::load(std::path::Path::new(&btc_bloom.to_string()))
|
||||||
.expect("Couldn't load bloom filter dump");
|
.expect("Couldn't load bloom filter dump");
|
||||||
println!("... done.");
|
println!("... done.");
|
||||||
|
|
||||||
let wtr = Mutex::new(csv::Writer::from_path(output_file).unwrap());
|
|
||||||
|
|
||||||
// log every 2^16 lines
|
// log every 2^16 lines
|
||||||
let c = Counter::new(0b0000_1111_1111_1111_1111);
|
let c = Counter::new(0b0000_1111_1111_1111_1111);
|
||||||
|
|
||||||
let secp = secp_engine();
|
let secp = secp_engine();
|
||||||
let bitcoin_mainnet_constant = bitcoin::network::Network::Bitcoin;
|
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
|
// silently drop any problematic lines
|
||||||
// replace with a more robust handling
|
// TODO replace with a mode that flags problematic inputs and keeps statistics on them
|
||||||
let passphrases: Vec<String> = BufReader::new(file)
|
let passphrases: Vec<String> = BufReader::with_capacity(BUF_READER_CAPACITY, file)
|
||||||
.lines()
|
.lines()
|
||||||
.map(|l| l.expect("Could not parse line"))
|
.filter_map(|l| l.ok())
|
||||||
.collect();
|
.collect();
|
||||||
let source_id = "brainwallet-single-sha256-direct";
|
let source_id = "brainwallet-sha256";
|
||||||
|
|
||||||
passphrases.par_iter().for_each(|passphrase| {
|
passphrases.par_iter().for_each(|passphrase| {
|
||||||
// Count lines and print progress
|
// Count lines and print progress
|
||||||
|
@ -120,9 +126,22 @@ pub fn brainwallet_single_sha256_check_btc(
|
||||||
// contains those.
|
// contains those.
|
||||||
//
|
//
|
||||||
// TODO consider a different data conversion approach
|
// TODO consider a different data conversion approach
|
||||||
|
//
|
||||||
|
// Optionally hash the data multiple times, which concatenates the output N times
|
||||||
|
for _i in 0..hasher_repetition_count {
|
||||||
hasher.update(passphrase.clone());
|
hasher.update(passphrase.clone());
|
||||||
|
}
|
||||||
// read hash digest and consume hasher
|
// 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();
|
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 =
|
let address_from_compressed_pubkey =
|
||||||
Address::p2pkh(&pubkey_compressed, bitcoin_mainnet_constant).to_string();
|
Address::p2pkh(&pubkey_compressed, bitcoin_mainnet_constant).to_string();
|
||||||
|
|
||||||
check_bloom_and_record_hits(
|
check_brainwallet_bloom_and_record_hits(
|
||||||
&bloom,
|
&bloom,
|
||||||
address_from_compressed_pubkey.to_string(),
|
address_from_compressed_pubkey.to_string(),
|
||||||
&wtr,
|
&wtr,
|
||||||
source_id.to_string(),
|
source_id.to_string(),
|
||||||
"direct".to_string(),
|
"direct".to_string(),
|
||||||
|
hashing_rounds.to_string(),
|
||||||
"compressed".to_string(),
|
"compressed".to_string(),
|
||||||
"".to_string(),
|
|
||||||
"".to_string(),
|
|
||||||
"256".to_string(),
|
"256".to_string(),
|
||||||
passphrase.to_string(),
|
passphrase.to_string(),
|
||||||
true,
|
true,
|
||||||
|
@ -167,15 +185,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
||||||
let address_from_uncompressed_pubkey =
|
let address_from_uncompressed_pubkey =
|
||||||
Address::p2pkh(&pubkey_uncompressed, bitcoin_mainnet_constant).to_string();
|
Address::p2pkh(&pubkey_uncompressed, bitcoin_mainnet_constant).to_string();
|
||||||
|
|
||||||
check_bloom_and_record_hits(
|
check_brainwallet_bloom_and_record_hits(
|
||||||
&bloom,
|
&bloom,
|
||||||
address_from_uncompressed_pubkey.to_string(),
|
address_from_uncompressed_pubkey.to_string(),
|
||||||
&wtr,
|
&wtr,
|
||||||
source_id.to_string(),
|
source_id.to_string(),
|
||||||
"direct".to_string(),
|
"direct".to_string(),
|
||||||
|
hashing_rounds.to_string(),
|
||||||
"uncompressed".to_string(),
|
"uncompressed".to_string(),
|
||||||
"".to_string(),
|
|
||||||
"".to_string(),
|
|
||||||
"256".to_string(),
|
"256".to_string(),
|
||||||
passphrase.to_string(),
|
passphrase.to_string(),
|
||||||
true,
|
true,
|
||||||
|
@ -187,15 +204,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
||||||
bitcoin::network::Network::Bitcoin,
|
bitcoin::network::Network::Bitcoin,
|
||||||
)
|
)
|
||||||
.to_string();
|
.to_string();
|
||||||
check_bloom_and_record_hits(
|
check_brainwallet_bloom_and_record_hits(
|
||||||
&bloom,
|
&bloom,
|
||||||
address.to_string(),
|
address.to_string(),
|
||||||
&wtr,
|
&wtr,
|
||||||
source_id.to_string(),
|
source_id.to_string(),
|
||||||
"direct".to_string(),
|
"direct".to_string(),
|
||||||
|
hashing_rounds.to_string(),
|
||||||
"compressed".to_string(),
|
"compressed".to_string(),
|
||||||
"".to_string(),
|
|
||||||
"".to_string(),
|
|
||||||
"256".to_string(),
|
"256".to_string(),
|
||||||
passphrase.to_string(),
|
passphrase.to_string(),
|
||||||
true,
|
true,
|
||||||
|
@ -207,15 +223,14 @@ pub fn brainwallet_single_sha256_check_btc(
|
||||||
bitcoin::network::Network::Bitcoin,
|
bitcoin::network::Network::Bitcoin,
|
||||||
)
|
)
|
||||||
.to_string();
|
.to_string();
|
||||||
check_bloom_and_record_hits(
|
check_brainwallet_bloom_and_record_hits(
|
||||||
&bloom,
|
&bloom,
|
||||||
address.to_string(),
|
address.to_string(),
|
||||||
&wtr,
|
&wtr,
|
||||||
source_id.to_string(),
|
source_id.to_string(),
|
||||||
"direct".to_string(),
|
"direct".to_string(),
|
||||||
|
hashing_rounds.to_string(),
|
||||||
"compressed".to_string(),
|
"compressed".to_string(),
|
||||||
"".to_string(),
|
|
||||||
"".to_string(),
|
|
||||||
"256".to_string(),
|
"256".to_string(),
|
||||||
passphrase.to_string(),
|
passphrase.to_string(),
|
||||||
true,
|
true,
|
||||||
|
|
Loading…
Reference in New Issue