mirror of
https://github.com/TransparentLC/opencl_vanity_gpg.git
synced 2025-10-20 15:24:08 +00:00
Compare commits
2 commits
7c43505f54
...
5fd3a100d6
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5fd3a100d6 | ||
![]() |
ef3853bb22 |
5 changed files with 164 additions and 43 deletions
58
README.md
58
README.md
|
@ -28,12 +28,15 @@ $ opencl_vanity_gpg -h
|
|||
Usage: opencl_vanity_gpg [OPTIONS]
|
||||
|
||||
Options:
|
||||
-c, --cipher-suite <CIPHER_SUITE> Cipher suite of the vanity key
|
||||
-c, --cipher-suite <CIPHER_SUITE>
|
||||
Cipher suite of the vanity key
|
||||
ed25519, ecdsa-****, rsa**** => Primary key
|
||||
cv25519, ecdh-**** => Subkey
|
||||
Use gpg CLI for further editing of the key. [default: ed25519] [possible values: ed25519, cv25519, rsa2048, rsa3072, rsa4096, ecdh-p256, ecdh-p384, ecdh-p521, ecdsa-p256, ecdsa-p384, ecdsa-p521]
|
||||
-u, --user-id <USER_ID> OpenPGP compatible user ID [default: "Dummy <dummy@example.com>"]
|
||||
-p, --pattern <PATTERN> A pattern less than 40 chars for matching fingerprints
|
||||
-u, --user-id <USER_ID>
|
||||
OpenPGP compatible user ID [default: "Dummy <dummy@example.com>"]
|
||||
-p, --pattern <PATTERN>
|
||||
A pattern less than 40 chars for matching fingerprints
|
||||
> Format:
|
||||
* 0-9A-F are fixed, G-Z are wildcards
|
||||
* Other chars will be ignored
|
||||
|
@ -41,22 +44,47 @@ Options:
|
|||
> Example:
|
||||
* 11XXXX** may output a fingerprint ends with 11222234 or 11AAAABF
|
||||
* 11XXYYZZ may output a fingerprint ends with 11223344 or 11AABBCC
|
||||
-f, --filter <FILTER> OpenCL kernel function for uint h[5] for matching fingerprints
|
||||
-f, --filter <FILTER>
|
||||
OpenCL kernel function for uint h[5] for matching fingerprints
|
||||
Ignore the pattern and no estimate is given if this has been set
|
||||
> Example:
|
||||
* (h[4] & 0xFFFF) == 0x1234 outputs a fingerprint ends with 1234
|
||||
* (h[0] & 0xFFFF0000) == 0xABCD0000 outputs a fingerprint starts with ABCD
|
||||
-o, --output <OUTPUT> The dir where the vanity keys are saved
|
||||
-d, --device <DEVICE> Device ID to use
|
||||
-t, --thread <THREAD> Adjust it to maximum your device's usage
|
||||
-i, --iteration <ITERATION> Adjust it to maximum your device's usage [default: 512]
|
||||
--timeout <TIMEOUT> Exit after a specified time in seconds
|
||||
--oneshot Exit after getting a vanity key
|
||||
--no-progress Don't print progress
|
||||
--no-secret-key-logging Don't print armored secret key
|
||||
--list-device Show available OpenCL devices then exit
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
-o, --output <OUTPUT>
|
||||
The dir where the vanity keys are saved
|
||||
-d, --device <DEVICE>
|
||||
Device ID to use
|
||||
-t, --thread <THREAD>
|
||||
Adjust it to maximum your device's usage
|
||||
-i, --iteration <ITERATION>
|
||||
Adjust it to maximum your device's usage [default: 512]
|
||||
--timeout <TIMEOUT>
|
||||
Exit after a specified time in seconds
|
||||
--oneshot
|
||||
Exit after getting a vanity key
|
||||
--no-progress
|
||||
Don't print progress
|
||||
--no-secret-key-logging
|
||||
Don't print armored secret key
|
||||
--list-device
|
||||
Show available OpenCL devices then exit
|
||||
--future-timestamp
|
||||
Generate keys with future timestamps instead of past timestamps
|
||||
When true: search from start_timestamp forward in time (start_timestamp + 0 to max_time_range)
|
||||
When false: search from start_timestamp backward in time (start_timestamp - max_time_range to start_timestamp - 0)
|
||||
--start-timestamp <START_TIMESTAMP>
|
||||
Custom timestamp to start searching from (Unix timestamp)
|
||||
This is the base time point from which the search begins
|
||||
If not specified, uses current time as the starting point
|
||||
Example: 1640995200 (Jan 1, 2022 00:00:00 UTC)
|
||||
--max-time-range <MAX_TIME_RANGE>
|
||||
Maximum time range to search in seconds (default: 86400000 = 1000 days)
|
||||
future_timestamp=true: search from start_timestamp to (start_timestamp + max_time_range)
|
||||
future_timestamp=false: search from (start_timestamp - max_time_range) to start_timestamp [default: 86400000]
|
||||
-h, --help
|
||||
Print help
|
||||
-V, --version
|
||||
Print version
|
||||
|
||||
$ opencl_vanity_gpg -p 11XXYYZZ --oneshot
|
||||
[2025-01-08T19:00:25Z INFO opencl_vanity_gpg] Using device: Apple M1 Pro
|
||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -26,7 +26,7 @@ fn main() -> anyhow::Result<()> {
|
|||
if ARGS.list_device {
|
||||
info!("Available OpenCL devices: \n");
|
||||
for (i, device) in device_list.iter().enumerate() {
|
||||
println!("Device #{} - {:?}", i, device);
|
||||
println!("Device #{i} - {device:?}");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -51,13 +51,32 @@ fn main() -> anyhow::Result<()> {
|
|||
};
|
||||
|
||||
let iteration = ARGS.iteration;
|
||||
|
||||
// Determine the starting timestamp
|
||||
let start_timestamp = ARGS
|
||||
.start_timestamp
|
||||
.unwrap_or_else(|| chrono::Utc::now().timestamp());
|
||||
|
||||
// Use the user-specified time range instead of dimension * iteration
|
||||
let max_search_offset = ARGS.max_time_range as i64;
|
||||
|
||||
if ARGS.future_timestamp {
|
||||
info!(
|
||||
"You will get vanity keys created after {}",
|
||||
chrono::Utc::now()
|
||||
.checked_sub_signed(chrono::TimeDelta::seconds((dimension * iteration) as i64))
|
||||
.unwrap()
|
||||
"Starting search from {} and going forward in time (up to {} seconds)",
|
||||
chrono::DateTime::from_timestamp(start_timestamp, 0)
|
||||
.unwrap_or_else(chrono::Utc::now)
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
max_search_offset
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
"Starting search from {} and going backward in time (up to {} seconds)",
|
||||
chrono::DateTime::from_timestamp(start_timestamp, 0)
|
||||
.unwrap_or_else(chrono::Utc::now)
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
max_search_offset
|
||||
);
|
||||
}
|
||||
|
||||
if ARGS.output.is_none() {
|
||||
if ARGS.no_secret_key_logging {
|
||||
|
@ -91,6 +110,31 @@ fn main() -> anyhow::Result<()> {
|
|||
};
|
||||
|
||||
let mut vanity_key = VanitySecretKey::new(ARGS.cipher_suite, ARGS.user_id.clone(), &mut rng);
|
||||
|
||||
// Set the initial timestamp for the key
|
||||
// Ensure we use the full timestamp value, not truncated
|
||||
let initial_timestamp = if start_timestamp > u32::MAX as i64 {
|
||||
// If timestamp is too large for u32, we need to handle this carefully
|
||||
// For now, use the current approach but ensure we're aware of the limitation
|
||||
warn!(
|
||||
"Timestamp {} is too large for u32, may cause unexpected behavior",
|
||||
start_timestamp
|
||||
);
|
||||
start_timestamp as u32
|
||||
} else {
|
||||
start_timestamp as u32
|
||||
};
|
||||
|
||||
info!(
|
||||
"Using base timestamp: {} ({})",
|
||||
initial_timestamp,
|
||||
chrono::DateTime::from_timestamp(initial_timestamp as i64, 0)
|
||||
.unwrap_or_else(chrono::Utc::now)
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true)
|
||||
);
|
||||
|
||||
vanity_key.edit_timestamp(initial_timestamp, &mut rng);
|
||||
|
||||
let mut hashdata = manually_prepare_sha1(vanity_key.hashdata());
|
||||
|
||||
let (tx_hashdata, rx_hashdata) = channel::<Vec<u32>>();
|
||||
|
@ -106,6 +150,10 @@ fn main() -> anyhow::Result<()> {
|
|||
&[
|
||||
format!("#define FILTER(h) ({filter})"),
|
||||
format!("#define CHUNK ({})", hashdata.len() / 16),
|
||||
format!(
|
||||
"#define FUTURE_MODE ({})",
|
||||
if ARGS.future_timestamp { 1 } else { 0 }
|
||||
),
|
||||
]
|
||||
.join("\n"),
|
||||
),
|
||||
|
@ -128,8 +176,11 @@ fn main() -> anyhow::Result<()> {
|
|||
loop {
|
||||
debug!("Send key to OpenCL thread");
|
||||
tx_hashdata.send(hashdata)?;
|
||||
let vanity_key_next =
|
||||
let mut vanity_key_next =
|
||||
VanitySecretKey::new(ARGS.cipher_suite, ARGS.user_id.clone(), &mut rng);
|
||||
|
||||
// Set the same initial timestamp for consistency
|
||||
vanity_key_next.edit_timestamp(initial_timestamp, &mut rng);
|
||||
let hashdata_next = manually_prepare_sha1(vanity_key_next.hashdata());
|
||||
|
||||
debug!("Receive result from OpenCL thread");
|
||||
|
@ -224,6 +275,7 @@ fn opencl_thread(
|
|||
.arg(&buffer_hashdata)
|
||||
.arg(&buffer_result)
|
||||
.arg(ARGS.iteration as u64)
|
||||
.arg(ARGS.max_time_range as u32)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -4,15 +4,35 @@
|
|||
#ifdef __INJECTS__
|
||||
#define CHUNK (0)
|
||||
#define FILTER(h) (false)
|
||||
#define FUTURE_MODE (0)
|
||||
#endif
|
||||
|
||||
__kernel void vanity_sha1(__constant uint *hashdata, __global uint *result, const ulong iter) {
|
||||
__kernel void vanity_sha1(__constant uint *hashdata, __global uint *result, const ulong iter, const uint max_time_range) {
|
||||
uint data[CHUNK * 16];
|
||||
for (uint i = 0; i < CHUNK * 16; i++) data[i] = hashdata[i];
|
||||
uint nonce = data[1];
|
||||
|
||||
uint thread_id = get_global_id(0);
|
||||
|
||||
for (uint i = 0; i < iter; i++) {
|
||||
data[1] = nonce - get_global_id(0) * iter - i;
|
||||
// Use a simple sequential approach that searches close to base time first
|
||||
// Each thread gets a small sequential offset
|
||||
uint offset = thread_id + i * get_global_size(0);
|
||||
|
||||
// Wrap around within max_time_range to avoid going too far
|
||||
offset = offset % max_time_range;
|
||||
|
||||
if (FUTURE_MODE) {
|
||||
// For future mode: increment timestamp within range
|
||||
data[1] = nonce + offset;
|
||||
// Check for overflow
|
||||
if (data[1] < nonce) break;
|
||||
} else {
|
||||
// For past mode: decrement timestamp within range
|
||||
data[1] = nonce - offset;
|
||||
// Check for underflow
|
||||
if (data[1] > nonce) break;
|
||||
}
|
||||
|
||||
uint h[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};
|
||||
|
||||
|
|
|
@ -75,6 +75,25 @@ pub struct Args {
|
|||
/// Show available OpenCL devices then exit
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub list_device: bool,
|
||||
|
||||
/// Generate keys with future timestamps instead of past timestamps
|
||||
/// When true: search from start_timestamp forward in time (start_timestamp + 0 to max_time_range)
|
||||
/// When false: search from start_timestamp backward in time (start_timestamp - max_time_range to start_timestamp - 0)
|
||||
#[arg(long, default_value_t = false, verbatim_doc_comment)]
|
||||
pub future_timestamp: bool,
|
||||
|
||||
/// Custom timestamp to start searching from (Unix timestamp)
|
||||
/// This is the base time point from which the search begins
|
||||
/// If not specified, uses current time as the starting point
|
||||
/// Example: 1640995200 (Jan 1, 2022 00:00:00 UTC)
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
pub start_timestamp: Option<i64>,
|
||||
|
||||
/// Maximum time range to search in seconds (default: 86400000 = 1000 days)
|
||||
/// future_timestamp=true: search from start_timestamp to (start_timestamp + max_time_range)
|
||||
/// future_timestamp=false: search from (start_timestamp - max_time_range) to start_timestamp
|
||||
#[arg(long, default_value_t = 86400000, verbatim_doc_comment)]
|
||||
pub max_time_range: u64,
|
||||
}
|
||||
|
||||
impl Default for Args {
|
||||
|
@ -93,6 +112,9 @@ impl Default for Args {
|
|||
no_progress: true,
|
||||
no_secret_key_logging: false,
|
||||
list_device: false,
|
||||
future_timestamp: false,
|
||||
start_timestamp: None,
|
||||
max_time_range: 86400000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use std::{fmt::Write, mem};
|
|||
|
||||
pub use args::*;
|
||||
pub use device::DeviceList;
|
||||
pub use pattern::HashPattern;
|
||||
use indicatif::*;
|
||||
use indicatif_log_bridge::LogWrapper;
|
||||
pub use pattern::HashPattern;
|
||||
pub use vanity_key::VanitySecretKey;
|
||||
|
||||
/// Do SHA-1 padding manually
|
||||
|
@ -98,7 +98,6 @@ pub fn init_progress_bar(estimate: Option<f64>) -> ProgressBar {
|
|||
bar
|
||||
}
|
||||
|
||||
|
||||
pub fn format_number(v: impl Into<f64>) -> String {
|
||||
match Into::<f64>::into(v) {
|
||||
v if v >= 1e12f64 => {
|
||||
|
|
Loading…
Add table
Reference in a new issue