Skip to content

Commit 68fb4f0

Browse files
committed
Add GenerateHybridKey command and improve Kyber key error handling
- Introduced a new command `GenerateHybridKey` to generate hybrid post-quantum keypairs. - Updated command-line usage documentation to include `genhybrid`. - Enhanced error handling for loading Kyber keys, checking for file existence before reading, and providing clearer error messages. - Improved output messages for generated keys to enhance user experience.
1 parent ce096c4 commit 68fb4f0

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

src/crypto/post_quantum.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,35 @@ impl HybridKeyPair {
8080
std::path::Path::new(ecdh_sec_path),
8181
)?;
8282

83-
// Load Kyber keys from serialized files
83+
// Load Kyber keys from serialized files with better error handling
84+
let kyber_pub_path_obj = std::path::Path::new(kyber_pub_path);
85+
let kyber_sec_path_obj = std::path::Path::new(kyber_sec_path);
86+
87+
// Check if Kyber key files exist before trying to read them
88+
if !kyber_pub_path_obj.exists() {
89+
return Err(PostQuantumError::Io(io::Error::new(
90+
io::ErrorKind::NotFound,
91+
format!("Kyber public key file not found at: {:?}", kyber_pub_path_obj),
92+
)));
93+
}
94+
95+
if !kyber_sec_path_obj.exists() {
96+
return Err(PostQuantumError::Io(io::Error::new(
97+
io::ErrorKind::NotFound,
98+
format!("Kyber secret key file not found at: {:?}", kyber_sec_path_obj),
99+
)));
100+
}
101+
84102
let kyber_public_bytes =
85-
std::fs::read(kyber_pub_path).map_err(PostQuantumError::Io)?;
103+
std::fs::read(kyber_pub_path).map_err(|e| PostQuantumError::Io(io::Error::new(
104+
e.kind(),
105+
format!("Failed to read Kyber public key from {:?}: {}", kyber_pub_path_obj, e),
106+
)))?;
86107
let kyber_secret_bytes =
87-
std::fs::read(kyber_sec_path).map_err(PostQuantumError::Io)?;
108+
std::fs::read(kyber_sec_path).map_err(|e| PostQuantumError::Io(io::Error::new(
109+
e.kind(),
110+
format!("Failed to read Kyber secret key from {:?}: {}", kyber_sec_path_obj, e),
111+
)))?;
88112

89113
// Deserialize Kyber keys
90114
let kyber_public = Kyber512PublicKey::from_bytes(&kyber_public_bytes).map_err(|e| {

src/main.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ enum Command {
1313
GenerateKey {
1414
name: Option<String>,
1515
},
16+
GenerateHybridKey {
17+
name: Option<String>,
18+
},
1619
Encrypt {
1720
recipient_key: String,
1821
input_file: String,
@@ -44,6 +47,7 @@ Usage:
4447
4548
Commands:
4649
genkey [name] Generate a new keypair
50+
genhybrid [name] Generate a new hybrid post-quantum keypair
4751
import-key [--public] <keyfile> Import a key
4852
encrypt, -e Encrypt a message
4953
decrypt, -d Decrypt a message
@@ -120,6 +124,9 @@ fn parse_args_from_vec(args: Vec<String>) -> Result<Command, String> {
120124
"genkey" => Ok(Command::GenerateKey {
121125
name: filtered_args.get(2).cloned(),
122126
}),
127+
"genhybrid" => Ok(Command::GenerateHybridKey {
128+
name: filtered_args.get(2).cloned(),
129+
}),
123130
"import-key" => {
124131
if filtered_args.len() < 3 {
125132
return Err("Missing key file to import".to_string());
@@ -270,6 +277,45 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
270277
println!(" Public key: {}", pub_path.display());
271278
println!(" Private key: {}", priv_path.display());
272279
}
280+
Command::GenerateHybridKey { name } => {
281+
println!("🔐 Generating new hybrid post-quantum keypair...");
282+
let name = name.unwrap_or_else(|| "default".to_string());
283+
284+
// Generate hybrid key pair
285+
let hybrid_keypair = crypto::post_quantum::HybridKeyPair::new()?;
286+
287+
// Set up file paths
288+
let ecdh_pub_path = keystore
289+
.keys_dir
290+
.join("public")
291+
.join(format!("{}.pub", name));
292+
let ecdh_sec_path = keystore
293+
.keys_dir
294+
.join("private")
295+
.join(format!("{}.key", name));
296+
let kyber_pub_path = keystore
297+
.keys_dir
298+
.join("public")
299+
.join(format!("{}.kyber.pub", name));
300+
let kyber_sec_path = keystore
301+
.keys_dir
302+
.join("private")
303+
.join(format!("{}.kyber.key", name));
304+
305+
// Save hybrid key pair
306+
hybrid_keypair.save(
307+
ecdh_pub_path.to_str().unwrap(),
308+
ecdh_sec_path.to_str().unwrap(),
309+
kyber_pub_path.to_str().unwrap(),
310+
kyber_sec_path.to_str().unwrap(),
311+
)?;
312+
313+
println!("✨ Generated hybrid post-quantum keys:");
314+
println!(" ECDH Public key: {}", ecdh_pub_path.display());
315+
println!(" ECDH Private key: {}", ecdh_sec_path.display());
316+
println!(" Kyber Public key: {}", kyber_pub_path.display());
317+
println!(" Kyber Private key: {}", kyber_sec_path.display());
318+
}
273319
Command::SetDialect { dialect } => {
274320
let new_dialect = match dialect.to_lowercase().as_str() {
275321
"cat" => {

0 commit comments

Comments
 (0)