2023-09-30 10:28:21 +00:00
|
|
|
|
/*
|
|
|
|
|
vanity-rage – a vanity key bruteforcer for age
|
|
|
|
|
Copyright (C) 2023 silt
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU
|
|
|
|
|
Affero General Public License as published by the Free Software Foundation, either version 3 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
|
|
|
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Affero General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License along with this program.
|
|
|
|
|
If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-09-30 10:53:27 +00:00
|
|
|
|
use age::{self, secrecy::ExposeSecret};
|
|
|
|
|
use chrono::{
|
|
|
|
|
prelude::{DateTime, Local},
|
|
|
|
|
SecondsFormat,
|
|
|
|
|
};
|
2023-09-30 06:25:12 +00:00
|
|
|
|
use glob_match::glob_match;
|
|
|
|
|
use rayon::prelude::*;
|
|
|
|
|
use std::{env, process};
|
|
|
|
|
|
2023-09-30 07:35:15 +00:00
|
|
|
|
fn genpair() -> (String, String) {
|
|
|
|
|
let key_priv = age::x25519::Identity::generate();
|
|
|
|
|
let key_pub = key_priv.to_public();
|
|
|
|
|
(
|
|
|
|
|
key_priv.to_string().expose_secret().to_string(),
|
|
|
|
|
key_pub.to_string(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn try_pattern(pattern: String, key_pub: String) -> bool {
|
|
|
|
|
glob_match(&pattern, &key_pub.to_string())
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-30 06:25:12 +00:00
|
|
|
|
fn main() {
|
|
|
|
|
let args = env::args();
|
|
|
|
|
let pattern = if args.len() < 2 {
|
|
|
|
|
println!(std::concat!(
|
|
|
|
|
"Usage: \n",
|
|
|
|
|
" vanity-rage [QUERY]\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"Queries follow standard glob syntax:\n",
|
|
|
|
|
" ? - match any single character\n",
|
|
|
|
|
" * - match zero or more characters\n",
|
|
|
|
|
" [abc] - match any character within the brackets\n",
|
|
|
|
|
" [!abc] - match any character not within the brackets\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"The provided glob should be able to match the returned key length\n",
|
|
|
|
|
));
|
|
|
|
|
process::exit(64);
|
|
|
|
|
} else {
|
2023-09-30 10:15:12 +00:00
|
|
|
|
format!("age1{}", args.last().unwrap().to_ascii_lowercase())
|
2023-09-30 06:25:12 +00:00
|
|
|
|
};
|
|
|
|
|
|
2023-09-30 07:35:15 +00:00
|
|
|
|
let pairs = loop {
|
2023-09-30 10:50:04 +00:00
|
|
|
|
let pairs: Vec<(String, String)> = (0..=4096)
|
2023-09-30 07:35:15 +00:00
|
|
|
|
.into_par_iter()
|
|
|
|
|
.filter_map(|_| {
|
|
|
|
|
let keypair = genpair();
|
|
|
|
|
if try_pattern(pattern.clone(), keypair.1.clone()) {
|
|
|
|
|
Some(keypair)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
if pairs.len() > 0 {
|
|
|
|
|
break pairs;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-30 10:49:09 +00:00
|
|
|
|
let (key_priv, key_pub) = pairs.first().unwrap();
|
2023-09-30 10:53:27 +00:00
|
|
|
|
let timestamp = Into::<DateTime<Local>>::into(std::time::SystemTime::now())
|
|
|
|
|
.to_rfc3339_opts(SecondsFormat::Secs, false);
|
|
|
|
|
println!("# created: {timestamp}\n# public key: {key_pub}\n{key_priv}");
|
2023-09-30 06:25:12 +00:00
|
|
|
|
}
|