mirror of
https://github.com/TransparentLC/opencl_vanity_gpg.git
synced 2025-10-20 15:24:08 +00:00
chore: clippy
This commit is contained in:
parent
f53ffd1c60
commit
e224d84f1c
2 changed files with 237 additions and 178 deletions
173
src/main.rs
173
src/main.rs
|
@ -1,21 +1,12 @@
|
|||
mod vanity_gpg;
|
||||
|
||||
use vanity_gpg::{CipherSuite, VanitySecretKey};
|
||||
use clap::Parser;
|
||||
use std::{
|
||||
fs,
|
||||
io,
|
||||
io::Write,
|
||||
mem,
|
||||
path::Path,
|
||||
sync::mpsc::channel,
|
||||
thread,
|
||||
time::Instant,
|
||||
};
|
||||
use log::{debug, info, warn};
|
||||
use ocl::{Buffer, Device, Platform, ProQue};
|
||||
use rand::thread_rng;
|
||||
use pgp::types::PublicKeyTrait;
|
||||
use log::{warn, info, debug};
|
||||
use rand::thread_rng;
|
||||
use std::{fs, io, io::Write, mem, path::Path, sync::mpsc::channel, thread, time::Instant};
|
||||
use vanity_gpg::{CipherSuite, VanitySecretKey};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
|
@ -44,7 +35,9 @@ struct Args {
|
|||
|
||||
/// 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
|
||||
#[arg(short, long, verbatim_doc_comment)]
|
||||
|
@ -87,17 +80,19 @@ struct Args {
|
|||
device_list: bool,
|
||||
}
|
||||
|
||||
/// 手动进行SHA-1的填充操作
|
||||
/// SHA-1的一个数据块是512 bit,因此输出的Vec<u32>长度是16的倍数
|
||||
/// Do SHA-1 padding manually
|
||||
/// A SHA-1 block is 512 bit, so the output Vec<u32> length is a multiple of 16
|
||||
fn manually_prepare_sha1(hashdata: Vec<u8>) -> Vec<u32> {
|
||||
// 填充后的长度
|
||||
// 用80 00 ...填充到448 mod 512 bit即56 mod 64 bytes,加上u64的8 bytes后长度是64的倍数
|
||||
// Length after padding
|
||||
// Fill with 0x80 0x00 ... to 448 mod 512 bit, which is 56 mod 64 bytes
|
||||
// plus u64's 8 bytes, the length is a multiple of 64
|
||||
let padded_length = hashdata.len() + (64 - ((hashdata.len() + 8) % 64)) + 8;
|
||||
let mut result_u8 = Vec::with_capacity(padded_length);
|
||||
result_u8.extend_from_slice(&hashdata);
|
||||
result_u8.push(0x80);
|
||||
result_u8.resize(padded_length, 0);
|
||||
// 需要把Vec<u8>直接转换成Vec<u32>
|
||||
|
||||
// convert Vec<u8> to Vec<u32>
|
||||
// https://stackoverflow.com/questions/49690459/converting-a-vecu32-to-vecu8-in-place-and-with-minimal-overhead
|
||||
let mut result_u32 = unsafe {
|
||||
let ptr = result_u8.as_mut_ptr() as *mut u32;
|
||||
|
@ -106,13 +101,15 @@ fn manually_prepare_sha1(hashdata: Vec<u8>) -> Vec<u32> {
|
|||
mem::forget(result_u8);
|
||||
Vec::from_raw_parts(ptr, length, capacity)
|
||||
};
|
||||
|
||||
// assert_eq!(result_u32.len() % 16, 0);
|
||||
// SHA-1的word和length使用大端序
|
||||
for i in 0..result_u32.len() {
|
||||
result_u32[i] = result_u32[i].to_be();
|
||||
// SHA-1 uses big-endian words and length
|
||||
for pos in &mut result_u32 {
|
||||
*pos = pos.to_be();
|
||||
}
|
||||
|
||||
let bit_length = hashdata.len() * 8;
|
||||
result_u32[padded_length / 4 - 1] = (bit_length ) as u32;
|
||||
result_u32[padded_length / 4 - 1] = (bit_length) as u32;
|
||||
result_u32[padded_length / 4 - 2] = (bit_length >> 32) as u32;
|
||||
result_u32
|
||||
}
|
||||
|
@ -123,7 +120,8 @@ fn parse_pattern(pattern: String) -> (String, f64) {
|
|||
_ => panic!("Invalid pattern"),
|
||||
};
|
||||
let mut parts: Vec<String> = vec![];
|
||||
// 处理0-9A-F
|
||||
|
||||
// Handle fixed 0-9A-F
|
||||
let mut fixed_pos_count: usize = 0;
|
||||
for i in 0..=4 {
|
||||
let mut mask = String::new();
|
||||
|
@ -145,8 +143,10 @@ fn parse_pattern(pattern: String) -> (String, f64) {
|
|||
parts.push(format!("(h[{i}] & 0x{mask}) == 0x{value}"));
|
||||
}
|
||||
}
|
||||
// 处理通配符G-Z
|
||||
let mut wildcard_pos_all: [Vec<usize>; (b'Z' - b'G' + 1) as usize] = std::default::Default::default();
|
||||
|
||||
// Handle wildcard G-Z
|
||||
let mut wildcard_pos_all: [Vec<usize>; (b'Z' - b'G' + 1) as usize] =
|
||||
std::default::Default::default();
|
||||
for (i, wildcard) in pattern.chars().enumerate() {
|
||||
if ('G'..='Z').contains(&wildcard) {
|
||||
wildcard_pos_all[((wildcard as u8) - b'G') as usize].push(i);
|
||||
|
@ -179,25 +179,36 @@ fn parse_pattern(pattern: String) -> (String, f64) {
|
|||
wildcard_pos_count += wildcard_pos.len() - 1;
|
||||
}
|
||||
}
|
||||
let filter = if parts.len() != 0 {
|
||||
let filter = if !parts.is_empty() {
|
||||
parts.join(" && ")
|
||||
} else {
|
||||
String::from("true")
|
||||
};
|
||||
(filter, (16f64).powi((fixed_pos_count + wildcard_pos_count) as i32))
|
||||
(
|
||||
filter,
|
||||
(16f64).powi((fixed_pos_count + wildcard_pos_count) as i32),
|
||||
)
|
||||
}
|
||||
|
||||
fn format_number(v: impl Into<f64>) -> String {
|
||||
match Into::<f64>::into(v) {
|
||||
// v if v >= 1e9f64 => { return format!("{:.02}g", v / 1e9f64); },
|
||||
v if v >= 1e6f64 => { return format!("{:.02}m", v / 1e6f64); },
|
||||
v if v >= 1e3f64 => { return format!("{:.02}k", v / 1e3f64); },
|
||||
v => { return format!("{v:.02}"); },
|
||||
v if v >= 1e6f64 => {
|
||||
format!("{:.02}m", v / 1e6f64)
|
||||
}
|
||||
v if v >= 1e3f64 => {
|
||||
format!("{:.02}k", v / 1e3f64)
|
||||
}
|
||||
v => {
|
||||
format!("{v:.02}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"))
|
||||
env_logger::Builder::from_env(
|
||||
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"),
|
||||
)
|
||||
.format_indent(None)
|
||||
.init();
|
||||
|
||||
|
@ -222,34 +233,30 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
};
|
||||
debug!("{:?}", &args);
|
||||
|
||||
let device_list: Vec<(Platform, Device)> = Platform::list()
|
||||
let device_list: Vec<(Platform, Device)> =
|
||||
Platform::list()
|
||||
.iter()
|
||||
.rfold(
|
||||
Vec::new(),
|
||||
|mut list, platform| {
|
||||
match Device::list_all(platform) {
|
||||
Ok(devices) => {
|
||||
let mut devices = devices
|
||||
.iter()
|
||||
.map(|device| (*platform, *device))
|
||||
.collect();
|
||||
.rfold(Vec::new(), |mut list, platform| {
|
||||
if let Ok(devices) = Device::list_all(platform) {
|
||||
let mut devices = devices.iter().map(|device| (*platform, *device)).collect();
|
||||
list.append(&mut devices);
|
||||
},
|
||||
Err(_) => {},
|
||||
}
|
||||
list
|
||||
},
|
||||
);
|
||||
});
|
||||
if args.device_list {
|
||||
for (index, (platform, device)) in device_list.iter().enumerate() {
|
||||
info!("Device #{} - {}", index, format!(
|
||||
info!(
|
||||
"Device #{} - {}",
|
||||
index,
|
||||
format!(
|
||||
"{} ({}, MaxWorkGroupSize={}, MaxWorkItemSizes={}, MaxWorkItemDimensions={})",
|
||||
device.name()?,
|
||||
platform.name()?,
|
||||
device.info(ocl::core::DeviceInfo::MaxWorkGroupSize)?,
|
||||
device.info(ocl::core::DeviceInfo::MaxWorkItemSizes)?,
|
||||
device.info(ocl::core::DeviceInfo::MaxWorkItemDimensions)?,
|
||||
));
|
||||
)
|
||||
);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -274,10 +281,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
info!(
|
||||
"You will get vanity keys created after {}",
|
||||
chrono::Utc::now()
|
||||
.checked_sub_signed(chrono::TimeDelta::seconds((dimension * iteration) as i64)).unwrap()
|
||||
.checked_sub_signed(chrono::TimeDelta::seconds((dimension * iteration) as i64))
|
||||
.unwrap()
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
);
|
||||
if let None = args.output {
|
||||
if args.output.is_none() {
|
||||
if args.no_secret_key_logging {
|
||||
warn!("No output dir given and you disabled secret key logging. You have no chance to save generated vanity keys.");
|
||||
} else {
|
||||
|
@ -291,7 +299,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
Some(pattern) => {
|
||||
let (filter, estimate) = parse_pattern(pattern);
|
||||
(filter, Some(estimate))
|
||||
},
|
||||
}
|
||||
None => panic!("No filter or pattern given"),
|
||||
},
|
||||
};
|
||||
|
@ -300,7 +308,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut rng = thread_rng();
|
||||
|
||||
match args.cipher_suite {
|
||||
CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096 => warn!("Generating RSA vanity keys is not recommended. Too slow!"),
|
||||
CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096 => {
|
||||
warn!("Generating RSA vanity keys is not recommended. Too slow!")
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
|
@ -308,13 +318,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut hashdata = manually_prepare_sha1(vanity_key.hashdata());
|
||||
|
||||
let pro_que = ProQue::builder()
|
||||
.src(std::include_str!("shader.cl").replace(
|
||||
.src(
|
||||
std::include_str!("shader.cl").replace(
|
||||
"#define __INJECTS__",
|
||||
&[
|
||||
format!("#define FILTER(h) ({filter})"),
|
||||
format!("#define CHUNK ({})", hashdata.len() / 16),
|
||||
].join("\n"),
|
||||
))
|
||||
]
|
||||
.join("\n"),
|
||||
),
|
||||
)
|
||||
.device(device)
|
||||
.dims(dimension)
|
||||
.build()?;
|
||||
|
@ -341,21 +354,27 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.queue(pro_que.queue().clone())
|
||||
.len(hashdata.len())
|
||||
.copy_host_slice(&hashdata)
|
||||
.build().unwrap();
|
||||
.build()
|
||||
.unwrap();
|
||||
let kernel = pro_que
|
||||
.kernel_builder("vanity_sha1")
|
||||
.arg(&buffer_hashdata)
|
||||
.arg(&buffer_result)
|
||||
.arg(iteration as u64)
|
||||
.build().unwrap();
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
unsafe { kernel.enq().unwrap(); }
|
||||
unsafe {
|
||||
kernel.enq().unwrap();
|
||||
}
|
||||
|
||||
buffer_result.read(&mut vec).enq().unwrap();
|
||||
tx_result.send(match vec[0] {
|
||||
tx_result
|
||||
.send(match vec[0] {
|
||||
0 => None,
|
||||
x => Some(x),
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
debug!("OpenCL thread quit");
|
||||
});
|
||||
|
@ -363,7 +382,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
loop {
|
||||
debug!("Send key to OpenCL thread");
|
||||
tx_hashdata.send(hashdata)?;
|
||||
let vanity_key_next = VanitySecretKey::new(args.cipher_suite, args.user_id.clone(), &mut rng);
|
||||
let vanity_key_next =
|
||||
VanitySecretKey::new(args.cipher_suite, args.user_id.clone(), &mut rng);
|
||||
let hashdata_next = manually_prepare_sha1(vanity_key_next.hashdata());
|
||||
|
||||
debug!("Receive result from OpenCL thread");
|
||||
|
@ -376,7 +396,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
Some(estimate) => print!(
|
||||
"[{}] {}/{} {:.02}x {:.02}s {} hash/s \r",
|
||||
match hashed_count % 16 {
|
||||
x if x < 8 => format!("{}>))'>{}", " ".repeat( x), " ".repeat(7 - x)),
|
||||
x if x < 8 => format!("{}>))'>{}", " ".repeat(x), " ".repeat(7 - x)),
|
||||
x => format!("{}<'((<{}", " ".repeat(15 - x), " ".repeat(x - 8)),
|
||||
},
|
||||
format_number(hashed as f64),
|
||||
|
@ -388,7 +408,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
None => print!(
|
||||
"[{}] {} {:.02}s {} hash/s \r",
|
||||
match hashed_count % 16 {
|
||||
x if x < 8 => format!("{}>))'>{}", " ".repeat( x), " ".repeat(7 - x)),
|
||||
x if x < 8 => format!("{}>))'>{}", " ".repeat(x), " ".repeat(7 - x)),
|
||||
x => format!("{}<'((<{}", " ".repeat(15 - x), " ".repeat(x - 8)),
|
||||
},
|
||||
format_number(hashed as f64),
|
||||
|
@ -399,8 +419,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
io::stdout().flush()?;
|
||||
}
|
||||
|
||||
match vanity_timestamp {
|
||||
Some(vanity_timestamp) => {
|
||||
if let Some(vanity_timestamp) = vanity_timestamp {
|
||||
vanity_key.edit_timestamp(vanity_timestamp, &mut rng);
|
||||
if args.no_secret_key_logging {
|
||||
info!("Get a vanity key!");
|
||||
|
@ -409,12 +428,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
info!(
|
||||
"Created at: {} ({})",
|
||||
vanity_key.secret_key.created_at().to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
vanity_key
|
||||
.secret_key
|
||||
.created_at()
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
vanity_key.secret_key.created_at().timestamp(),
|
||||
);
|
||||
info!("Fingerprint #0: {}", hex::encode_upper(vanity_key.secret_key.fingerprint().as_bytes()));
|
||||
info!(
|
||||
"Fingerprint #0: {}",
|
||||
hex::encode_upper(vanity_key.secret_key.fingerprint().as_bytes())
|
||||
);
|
||||
for (i, subkey) in vanity_key.secret_key.secret_subkeys.iter().enumerate() {
|
||||
info!("Fingerprint #{}: {}", i + 1, hex::encode_upper(subkey.fingerprint().as_bytes()));
|
||||
info!(
|
||||
"Fingerprint #{}: {}",
|
||||
i + 1,
|
||||
hex::encode_upper(subkey.fingerprint().as_bytes())
|
||||
);
|
||||
}
|
||||
match estimate {
|
||||
Some(estimate) => info!(
|
||||
|
@ -433,17 +462,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
if let Some(ref output_dir) = args.output {
|
||||
fs::write(
|
||||
Path::new(output_dir).join(format!("{}-sec.asc", hex::encode_upper(vanity_key.secret_key.fingerprint().as_bytes()))),
|
||||
Path::new(output_dir).join(format!(
|
||||
"{}-sec.asc",
|
||||
hex::encode_upper(vanity_key.secret_key.fingerprint().as_bytes())
|
||||
)),
|
||||
vanity_key.to_armored_string()?,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
if args.oneshot {
|
||||
break;
|
||||
}
|
||||
hashed = 0;
|
||||
start = Instant::now();
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
if let Some(timeout) = args.timeout {
|
||||
if elapsed > timeout {
|
||||
|
|
|
@ -1,34 +1,24 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use clap::ValueEnum;
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use rand::{Rng, CryptoRng};
|
||||
use log::debug;
|
||||
use pgp::{
|
||||
composed::{key::SecretKeyParamsBuilder, KeyType},
|
||||
crypto::{
|
||||
hash::HashAlgorithm,
|
||||
sym::SymmetricKeyAlgorithm,
|
||||
ecc_curve::ECCCurve,
|
||||
},
|
||||
ser::Serialize,
|
||||
crypto::{ecc_curve::ECCCurve, hash::HashAlgorithm, sym::SymmetricKeyAlgorithm},
|
||||
packet::KeyFlags,
|
||||
types::{
|
||||
CompressionAlgorithm,
|
||||
PublicKeyTrait,
|
||||
SecretKeyTrait,
|
||||
KeyVersion,
|
||||
},
|
||||
Deserializable,
|
||||
SecretKey,
|
||||
SecretSubkey,
|
||||
SignedSecretKey,
|
||||
SubkeyParamsBuilder,
|
||||
ser::Serialize,
|
||||
types::{CompressionAlgorithm, KeyVersion, PublicKeyTrait, SecretKeyTrait},
|
||||
Deserializable, SecretKey, SecretSubkey, SignedSecretKey, SubkeyParamsBuilder,
|
||||
};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use smallvec::smallvec;
|
||||
use log::debug;
|
||||
|
||||
/// 获取用于计算一个私钥的指纹的数据
|
||||
/// Get the data used to calculate the fingerprint of a private key
|
||||
fn build_secret_key_hashdata(secret_key: impl SecretKeyTrait) -> Vec<u8> {
|
||||
let mut hashdata = vec![0x99, 0, 0, 0x04, 0, 0, 0, 0];
|
||||
BigEndian::write_u32(&mut hashdata[4..8], secret_key.created_at().timestamp() as u32);
|
||||
BigEndian::write_u32(
|
||||
&mut hashdata[4..8],
|
||||
secret_key.created_at().timestamp() as u32,
|
||||
);
|
||||
hashdata.push(secret_key.algorithm().into());
|
||||
secret_key.public_params().to_writer(&mut hashdata).unwrap();
|
||||
let packet_len = (hashdata.len() - 3) as u16;
|
||||
|
@ -36,7 +26,7 @@ fn build_secret_key_hashdata(secret_key: impl SecretKeyTrait) -> Vec<u8> {
|
|||
hashdata
|
||||
}
|
||||
|
||||
/// 需要被修改的密钥类型
|
||||
/// Cipher Suites
|
||||
#[derive(ValueEnum, Default, Clone, Copy, Debug)]
|
||||
#[clap(rename_all = "kebab_case")]
|
||||
pub enum CipherSuite {
|
||||
|
@ -53,6 +43,7 @@ pub enum CipherSuite {
|
|||
EcdsaP384,
|
||||
EcdsaP521,
|
||||
}
|
||||
|
||||
pub struct VanitySecretKey {
|
||||
pub cipher_suite: CipherSuite,
|
||||
pub secret_key: SignedSecretKey,
|
||||
|
@ -92,10 +83,13 @@ impl VanitySecretKey {
|
|||
secret_key_params_builder
|
||||
.key_type(KeyType::EdDSALegacy)
|
||||
.subkey(subkey_params_builder.build().unwrap());
|
||||
},
|
||||
CipherSuite::EcdhP256 | CipherSuite::EcdsaP256 |
|
||||
CipherSuite::EcdhP384 | CipherSuite::EcdsaP384 |
|
||||
CipherSuite::EcdhP521 | CipherSuite::EcdsaP521 => {
|
||||
}
|
||||
CipherSuite::EcdhP256
|
||||
| CipherSuite::EcdsaP256
|
||||
| CipherSuite::EcdhP384
|
||||
| CipherSuite::EcdsaP384
|
||||
| CipherSuite::EcdhP521
|
||||
| CipherSuite::EcdsaP521 => {
|
||||
let curve = match cipher_suite {
|
||||
CipherSuite::EcdhP256 | CipherSuite::EcdsaP256 => ECCCurve::P256,
|
||||
CipherSuite::EcdhP384 | CipherSuite::EcdsaP384 => ECCCurve::P384,
|
||||
|
@ -109,7 +103,7 @@ impl VanitySecretKey {
|
|||
secret_key_params_builder
|
||||
.key_type(KeyType::ECDSA(curve.clone()))
|
||||
.subkey(subkey_params_builder.build().unwrap());
|
||||
},
|
||||
}
|
||||
CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096 => {
|
||||
let bits = match cipher_suite {
|
||||
CipherSuite::RSA2048 => 2048,
|
||||
|
@ -120,13 +114,15 @@ impl VanitySecretKey {
|
|||
secret_key_params_builder
|
||||
.key_type(KeyType::Rsa(bits))
|
||||
.can_encrypt(true);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let secret_key_params = secret_key_params_builder.build().unwrap();
|
||||
let secret_key = secret_key_params
|
||||
.generate(&mut rng).unwrap()
|
||||
.sign(&mut rng, || String::new()).unwrap();
|
||||
.generate(&mut rng)
|
||||
.unwrap()
|
||||
.sign(&mut rng, String::new)
|
||||
.unwrap();
|
||||
assert_eq!(secret_key.version(), KeyVersion::V4);
|
||||
|
||||
Self {
|
||||
|
@ -139,7 +135,7 @@ impl VanitySecretKey {
|
|||
// RFC 9580 - OpenPGP
|
||||
// 4. Packet Syntax
|
||||
// https://datatracker.ietf.org/doc/html/rfc9580#name-packet-syntax
|
||||
let mut secret_key_bytes = Vec::from(self.secret_key.to_bytes().unwrap());
|
||||
let mut secret_key_bytes = self.secret_key.to_bytes().unwrap();
|
||||
let mut packet_read_pos: usize = 0;
|
||||
while packet_read_pos < secret_key_bytes.len() {
|
||||
let cipher_type_byte = secret_key_bytes[packet_read_pos];
|
||||
|
@ -148,15 +144,33 @@ impl VanitySecretKey {
|
|||
let (size, size_length) = match cipher_type_byte >> 6 {
|
||||
0b10 => match cipher_type_byte & 0b00000011 {
|
||||
0 => (secret_key_bytes[packet_read_pos] as usize, 1),
|
||||
1 => (BigEndian::read_u16(&secret_key_bytes[packet_read_pos..packet_read_pos + 2]) as usize, 2),
|
||||
2 => (BigEndian::read_u32(&secret_key_bytes[packet_read_pos..packet_read_pos + 4]) as usize, 4),
|
||||
1 => (
|
||||
BigEndian::read_u16(&secret_key_bytes[packet_read_pos..packet_read_pos + 2])
|
||||
as usize,
|
||||
2,
|
||||
),
|
||||
2 => (
|
||||
BigEndian::read_u32(&secret_key_bytes[packet_read_pos..packet_read_pos + 4])
|
||||
as usize,
|
||||
4,
|
||||
),
|
||||
3 => unimplemented!("Indeterminate length"),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
0b11 => match secret_key_bytes[packet_read_pos] {
|
||||
x if x < 192 => (secret_key_bytes[packet_read_pos] as usize, 1),
|
||||
x if x < 224 => ((((secret_key_bytes[packet_read_pos] - 192) as usize) << 8) + (secret_key_bytes[packet_read_pos + 1] as usize) + 192, 2),
|
||||
x if x == 255 => (BigEndian::read_u32(&secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5]) as usize, 5),
|
||||
x if x < 224 => (
|
||||
(((secret_key_bytes[packet_read_pos] - 192) as usize) << 8)
|
||||
+ (secret_key_bytes[packet_read_pos + 1] as usize)
|
||||
+ 192,
|
||||
2,
|
||||
),
|
||||
255 => (
|
||||
BigEndian::read_u32(
|
||||
&secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5],
|
||||
) as usize,
|
||||
5,
|
||||
),
|
||||
_ => unimplemented!("Partial body length"),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
|
@ -172,45 +186,59 @@ impl VanitySecretKey {
|
|||
// 0x05 => Secret-Key Packet
|
||||
// 0x07 => Secret-Subkey Packet
|
||||
if [0x05, 0x07].contains(&packet_type) {
|
||||
BigEndian::write_u32(&mut secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5], timestamp);
|
||||
BigEndian::write_u32(
|
||||
&mut secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5],
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
packet_read_pos += size;
|
||||
}
|
||||
// 只修改了时间,因此这个key的签名是无效的
|
||||
|
||||
// The signature of this key is invalid because only the timestamp is modified
|
||||
let edited_key = SignedSecretKey::from_bytes(&secret_key_bytes[..]).unwrap();
|
||||
|
||||
// 重新对key签名
|
||||
// Re-sign the key
|
||||
let mut subkey_flags = KeyFlags::default();
|
||||
subkey_flags.set_encrypt_storage(true);
|
||||
subkey_flags.set_encrypt_comms(true);
|
||||
self.secret_key = SecretKey::new(
|
||||
edited_key.primary_key,
|
||||
edited_key.details.as_unsigned(),
|
||||
edited_key.public_subkeys
|
||||
edited_key
|
||||
.public_subkeys
|
||||
.iter()
|
||||
.map(|e| e.as_unsigned())
|
||||
.collect(),
|
||||
edited_key.secret_subkeys
|
||||
edited_key
|
||||
.secret_subkeys
|
||||
.iter()
|
||||
.map(|e| SecretSubkey::new(e.key.clone(), subkey_flags))
|
||||
.collect(),
|
||||
).sign(&mut rng, || String::new()).unwrap();
|
||||
// self.secret_key.verify().unwrap();
|
||||
)
|
||||
.sign(&mut rng, String::new)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn hashdata(&self) -> Vec<u8> {
|
||||
match self.cipher_suite {
|
||||
CipherSuite::Ed25519 |
|
||||
CipherSuite::EcdsaP256 | CipherSuite::EcdsaP384 | CipherSuite::EcdsaP521 |
|
||||
CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096
|
||||
=> build_secret_key_hashdata(&self.secret_key),
|
||||
CipherSuite::Cv25519 |
|
||||
CipherSuite::EcdhP256 | CipherSuite::EcdhP384 | CipherSuite::EcdhP521
|
||||
=> build_secret_key_hashdata(&self.secret_key.secret_subkeys[0]),
|
||||
CipherSuite::Ed25519
|
||||
| CipherSuite::EcdsaP256
|
||||
| CipherSuite::EcdsaP384
|
||||
| CipherSuite::EcdsaP521
|
||||
| CipherSuite::RSA2048
|
||||
| CipherSuite::RSA3072
|
||||
| CipherSuite::RSA4096 => build_secret_key_hashdata(&self.secret_key),
|
||||
CipherSuite::Cv25519
|
||||
| CipherSuite::EcdhP256
|
||||
| CipherSuite::EcdhP384
|
||||
| CipherSuite::EcdhP521 => {
|
||||
build_secret_key_hashdata(&self.secret_key.secret_subkeys[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_armored_string(&self) -> Result<String, pgp::errors::Error> {
|
||||
self.secret_key.to_armored_string(pgp::ArmorOptions::default())
|
||||
self.secret_key
|
||||
.to_armored_string(pgp::ArmorOptions::default())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue