/ client / src / authentication.rs
authentication.rs
  1  use ed25519_dalek::{SigningKey as Ed25519PrivateKey, VerifyingKey as Ed25519PublicKey, SecretKey as Ed25519SecretKey, Signature as Ed25519Signature, Signer as Ed25519Signer, Verifier as Ed25519Verifier};
  2  use oqs::sig::Sig;
  3  use std::error::Error;
  4  
  5  
  6  pub fn sign_data_with_dilithium(data: &[u8], dilithium_sk: &oqs::sig::SecretKey) -> Result<String, Box<dyn Error>> {
  7      // Create the signature algorithm instance for Dilithium5
  8      let sigalg = Sig::new(oqs::sig::Algorithm::Dilithium5)?;
  9  
 10      // Sign the data using the secret key
 11      let signature = sigalg.sign(data, dilithium_sk)?;
 12  
 13      // Format the data and signature into a single combined string
 14      let combined = format!(
 15          "{}-----BEGIN SIGNATURE-----\n{}\n-----END SIGNATURE-----",
 16          hex::encode(data), // Data encoded as hex
 17          hex::encode(signature) // Signature encoded as hex
 18      );
 19  
 20      Ok(combined)
 21  }
 22  
 23  pub fn verify_signature_with_dilithium(data: &[u8], dilithium_pk: &oqs::sig::PublicKey) -> Result<bool, Box<dyn Error>> {
 24      // Convert the data to a string for easier processing
 25      let data_str = String::from_utf8_lossy(data);
 26  
 27      // Find the "-----BEGIN SIGNATURE-----" delimiter
 28      let start_pos = data_str.find("-----BEGIN SIGNATURE-----").ok_or("Signature start not found")?;
 29  
 30      // Extract the data before the signature part (i.e., before the "-----BEGIN SIGNATURE-----")
 31      let data_before_signature = &data_str[..start_pos].trim();
 32      
 33      // If the extracted data before the signature is hex-encoded, decode it
 34      let data_bytes = hex::decode(data_before_signature)?;
 35  
 36      // Find the "-----END SIGNATURE-----" delimiter
 37      let end_pos = data_str.find("-----END SIGNATURE-----").ok_or("Signature end not found")?;
 38  
 39      // Extract the signature hex value and decode it
 40      let signature_hex = &data_str[start_pos + "-----BEGIN SIGNATURE-----".len()..end_pos].trim();
 41      let signature_bytes = hex::decode(signature_hex)?;
 42  
 43      // Initialize the Dilithium algorithm for signature verification
 44      let sigalg = Sig::new(oqs::sig::Algorithm::Dilithium5)?;
 45      
 46      // Attempt to convert the signature bytes to a valid signature
 47      let signature_ref = match (&sigalg).signature_from_bytes(&signature_bytes) {
 48          Some(sig) => sig,
 49          None => return Err("Invalid signature".into()),
 50      };
 51  
 52      // Verify the signature using the provided public key
 53      sigalg.verify(&data_bytes, &signature_ref, dilithium_pk)?;
 54  
 55      Ok(true)
 56  }
 57  
 58  pub fn sign_data_with_eddsa(data: &[u8], eddsa_sk: &Ed25519SecretKey) -> Result<String, Box<dyn Error>> {
 59      // Create a SigningKey using the SecretKey
 60      let signing_key = Ed25519PrivateKey::from(*eddsa_sk); // Create SigningKey from SecretKey
 61  
 62      // Sign the raw data using the EdDSA secret key
 63      let signature: Ed25519Signature = signing_key.sign(data);
 64  
 65      // Format the data and signature into a single combined string
 66      let combined = format!(
 67          "{}-----BEGIN SIGNATURE-----\n{}\n-----END SIGNATURE-----",
 68          hex::encode(data), // Hex-encoded data
 69          hex::encode(signature.to_bytes()) // Signature encoded as hex
 70      );
 71  
 72      Ok(combined)
 73  }
 74  
 75  pub fn verify_signature_with_eddsa(signature_with_data: &str, eddsa_pk: &Ed25519PublicKey) -> Result<bool, Box<dyn Error>> {
 76      let start_pos = signature_with_data
 77          .find("-----BEGIN SIGNATURE-----")
 78          .ok_or("Signature start marker not found")?;
 79      let end_pos = signature_with_data
 80          .find("-----END SIGNATURE-----")
 81          .ok_or("Signature end marker not found")?;
 82  
 83      let signature_hex = &signature_with_data[start_pos + "-----BEGIN SIGNATURE-----".len()..end_pos].trim();
 84      let signature_bytes = hex::decode(signature_hex).map_err(|e| format!("Failed to decode signature: {}", e))?;
 85  
 86      let signature_array: &[u8; 64] = signature_bytes
 87          .as_slice()
 88          .try_into()
 89          .map_err(|_| "Signature byte slice is not 64 bytes long")?;
 90  
 91      let signature = Ed25519Signature::from_bytes(signature_array);
 92  
 93      let data_before_signature = &signature_with_data[..start_pos].trim();
 94  
 95      let data_bytes = hex::decode(data_before_signature).map_err(|e| format!("Failed to decode data: {}", e))?;
 96  
 97      // Verify the signature with the original data
 98      let verification_result = eddsa_pk
 99          .verify(&data_bytes, &signature)
100          .map_err(|_| "Signature verification failed");
101  
102      match verification_result {
103          Ok(_) => println!("Signature verification successful."),
104          Err(_) => println!("Signature verification failed."),
105      }
106  
107      verification_result?;
108  
109      Ok(true)
110  }