diff --git a/src/main.rs b/src/main.rs index a515075..6599932 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,14 @@ use std::io::Write; use std::path::PathBuf; use clap::{Parser, Subcommand}; +use leansig::serialization::Serializable; use leansig::signature::{ generalized_xmss::instantiations_poseidon_top_level::lifetime_2_to_the_32::hashing_optimized::SIGTopLevelTargetSumLifetime32Dim64Base8, SignatureScheme, }; -use serde_json::Value; + +// Type alias for the public key type +type PublicKeyType = ::PublicKey; /// A CLI tool to generate cryptographic keys for hash-based signatures. #[derive(Parser, Debug)] @@ -111,40 +114,27 @@ fn generate_keys( } /// Convert pubkey JSON file to hex string -/// Reads the JSON file, extracts root and parameter arrays, -/// converts each u32 to 4 bytes (little-endian), concatenates, -/// and returns hex string with "0x" prefix +/// Reads the JSON file, deserializes into PublicKey type using serde, +/// then uses SSZ serialization (to_bytes) to get canonical form bytes. +/// Returns hex string with "0x" prefix. +/// +/// Note: The JSON file contains field elements in Montgomery form (internal representation). +/// We must use to_bytes() which performs SSZ serialization to get the canonical form +/// that is expected by from_bytes() during signature verification. fn pubkey_json_to_hex(pk_file_path: &PathBuf) -> Result> { // Read JSON file let json_content = fs::read_to_string(pk_file_path)?; - let json: Value = serde_json::from_str(&json_content)?; - - // Extract root array (8 u32 integers) - let root_array = json["root"] - .as_array() - .ok_or("Missing or invalid 'root' array")?; - - // Extract parameter array (5 u32 integers) - let param_array = json["parameter"] - .as_array() - .ok_or("Missing or invalid 'parameter' array")?; - - // Convert root array to bytes (little-endian) - let mut pubkey_bytes = Vec::new(); - for val in root_array { - let num = val.as_u64().ok_or("Invalid number in root array")? as u32; - pubkey_bytes.extend_from_slice(&num.to_le_bytes()); - } - - // Convert parameter array to bytes (little-endian) - for val in param_array { - let num = val.as_u64().ok_or("Invalid number in parameter array")? as u32; - pubkey_bytes.extend_from_slice(&num.to_le_bytes()); - } - + + // Deserialize into PublicKeyType using serde (this handles Montgomery form) + let public_key: PublicKeyType = serde_json::from_str(&json_content)?; + + // Use to_bytes() which uses SSZ serialization (canonical form) + // This is the correct format expected by from_bytes() during verification + let pubkey_bytes = public_key.to_bytes(); + // Convert bytes to hex string with "0x" prefix let hex_string = format!("0x{}", hex::encode(&pubkey_bytes)); - + Ok(hex_string) }