extern crate openssl;
use std::str;
use openssl::ec::{EcGroup, EcKey};
use openssl::nid::Nid;
use openssl::pkey::{PKey, Private};
use crate::key::Pkcs8pem;
use super::error::{KeyError, KeyResult};
#[path = "int_def.rs"]
mod int_def;
use int_def::{Pkcs8pemBytes, Signing};
#[derive(Clone)]
pub struct EllipticCurve {
pub name: String,
pkcs8pem: Pkcs8pemBytes,
}
impl EllipticCurve {
pub fn new(name: &str) -> KeyResult<EllipticCurve> {
let pkcs8pem = EllipticCurve::generate()?;
Ok(EllipticCurve {
name: String::from(name),
pkcs8pem,
})
}
pub fn create_from_pem(name: &str, pem: &Pkcs8pem) -> EllipticCurve {
let pkcs8pem = Pkcs8pemBytes::new(
pem.private.to_string().as_bytes(),
pem.public.to_string().as_bytes(),
);
EllipticCurve {
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 verified = Signing::verify(&keypair, &data, &signature)?;
Ok(verified)
}
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 EllipticCurve {
fn generate() -> KeyResult<Pkcs8pemBytes> {
let ec_group = match EcGroup::from_curve_name(Nid::SECP256K1) {
Ok(group) => group,
Err(_) => return Err(KeyError::GenerationError(1000)),
};
let ec_key = match EcKey::generate(&ec_group) {
Ok(key) => key,
Err(_) => return Err(KeyError::GenerationError(1001)),
};
let pkey = match PKey::from_ec_key(ec_key) {
Ok(pkey) => pkey,
Err(_) => return Err(KeyError::GenerationError(1001)),
};
let mut pkcs8pem = Pkcs8pemBytes::new(&vec![], &vec![]);
pkcs8pem.private = match pkey.private_key_to_pem_pkcs8() {
Ok(bytes) => bytes,
Err(_) => return Err(KeyError::GenerationError(1002)),
};
pkcs8pem.public = match pkey.public_key_to_pem() {
Ok(bytes) => bytes,
Err(_) => return Err(KeyError::GenerationError(1003)),
};
Ok(pkcs8pem)
}
fn get_keypair(&self) -> KeyResult<PKey<Private>> {
let keypair = match EcKey::private_key_from_pem(&self.pkcs8pem.private) {
Ok(keypair) => keypair,
Err(_) => return Err(KeyError::SigningError(2007)),
};
let keypair = match PKey::from_ec_key(keypair) {
Ok(keypair) => keypair,
Err(_) => return Err(KeyError::SigningError(2008)),
};
Ok(keypair)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn ec_gen() {
use std::time::Instant;
let start = Instant::now();
let key = EllipticCurve::new("Test").unwrap();
let duration = start.elapsed();
println!("EC generated in {:?}", duration);
let string = key.get_pem().unwrap();
println!("Key pub: {:?}", string.public);
println!("Key prv: {:?}", string.private);
}
#[test]
fn ec_sign() {
let data_to_sign = String::from("Test data");
let key = EllipticCurve::new("Test").unwrap();
let signature = key.sign(&data_to_sign).unwrap();
println!("EC Sig: {}", signature);
println!(
"Verification: {:?}",
key.verify(&data_to_sign, &signature).unwrap()
);
assert!(key.verify(&data_to_sign, &signature).unwrap());
}
}