mirror of https://github.com/breard-r/acmed.git
Browse Source
Create an abstraction around public and private keys
Create an abstraction around public and private keys
Since it is planned to add a "standalone" feature that will replace OpenSSL by crates not linking to any external library, it is required to abstract all the OpenSSL specific types. This is a huge work and therefore is divided in several steps. This first one is dedicated to public and private keys. rel #2pull/5/head
Rodolphe Breard
6 years ago
12 changed files with 309 additions and 213 deletions
-
3acme_common/src/crypto.rs
-
223acme_common/src/crypto/openssl_keys.rs
-
45acme_common/src/gen.rs
-
2acme_common/src/lib.rs
-
16acmed/src/acme_proto/account.rs
-
37acmed/src/acme_proto/certificate.rs
-
48acmed/src/acme_proto/jws.rs
-
80acmed/src/acme_proto/jws/algorithms.rs
-
10acmed/src/acme_proto/structs/authorization.rs
-
31acmed/src/storage.rs
-
17tacd/src/certificate.rs
-
10tacd/src/server.rs
@ -0,0 +1,3 @@ |
|||
mod openssl_keys;
|
|||
pub use openssl_keys::{gen_keypair, KeyType, PrivateKey, PublicKey};
|
|||
pub const DEFAULT_ALGO: &str = "rsa2048";
|
@ -0,0 +1,223 @@ |
|||
use crate::b64_encode;
|
|||
use crate::error::Error;
|
|||
use openssl::bn::{BigNum, BigNumContext};
|
|||
use openssl::ec::{EcGroup, EcKey};
|
|||
use openssl::ecdsa::EcdsaSig;
|
|||
use openssl::nid::Nid;
|
|||
use openssl::pkey::{Id, PKey, Private, Public};
|
|||
use openssl::rsa::Rsa;
|
|||
use serde_json::json;
|
|||
use std::fmt;
|
|||
use std::str::FromStr;
|
|||
|
|||
macro_rules! get_key_type {
|
|||
($key: expr) => {
|
|||
match $key.id() {
|
|||
Id::RSA => match $key.rsa()?.size() {
|
|||
2048 => KeyType::Rsa2048,
|
|||
4096 => KeyType::Rsa4096,
|
|||
s => {
|
|||
return Err(format!("{}: unsupported RSA key size", s).into());
|
|||
}
|
|||
},
|
|||
Id::EC => match $key.ec_key()?.group().curve_name() {
|
|||
Some(Nid::X9_62_PRIME256V1) => KeyType::EcdsaP256,
|
|||
Some(Nid::SECP384R1) => KeyType::EcdsaP384,
|
|||
_ => {
|
|||
return Err("Unsupported EC key".into());
|
|||
}
|
|||
},
|
|||
_ => {
|
|||
return Err("Unsupported key type".into());
|
|||
}
|
|||
}
|
|||
};
|
|||
}
|
|||
|
|||
#[derive(Clone, Copy, Debug)]
|
|||
pub enum KeyType {
|
|||
Rsa2048,
|
|||
Rsa4096,
|
|||
EcdsaP256,
|
|||
EcdsaP384,
|
|||
}
|
|||
|
|||
impl FromStr for KeyType {
|
|||
type Err = Error;
|
|||
|
|||
fn from_str(s: &str) -> Result<Self, Error> {
|
|||
match s.to_lowercase().as_str() {
|
|||
"rsa2048" => Ok(KeyType::Rsa2048),
|
|||
"rsa4096" => Ok(KeyType::Rsa4096),
|
|||
"ecdsa_p256" => Ok(KeyType::EcdsaP256),
|
|||
"ecdsa_p384" => Ok(KeyType::EcdsaP384),
|
|||
_ => Err(format!("{}: unknown algorithm.", s).into()),
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
impl fmt::Display for KeyType {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|||
let s = match self {
|
|||
KeyType::Rsa2048 => "rsa2048",
|
|||
KeyType::Rsa4096 => "rsa4096",
|
|||
KeyType::EcdsaP256 => "ecdsa-p256",
|
|||
KeyType::EcdsaP384 => "ecdsa-p384",
|
|||
};
|
|||
write!(f, "{}", s)
|
|||
}
|
|||
}
|
|||
|
|||
pub struct PublicKey {
|
|||
pub key_type: KeyType,
|
|||
pub inner_key: PKey<Public>,
|
|||
}
|
|||
|
|||
impl PublicKey {
|
|||
pub fn from_pem(pem_data: &[u8]) -> Result<Self, Error> {
|
|||
let inner_key = PKey::public_key_from_pem(pem_data)?;
|
|||
let key_type = get_key_type!(inner_key);
|
|||
Ok(PublicKey {
|
|||
key_type,
|
|||
inner_key,
|
|||
})
|
|||
}
|
|||
|
|||
pub fn to_pem(&self) -> Result<Vec<u8>, Error> {
|
|||
self.inner_key
|
|||
.public_key_to_pem()
|
|||
.map_err(|e| Error::from(e))
|
|||
}
|
|||
}
|
|||
|
|||
pub struct PrivateKey {
|
|||
pub key_type: KeyType,
|
|||
pub inner_key: PKey<Private>,
|
|||
}
|
|||
|
|||
impl PrivateKey {
|
|||
pub fn from_pem(pem_data: &[u8]) -> Result<Self, Error> {
|
|||
let inner_key = PKey::private_key_from_pem(pem_data)?;
|
|||
let key_type = get_key_type!(inner_key);
|
|||
Ok(PrivateKey {
|
|||
key_type,
|
|||
inner_key,
|
|||
})
|
|||
}
|
|||
|
|||
pub fn to_pem(&self) -> Result<Vec<u8>, Error> {
|
|||
self.inner_key
|
|||
.private_key_to_pem_pkcs8()
|
|||
.map_err(|e| Error::from(e))
|
|||
}
|
|||
|
|||
pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
|
|||
match self.key_type {
|
|||
KeyType::Rsa2048 | KeyType::Rsa4096 => {
|
|||
// TODO: implement RSA signatures
|
|||
Err("RSA signatures are not implemented yet".into())
|
|||
}
|
|||
KeyType::EcdsaP256 | KeyType::EcdsaP384 => {
|
|||
let signature = EcdsaSig::sign(data, self.inner_key.ec_key()?.as_ref())?;
|
|||
let r = signature.r().to_vec();
|
|||
let mut s = signature.s().to_vec();
|
|||
let mut signature = r;
|
|||
signature.append(&mut s);
|
|||
Ok(signature)
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
pub fn get_jwk_thumbprint(&self) -> Result<String, Error> {
|
|||
match self.key_type {
|
|||
KeyType::EcdsaP256 | KeyType::EcdsaP384 => self.get_nist_ec_jwk(),
|
|||
// TODO: implement RSA JWK thumbprint
|
|||
KeyType::Rsa2048 | KeyType::Rsa4096 => {
|
|||
Err("RSA jwk thumbprint are not implemented yet".into())
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
fn get_nist_ec_jwk(&self) -> Result<String, Error> {
|
|||
let (x, y) = self.get_nist_ec_coordinates()?;
|
|||
let crv = match self.key_type {
|
|||
KeyType::EcdsaP256 => "P-256",
|
|||
KeyType::EcdsaP384 => "P-384",
|
|||
_ => {
|
|||
return Err("Not a NIST elliptic curve.".into());
|
|||
}
|
|||
};
|
|||
let jwk = json!({
|
|||
"crv": crv,
|
|||
"kty": "EC",
|
|||
"x": x,
|
|||
"y": y,
|
|||
});
|
|||
Ok(jwk.to_string())
|
|||
}
|
|||
|
|||
pub fn get_nist_ec_coordinates(&self) -> Result<(String, String), Error> {
|
|||
let curve = match self.key_type {
|
|||
KeyType::EcdsaP256 => Nid::X9_62_PRIME256V1,
|
|||
KeyType::EcdsaP384 => Nid::SECP384R1,
|
|||
_ => {
|
|||
return Err("Not a NIST elliptic curve.".into());
|
|||
}
|
|||
};
|
|||
let group = EcGroup::from_curve_name(curve).unwrap();
|
|||
let mut ctx = BigNumContext::new().unwrap();
|
|||
let mut x = BigNum::new().unwrap();
|
|||
let mut y = BigNum::new().unwrap();
|
|||
self.inner_key
|
|||
.ec_key()
|
|||
.unwrap()
|
|||
.public_key()
|
|||
.affine_coordinates_gfp(&group, &mut x, &mut y, &mut ctx)?;
|
|||
let x = b64_encode(&x.to_vec());
|
|||
let y = b64_encode(&y.to_vec());
|
|||
Ok((x, y))
|
|||
}
|
|||
}
|
|||
|
|||
fn gen_rsa_pair(nb_bits: u32) -> Result<(PKey<Public>, PKey<Private>), Error> {
|
|||
let priv_key = Rsa::generate(nb_bits).unwrap();
|
|||
let pub_key = Rsa::from_public_components(
|
|||
priv_key.n().to_owned().unwrap(),
|
|||
priv_key.e().to_owned().unwrap(),
|
|||
)
|
|||
.unwrap();
|
|||
Ok((
|
|||
PKey::from_rsa(pub_key).unwrap(),
|
|||
PKey::from_rsa(priv_key).unwrap(),
|
|||
))
|
|||
}
|
|||
|
|||
fn gen_ec_pair(nid: Nid) -> Result<(PKey<Public>, PKey<Private>), Error> {
|
|||
let group = EcGroup::from_curve_name(nid).unwrap();
|
|||
let ec_priv_key = EcKey::generate(&group).unwrap();
|
|||
let public_key_point = ec_priv_key.public_key();
|
|||
let ec_pub_key = EcKey::from_public_key(&group, public_key_point).unwrap();
|
|||
Ok((
|
|||
PKey::from_ec_key(ec_pub_key).unwrap(),
|
|||
PKey::from_ec_key(ec_priv_key).unwrap(),
|
|||
))
|
|||
}
|
|||
|
|||
pub fn gen_keypair(key_type: KeyType) -> Result<(PublicKey, PrivateKey), Error> {
|
|||
let (pub_key, priv_key) = match key_type {
|
|||
KeyType::Rsa2048 => gen_rsa_pair(2048),
|
|||
KeyType::Rsa4096 => gen_rsa_pair(4096),
|
|||
KeyType::EcdsaP256 => gen_ec_pair(Nid::X9_62_PRIME256V1),
|
|||
KeyType::EcdsaP384 => gen_ec_pair(Nid::SECP384R1),
|
|||
}
|
|||
.map_err(|_| Error::from(format!("Unable to generate a {} key pair.", key_type)))?;
|
|||
let pub_key = PublicKey {
|
|||
key_type,
|
|||
inner_key: pub_key,
|
|||
};
|
|||
let priv_key = PrivateKey {
|
|||
key_type,
|
|||
inner_key: priv_key,
|
|||
};
|
|||
Ok((pub_key, priv_key))
|
|||
}
|
@ -1,45 +0,0 @@ |
|||
use crate::error::Error;
|
|||
use openssl::ec::{EcGroup, EcKey};
|
|||
use openssl::nid::Nid;
|
|||
use openssl::pkey::{PKey, Private, Public};
|
|||
use openssl::rsa::Rsa;
|
|||
|
|||
fn gen_ec_pair(nid: Nid) -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
let group = EcGroup::from_curve_name(nid).unwrap();
|
|||
let ec_priv_key = EcKey::generate(&group).unwrap();
|
|||
let public_key_point = ec_priv_key.public_key();
|
|||
let ec_pub_key = EcKey::from_public_key(&group, public_key_point).unwrap();
|
|||
Ok((
|
|||
PKey::from_ec_key(ec_priv_key).unwrap(),
|
|||
PKey::from_ec_key(ec_pub_key).unwrap(),
|
|||
))
|
|||
}
|
|||
|
|||
pub fn p256() -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
gen_ec_pair(Nid::X9_62_PRIME256V1)
|
|||
}
|
|||
|
|||
pub fn p384() -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
gen_ec_pair(Nid::SECP384R1)
|
|||
}
|
|||
|
|||
fn gen_rsa_pair(nb_bits: u32) -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
let priv_key = Rsa::generate(nb_bits).unwrap();
|
|||
let pub_key = Rsa::from_public_components(
|
|||
priv_key.n().to_owned().unwrap(),
|
|||
priv_key.e().to_owned().unwrap(),
|
|||
)
|
|||
.unwrap();
|
|||
Ok((
|
|||
PKey::from_rsa(priv_key).unwrap(),
|
|||
PKey::from_rsa(pub_key).unwrap(),
|
|||
))
|
|||
}
|
|||
|
|||
pub fn rsa2048() -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
gen_rsa_pair(2048)
|
|||
}
|
|||
|
|||
pub fn rsa4096() -> Result<(PKey<Private>, PKey<Public>), Error> {
|
|||
gen_rsa_pair(4096)
|
|||
}
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue