/ client / src / key_operations.rs
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  }