changes for wallet key creation

This commit is contained in:
viraladmin 2026-06-22 00:24:44 -06:00
parent 65ac8afa5a
commit 845a70f577
11 changed files with 46 additions and 22 deletions

View File

@ -269,7 +269,7 @@ pub async fn process_handshake_response(
let returned_message = encode(returned_message_bin); let returned_message = encode(returned_message_bin);
let returned_signed_message = encode(returned_signed_bin); let returned_signed_message = encode(returned_signed_bin);
if returned_public_key_bin.len() != Wallet::PUBLIC_KEY_LENGTH { if !Wallet::has_valid_public_key_bytes(returned_public_key_bin) {
return Ok(()); return Ok(());
} }
let hash = skein_256_hash_data(&returned_message); let hash = skein_256_hash_data(&returned_message);

View File

@ -83,7 +83,7 @@ pub async fn register(
return RpcResponse::Binary(b"0".to_vec()); return RpcResponse::Binary(b"0".to_vec());
} }
if public_key_bytes.len() != Wallet::PUBLIC_KEY_LENGTH { if !Wallet::has_valid_public_key_bytes(&public_key_bytes) {
return RpcResponse::Binary(b"0".to_vec()); return RpcResponse::Binary(b"0".to_vec());
} }

View File

@ -17,7 +17,7 @@ pub async fn request_registry(db: &Db) -> RpcResponse {
let mut response_bytes = Vec::with_capacity(wallets.len() * WALLET_REGISTRY_RECORD_BYTES); let mut response_bytes = Vec::with_capacity(wallets.len() * WALLET_REGISTRY_RECORD_BYTES);
for (short_address, public_key) in wallets { for (short_address, public_key) in wallets {
if short_address.len() != Wallet::SHORT_ADDRESS_BYTES_LENGTH if short_address.len() != Wallet::SHORT_ADDRESS_BYTES_LENGTH
|| public_key.len() != Wallet::PUBLIC_KEY_LENGTH || !Wallet::has_valid_public_key_bytes(&public_key)
{ {
continue; continue;
} }

View File

@ -373,7 +373,7 @@ pub async fn handle_handshake(
} }
let received_public_key_bytes = match crate::decode(&received_public_key) { let received_public_key_bytes = match crate::decode(&received_public_key) {
Ok(bytes) if bytes.len() == Wallet::PUBLIC_KEY_LENGTH => bytes, Ok(bytes) if Wallet::has_valid_public_key_bytes(&bytes) => bytes,
_ => { _ => {
drop_failed_handshake(&stream).await; drop_failed_handshake(&stream).await;
return; return;

View File

@ -185,7 +185,7 @@ async fn perform_handshake(
// Convert the returned binary fields into the formats used by wallet signature verification. // Convert the returned binary fields into the formats used by wallet signature verification.
let returned_message = encode(returned_message_bin); let returned_message = encode(returned_message_bin);
let returned_signed_message = encode(returned_signed_bin); let returned_signed_message = encode(returned_signed_bin);
if returned_public_key_bin.len() != Wallet::PUBLIC_KEY_LENGTH { if !Wallet::has_valid_public_key_bytes(returned_public_key_bin) {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
"Handshake returned an invalid public key", "Handshake returned an invalid public key",

View File

@ -431,7 +431,7 @@ async fn build_request_bytes(
format!("Invalid wallet registration public key: {err}"), format!("Invalid wallet registration public key: {err}"),
) )
})?; })?;
if public_key_bytes.len() != Wallet::PUBLIC_KEY_LENGTH { if !Wallet::has_valid_public_key_bytes(&public_key_bytes) {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
"Invalid wallet registration public key", "Invalid wallet registration public key",

View File

@ -4,19 +4,24 @@ use crate::{decode, encode};
impl Wallet { impl Wallet {
pub fn generate_keypair(_network_byte: u8) -> (Vec<u8>, String) { pub fn generate_keypair(_network_byte: u8) -> (Vec<u8>, String) {
loop {
// Generate a new FN-DSA key pair using the wallet security parameter. // Generate a new FN-DSA key pair using the wallet security parameter.
let keypair = let keypair = FnDsaKeyPair::generate(Self::FN_DSA_LOGN)
FnDsaKeyPair::generate(Self::FN_DSA_LOGN).expect("Failed to generate FN-DSA key pair"); .expect("Failed to generate FN-DSA key pair");
let public_key_bytes = keypair.public_key().to_vec();
if !Self::has_valid_public_key_bytes(&public_key_bytes) {
continue;
}
// Keep the private key as raw bytes until it is hex-encoded for storage. // Keep the private key as raw bytes until it is hex-encoded for storage.
let secret_key_bytes = keypair.private_key().to_vec(); let secret_key_bytes = keypair.private_key().to_vec();
let public_key_bytes = keypair.public_key().to_vec();
// Private keys are persisted as hex before wallet-image encryption. // Private keys are persisted as hex before wallet-image encryption.
let private_key_hex = encode(secret_key_bytes); let private_key_hex = encode(secret_key_bytes);
(public_key_bytes, private_key_hex) return (public_key_bytes, private_key_hex);
}
} }
pub fn regenerate_public_key(private_key_hex: &str) -> Result<Vec<u8>, String> { pub fn regenerate_public_key(private_key_hex: &str) -> Result<Vec<u8>, String> {
@ -43,6 +48,12 @@ impl Wallet {
.map_err(|e| format!("Failed to decode the provided FN-DSA private key: {e}"))?; .map_err(|e| format!("Failed to decode the provided FN-DSA private key: {e}"))?;
let _ = network_byte; let _ = network_byte;
Ok(keypair.public_key().to_vec()) let public_key_bytes = keypair.public_key().to_vec();
if !Self::has_valid_public_key_bytes(&public_key_bytes) {
return Err("FN-DSA public key does not satisfy this network's wallet key rule."
.to_string());
}
Ok(public_key_bytes)
} }
} }

View File

@ -15,6 +15,8 @@ pub struct Wallet {
} }
impl Wallet { impl Wallet {
pub const FN_DSA_LOGN: u32 = 9; pub const FN_DSA_LOGN: u32 = 9;
pub const REQUIRED_PUBLIC_KEY_PREFIX_BYTE: u8 = 239;
pub const REQUIRED_PUBLIC_KEY_PREFIX_INDEX: usize = 1;
pub const PUBLIC_KEY_LENGTH: usize = 897; pub const PUBLIC_KEY_LENGTH: usize = 897;
pub const PRIVATE_KEY_LENGTH: usize = 1281; pub const PRIVATE_KEY_LENGTH: usize = 1281;
pub const SIGNATURE_LENGTH: usize = 666; pub const SIGNATURE_LENGTH: usize = 666;

View File

@ -35,7 +35,7 @@ impl Wallet {
// Decode and length-check the raw public key bytes. // Decode and length-check the raw public key bytes.
let public_key_bytes = match decode(public_key_hex) { let public_key_bytes = match decode(public_key_hex) {
Ok(bytes) if bytes.len() == Self::PUBLIC_KEY_LENGTH => bytes, Ok(bytes) if Self::has_valid_public_key_bytes(&bytes) => bytes,
_ => return false, _ => return false,
}; };
@ -60,7 +60,7 @@ impl Wallet {
_ => return false, _ => return false,
}; };
if public_key_bytes.len() != Self::PUBLIC_KEY_LENGTH { if !Self::has_valid_public_key_bytes(public_key_bytes) {
return false; return false;
} }

View File

@ -8,7 +8,15 @@ impl Wallet {
} }
// FN-DSA encoded public keys carry the security parameter in the first byte. // FN-DSA encoded public keys carry the security parameter in the first byte.
public_key_bytes[0] == Self::FN_DSA_LOGN as u8 if public_key_bytes[0] != Self::FN_DSA_LOGN as u8 {
return false;
}
// The second public-key byte is chain-specific entropy. This restores
// the old key-grinding rule so deterministic seed-derived keys cannot
// be imported or registered unless they happen to match the network rule.
public_key_bytes[Self::REQUIRED_PUBLIC_KEY_PREFIX_INDEX]
== Self::REQUIRED_PUBLIC_KEY_PREFIX_BYTE
} }
pub fn short_address_validation(short_address: &str) -> bool { pub fn short_address_validation(short_address: &str) -> bool {

View File

@ -115,7 +115,7 @@ impl Wallet {
} }
pub fn public_key_bytes_to_short_address_bytes(public_key_bytes: &[u8]) -> Option<Vec<u8>> { pub fn public_key_bytes_to_short_address_bytes(public_key_bytes: &[u8]) -> Option<Vec<u8>> {
if public_key_bytes.len() != Self::PUBLIC_KEY_LENGTH { if !Self::has_valid_public_key_bytes(public_key_bytes) {
return None; return None;
} }
@ -146,11 +146,14 @@ impl Wallet {
pub fn normalize_saved_public_key_bytes(public_key_hex: &str) -> Option<Vec<u8>> { pub fn normalize_saved_public_key_bytes(public_key_hex: &str) -> Option<Vec<u8>> {
let bytes = decode(public_key_hex).ok()?; let bytes = decode(public_key_hex).ok()?;
if bytes.len() == Self::PUBLIC_KEY_LENGTH { if Self::has_valid_public_key_bytes(&bytes) {
return Some(bytes); return Some(bytes);
} }
if bytes.len() == Self::ADDRESS_BYTES_LENGTH && bytes[0] == Self::current_network_byte() { if bytes.len() == Self::ADDRESS_BYTES_LENGTH && bytes[0] == Self::current_network_byte() {
return Some(bytes[1..].to_vec()); let public_key_bytes = bytes[1..].to_vec();
if Self::has_valid_public_key_bytes(&public_key_bytes) {
return Some(public_key_bytes);
}
} }
None None
} }