key_operations.rs
1 use oqs::*; 2 use oqs::sig::{Sig, PublicKey, SecretKey}; 3 use std::fs::{self, File}; 4 use std::io::{self, Write, Read}; 5 use std::result::Result; 6 use base64::{Engine, engine::general_purpose}; 7 use rand::RngCore; 8 use chacha20poly1305::aead::OsRng; 9 use ed25519_dalek::{SigningKey as Ed25519PrivateKey, VerifyingKey as Ed25519PublicKey}; 10 11 use crate::{decrypt_data, encrypt_data, get_raw_bytes_public_key, get_raw_bytes_secret_key}; 12 13 pub fn save_dilithium_keys_to_file(public_key: &PublicKey, secret_key: &SecretKey, user: &str, password: &str) -> io::Result<()> { 14 let pub_bytes = get_raw_bytes_public_key(public_key); 15 let sec_bytes = get_raw_bytes_secret_key(secret_key); 16 17 let pub_base64 = general_purpose::STANDARD.encode(&pub_bytes); 18 let sec_base64 = general_purpose::STANDARD.encode(&sec_bytes); 19 20 let encrypted_pub = encrypt_data(&pub_base64, password) 21 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Encryption error: {}", e)))?; 22 let encrypted_sec = encrypt_data(&sec_base64, password) 23 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Encryption error: {}", e)))?; 24 25 fs::create_dir_all("keys")?; 26 let pub_file_path = format!("keys/{}_dilithium_public_key.enc", user); 27 let sec_file_path = format!("keys/{}_dilithium_secret_key.enc", user); 28 29 File::create(&pub_file_path)?.write_all(encrypted_pub.as_bytes())?; 30 File::create(&sec_file_path)?.write_all(encrypted_sec.as_bytes())?; 31 32 Ok(()) 33 } 34 35 pub fn load_dilithium_keys_from_file(sigalg: &Sig, user: &str, password: &str) -> io::Result<(PublicKey, SecretKey)> { 36 let pub_file_path = format!("keys/{}_dilithium_public_key.enc", user); 37 let sec_file_path = format!("keys/{}_dilithium_secret_key.enc", user); 38 39 let mut pub_file = File::open(&pub_file_path)?; 40 let mut pub_encrypted = String::new(); 41 pub_file.read_to_string(&mut pub_encrypted)?; 42 43 let mut sec_file = File::open(&sec_file_path)?; 44 let mut sec_encrypted = String::new(); 45 sec_file.read_to_string(&mut sec_encrypted)?; 46 47 let decrypted_pub = decrypt_data(&pub_encrypted, password) 48 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Decryption error: {}", e)))?; 49 let decrypted_sec = decrypt_data(&sec_encrypted, password) 50 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Decryption error: {}", e)))?; 51 52 let pub_bytes = general_purpose::STANDARD.decode(&decrypted_pub) 53 .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to decode public key"))?; 54 let sec_bytes = general_purpose::STANDARD.decode(&decrypted_sec) 55 .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to decode secret key"))?; 56 57 let public_key_ref = sigalg 58 .public_key_from_bytes(&pub_bytes) 59 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "Invalid public key data"))?; 60 let secret_key_ref = sigalg 61 .secret_key_from_bytes(&sec_bytes) 62 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "Invalid secret key data"))?; 63 64 Ok((public_key_ref.to_owned(), secret_key_ref.to_owned())) 65 } 66 67 pub fn save_eddsa_keys( 68 username: &str, 69 signing_key: &Ed25519PrivateKey, 70 verifying_key: &Ed25519PublicKey, 71 password: &str, 72 ) -> io::Result<()> { 73 let private_key_base64 = general_purpose::STANDARD.encode(signing_key.as_bytes()); 74 let public_key_base64 = general_purpose::STANDARD.encode(verifying_key.as_bytes()); 75 76 let encrypted_private_key = encrypt_data(&private_key_base64, password) 77 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Encryption failed: {}", e)))?; 78 let encrypted_public_key = encrypt_data(&public_key_base64, password) 79 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Encryption failed: {}", e)))?; 80 81 fs::create_dir_all("keys")?; 82 let priv_file_name = format!("keys/{}_eddsa_private_key.enc", username); 83 let pub_file_name = format!("keys/{}_eddsa_public_key.enc", username); 84 85 File::create(&priv_file_name)?.write_all(encrypted_private_key.as_bytes())?; 86 File::create(&pub_file_name)?.write_all(encrypted_public_key.as_bytes())?; 87 88 Ok(()) 89 } 90 91 pub fn load_eddsa_keys(username: &str, password: &str) -> Result<(Ed25519PrivateKey, Ed25519PublicKey), Box<dyn std::error::Error>> { 92 let priv_file_name = format!("keys/{}_eddsa_private_key.enc", username); 93 let pub_file_name = format!("keys/{}_eddsa_public_key.enc", username); 94 95 let mut priv_file = File::open(&priv_file_name)?; 96 let mut priv_key_encrypted = String::new(); 97 priv_file.read_to_string(&mut priv_key_encrypted)?; 98 let priv_key_decrypted = decrypt_data(&priv_key_encrypted, password)?; 99 100 let priv_key_bytes = general_purpose::STANDARD.decode(priv_key_decrypted.trim())?; 101 let priv_key_array: [u8; 32] = priv_key_bytes.as_slice().try_into()?; 102 let signing_key = Ed25519PrivateKey::from_bytes(&priv_key_array); 103 104 let mut pub_file = File::open(&pub_file_name)?; 105 let mut pub_key_encrypted = String::new(); 106 pub_file.read_to_string(&mut pub_key_encrypted)?; 107 let pub_key_decrypted = decrypt_data(&pub_key_encrypted, password)?; 108 109 let pub_key_bytes = general_purpose::STANDARD.decode(pub_key_decrypted.trim())?; 110 let pub_key_array: [u8; 32] = pub_key_bytes.as_slice().try_into()?; 111 let verifying_key = Ed25519PublicKey::from_bytes(&pub_key_array)?; 112 113 Ok((signing_key, verifying_key)) 114 } 115 116 pub fn generate_dilithium_keys(sigalg: &Sig) -> Result<(sig::PublicKey, sig::SecretKey), Box<dyn std::error::Error>> { 117 let (sig_pk, sig_sk) = sigalg.keypair()?; 118 Ok((sig_pk, sig_sk)) 119 } 120 121 /// Returns a tuple containing serialized signing key and verifying key. 122 pub fn generate_eddsa_keys() -> (Ed25519PrivateKey, Ed25519PublicKey) { 123 // Create a cryptographically secure pseudorandom number generator. 124 let mut csprng = OsRng; 125 126 // Generate 32 random bytes for the private key. 127 let mut secret_key_bytes = [0u8; 32]; 128 csprng.fill_bytes(&mut secret_key_bytes); 129 130 // Create the signing key from the random bytes. 131 let signing_key = Ed25519PrivateKey::from_bytes(&secret_key_bytes); 132 133 // Serialize the signing key and verifying key to byte arrays. 134 let signing_key_bytes = signing_key.clone().to_bytes(); // 32 bytes (private key) 135 let verifying_key_bytes = signing_key.verifying_key(); // 32 bytes (public key) 136 137 (signing_key_bytes.into(), verifying_key_bytes) 138 } 139 140 pub fn key_operations_dilithium( 141 sigalg: &Sig, 142 username: &str, 143 password: &str, 144 ) -> Result<(PublicKey, SecretKey), Box<dyn std::error::Error>> { 145 // Check if we have already saved keys for the given username; if not, generate and save them 146 match load_dilithium_keys_from_file(sigalg, username, password) { 147 Ok((pk, sk)) => { 148 println!("Loaded {}'s Dilithium5 keys from file.", username); 149 Ok((pk, sk)) 150 }, 151 Err(_) => { 152 let (pk, sk) = generate_dilithium_keys(sigalg)?; 153 154 // Handle save result 155 if let Err(e) = save_dilithium_keys_to_file(&pk, &sk, username, password) { 156 // Log or handle the error appropriately 157 println!("Error saving Dilithium5 keys for {}: {}", username, e); 158 // Depending on your requirement, you may want to propagate this error or return a success anyway 159 return Err(Box::new(e)); 160 } 161 162 Ok((pk, sk)) 163 } 164 } 165 } 166 167 168 pub fn key_operations_eddsa( 169 username: &str, 170 password: &str, 171 ) -> Result<(Ed25519PrivateKey, [u8; 32]), Box<dyn std::error::Error>> { 172 // Try to load the keys, expecting Result type from load_eddsa_keys 173 let result = load_eddsa_keys(username, password); 174 175 // If loading fails, generate and save new keys, otherwise return the loaded keys 176 match result { 177 Ok((sk, pk)) => { 178 // Successfully loaded keys 179 println!("Loaded {}'s EdDSA keys from file.", username); 180 Ok((sk, pk.to_bytes())) // Return public key and private key bytes 181 }, 182 Err(_) => { 183 // If loading failed, generate new keys and save them 184 let (sk, pk) = generate_eddsa_keys(); 185 186 // Handle save result 187 if let Err(e) = save_eddsa_keys(username, &sk, &pk, password) { 188 // Log or handle the error appropriately 189 println!("Error saving EdDSA keys for {}: {}", username, e); 190 // Depending on your requirement, you may want to propagate this error or return a success anyway 191 return Err(Box::new(e)); 192 } 193 194 // Return the newly generated keys 195 Ok((sk, pk.to_bytes())) 196 } 197 } 198 }