extern crate openssl;
use std::str;
use openssl::pkey::{PKey, Private};
use openssl::rsa::Rsa as openssl_rsa;
use crate::key::Pkcs8pem;
use super::{KeyError, KeyResult};
#[path = "int_def.rs"]
mod int_def;
use int_def::{Pkcs8pemBytes, Signing};
#[derive(Clone)]
pub struct RSA {
pub name: String,
pkcs8pem: Pkcs8pemBytes,
}
impl RSA {
pub fn new(name: &str) -> KeyResult<RSA> {
let pkcs8pem = match RSA::generate() {
Ok(pem) => pem,
Err(error) => return Err(error),
};
Ok(RSA {
name: String::from(name),
pkcs8pem,
})
}
pub fn create_from_pem(name: &str, pem: &Pkcs8pem) -> RSA {
let pkcs8pem = Pkcs8pemBytes::new(
pem.private.to_string().as_bytes(),
pem.public.to_string().as_bytes(),
);
RSA {
name: String::from(name),
pkcs8pem,
}
}
pub fn sign(&self, data: &str) -> KeyResult<String> {
let keypair = self.get_keypair()?;
let signature = Signing::sign(&keypair, &data)?;
Ok(signature)
}
pub fn verify(&self, data: &str, signature: &str) -> KeyResult<bool> {
let keypair = self.get_keypair()?;
let verification = Signing::verify(&keypair, &data, &signature)?;
Ok(verification)
}
pub fn get_pem(&self) -> KeyResult<Pkcs8pem> {
let private_pem = match str::from_utf8(&self.pkcs8pem.private) {
Ok(pem) => pem,
Err(_) => return Err(KeyError::StringifyError(3000)),
};
let public_pem = match str::from_utf8(&self.pkcs8pem.public) {
Ok(pem) => pem,
Err(_) => return Err(KeyError::StringifyError(3001)),
};
Ok(Pkcs8pem {
private: private_pem.to_string(),
public: public_pem.to_string(),
})
}
}
impl RSA {
fn generate() -> KeyResult<Pkcs8pemBytes> {
let rsa = match openssl_rsa::generate(2048) {
Ok(rsa) => rsa,
Err(_) => return Err(KeyError::GenerationError(1004)),
};
let private = match rsa.private_key_to_pem() {
Ok(bytes) => bytes,
Err(_) => return Err(KeyError::GenerationError(1005)),
};
let public = match rsa.public_key_to_pem() {
Ok(bytes) => bytes,
Err(_) => return Err(KeyError::GenerationError(1006)),
};
Ok(Pkcs8pemBytes::new(&private, &public))
}
fn get_keypair(&self) -> KeyResult<PKey<Private>> {
let keypair = match openssl_rsa::private_key_from_pem(&self.pkcs8pem.private) {
Ok(keypair) => keypair,
Err(_) => return Err(KeyError::SigningError(2007)),
};
let keypair = match PKey::from_rsa(keypair) {
Ok(keypair) => keypair,
Err(_) => return Err(KeyError::SigningError(2008)),
};
Ok(keypair)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rsa_gen() {
use std::time::Instant;
let start = Instant::now();
let key = RSA::new("Test").unwrap();
let duration = start.elapsed();
let start2 = Instant::now();
let pem = key.get_pem().unwrap();
let duration_of_pem_stringification = start2.elapsed();
let overall_duration = start.elapsed();
println!(
"Private PEM: \n{}\n Public PEM: \n{}\n",
pem.private, pem.public
);
println!("RSA Generation time: {:?}", duration);
println!(
"RSA PEM stringification time: {:?}",
duration_of_pem_stringification
);
println!("RSA Overall time: {:?}", overall_duration);
}
#[test]
fn rsa_sign() {
let sig_data = String::from("I am test data");
let key = RSA::new("Test").unwrap();
let signature = key.sign(&sig_data).unwrap();
println!("Sig {}", signature);
println!(
"Verification: {:?}",
key.verify(&sig_data, &signature).unwrap()
);
assert!(key.verify(&sig_data, &signature).unwrap());
}
}