Browse Source

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 #2
pull/5/head
Rodolphe Breard 6 years ago
parent
commit
63e35712fe
  1. 3
      acme_common/src/crypto.rs
  2. 223
      acme_common/src/crypto/openssl_keys.rs
  3. 45
      acme_common/src/gen.rs
  4. 2
      acme_common/src/lib.rs
  5. 16
      acmed/src/acme_proto/account.rs
  6. 37
      acmed/src/acme_proto/certificate.rs
  7. 48
      acmed/src/acme_proto/jws.rs
  8. 80
      acmed/src/acme_proto/jws/algorithms.rs
  9. 10
      acmed/src/acme_proto/structs/authorization.rs
  10. 31
      acmed/src/storage.rs
  11. 17
      tacd/src/certificate.rs
  12. 10
      tacd/src/server.rs

3
acme_common/src/crypto.rs

@ -0,0 +1,3 @@
mod openssl_keys;
pub use openssl_keys::{gen_keypair, KeyType, PrivateKey, PublicKey};
pub const DEFAULT_ALGO: &str = "rsa2048";

223
acme_common/src/crypto/openssl_keys.rs

@ -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))
}

45
acme_common/src/gen.rs

@ -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)
}

2
acme_common/src/lib.rs

@ -1,7 +1,7 @@
use daemonize::Daemonize;
pub mod crypto;
pub mod error;
pub mod gen;
pub mod logs;
pub fn b64_encode<T: ?Sized + AsRef<[u8]>>(input: &T) -> String {

16
acmed/src/acme_proto/account.rs

@ -4,13 +4,13 @@ use crate::acme_proto::jws::encode_jwk;
use crate::acme_proto::structs::{Account, AccountResponse, Directory};
use crate::certificate::Certificate;
use crate::storage;
use acme_common::crypto::{PrivateKey, PublicKey};
use acme_common::error::Error;
use openssl::pkey::{PKey, Private, Public};
use std::str::FromStr;
pub struct AccountManager {
pub priv_key: PKey<Private>,
pub pub_key: PKey<Public>,
pub pub_key: PublicKey,
pub priv_key: PrivateKey,
pub account_url: String,
pub orders_url: String,
}
@ -23,20 +23,20 @@ impl AccountManager {
root_certs: &[String],
) -> Result<(Self, String), Error> {
// TODO: store the key id (account url)
let (priv_key, pub_key) = if storage::account_files_exists(cert) {
let (pub_key, priv_key) = if storage::account_files_exists(cert) {
// TODO: check if the keys are suitable for the specified signature algorithm
// and, if not, initiate a key rollover.
(
storage::get_account_priv_key(cert)?,
storage::get_account_pub_key(cert)?,
storage::get_account_priv_key(cert)?,
)
} else {
// TODO: allow to change the signature algo
let sign_alg = SignatureAlgorithm::from_str(crate::DEFAULT_JWS_SIGN_ALGO)?;
let (priv_key, pub_key) = sign_alg.gen_key_pair()?;
let (pub_key, priv_key) = sign_alg.gen_key_pair()?;
storage::set_account_priv_key(cert, &priv_key)?;
storage::set_account_pub_key(cert, &pub_key)?;
(priv_key, pub_key)
(pub_key, priv_key)
};
let account = Account::new(cert);
let account = serde_json::to_string(&account)?;
@ -50,8 +50,8 @@ impl AccountManager {
&nonce,
)?;
let ac = AccountManager {
priv_key,
pub_key,
priv_key,
account_url,
orders_url: acc_rep.orders.unwrap_or_default(),
};

37
acmed/src/acme_proto/certificate.rs

@ -1,32 +1,33 @@
use crate::certificate::{Algorithm, Certificate};
use crate::storage;
use acme_common::b64_encode;
use acme_common::crypto::{gen_keypair, KeyType, PrivateKey, PublicKey};
use acme_common::error::Error;
use acme_common::{b64_encode, gen};
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Private, Public};
use openssl::stack::Stack;
use openssl::x509::extension::SubjectAlternativeName;
use openssl::x509::X509ReqBuilder;
use serde_json::json;
fn gen_key_pair(cert: &Certificate) -> Result<(PKey<Private>, PKey<Public>), Error> {
let (priv_key, pub_key) = match cert.algo {
Algorithm::Rsa2048 => gen::rsa2048(),
Algorithm::Rsa4096 => gen::rsa4096(),
Algorithm::EcdsaP256 => gen::p256(),
Algorithm::EcdsaP384 => gen::p384(),
}?;
fn gen_key_pair(cert: &Certificate) -> Result<(PublicKey, PrivateKey), Error> {
let key_type = match cert.algo {
Algorithm::Rsa2048 => KeyType::Rsa2048,
Algorithm::Rsa4096 => KeyType::Rsa4096,
Algorithm::EcdsaP256 => KeyType::EcdsaP256,
Algorithm::EcdsaP384 => KeyType::EcdsaP384,
};
let (pub_key, priv_key) = gen_keypair(key_type)?;
storage::set_priv_key(cert, &priv_key)?;
Ok((priv_key, pub_key))
Ok((pub_key, priv_key))
}
fn read_key_pair(cert: &Certificate) -> Result<(PKey<Private>, PKey<Public>), Error> {
let priv_key = storage::get_priv_key(cert)?;
fn read_key_pair(cert: &Certificate) -> Result<(PublicKey, PrivateKey), Error> {
let pub_key = storage::get_pub_key(cert)?;
Ok((priv_key, pub_key))
let priv_key = storage::get_priv_key(cert)?;
Ok((pub_key, priv_key))
}
pub fn get_key_pair(cert: &Certificate) -> Result<(PKey<Private>, PKey<Public>), Error> {
pub fn get_key_pair(cert: &Certificate) -> Result<(PublicKey, PrivateKey), Error> {
if cert.kp_reuse {
match read_key_pair(cert) {
Ok((priv_key, pub_key)) => Ok((priv_key, pub_key)),
@ -39,11 +40,11 @@ pub fn get_key_pair(cert: &Certificate) -> Result<(PKey<Private>, PKey<Public>),
pub fn generate_csr(
cert: &Certificate,
priv_key: &PKey<Private>,
pub_key: &PKey<Public>,
pub_key: &PublicKey,
priv_key: &PrivateKey,
) -> Result<String, Error> {
let mut builder = X509ReqBuilder::new()?;
builder.set_pubkey(pub_key)?;
builder.set_pubkey(&pub_key.inner_key)?;
let ctx = builder.x509v3_context(None);
let mut san = SubjectAlternativeName::new();
for c in cert.domains.iter() {
@ -53,7 +54,7 @@ pub fn generate_csr(
let mut ext_stack = Stack::new()?;
ext_stack.push(san)?;
builder.add_extensions(&ext_stack)?;
builder.sign(priv_key, MessageDigest::sha256())?;
builder.sign(&priv_key.inner_key, MessageDigest::sha256())?;
let csr = builder.build();
let csr = csr.to_der()?;
let csr = b64_encode(&csr);

48
acmed/src/acme_proto/jws.rs

@ -1,8 +1,7 @@
use crate::acme_proto::jws::algorithms::{EdDsaVariant, SignatureAlgorithm};
use acme_common::b64_encode;
use acme_common::crypto::PrivateKey;
use acme_common::error::Error;
use openssl::ecdsa::EcdsaSig;
use openssl::pkey::{PKey, Private};
use openssl::sha::sha256;
use serde::Serialize;
@ -32,37 +31,13 @@ struct JwsProtectedHeaderKid {
url: String,
}
fn es256_sign(data: &[u8], private_key: &PKey<Private>) -> Result<String, Error> {
let signature = EcdsaSig::sign(data, private_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);
let signature = b64_encode(&signature);
Ok(signature)
}
fn eddsa_ed25519_sign(_data: &[u8], _private_key: &PKey<Private>) -> Result<String, Error> {
// TODO: implement eddsa_ed25519_sign
Err("EdDSA not implemented.".into())
}
fn get_data(
private_key: &PKey<Private>,
protected: &str,
payload: &[u8],
sign_alg: SignatureAlgorithm,
) -> Result<String, Error> {
fn get_data(private_key: &PrivateKey, protected: &str, payload: &[u8]) -> Result<String, Error> {
let protected = b64_encode(protected);
let payload = b64_encode(payload);
let signing_input = format!("{}.{}", protected, payload);
let fingerprint = sha256(signing_input.as_bytes());
let signature = match sign_alg {
SignatureAlgorithm::Es256 => es256_sign(&fingerprint, private_key)?,
SignatureAlgorithm::EdDsa(variant) => match variant {
EdDsaVariant::Ed25519 => eddsa_ed25519_sign(&fingerprint, private_key)?,
},
};
let signature = private_key.sign(&fingerprint)?;
let signature = b64_encode(&signature);
let data = JwsData {
protected,
payload,
@ -73,7 +48,7 @@ fn get_data(
}
pub fn encode_jwk(
private_key: &PKey<Private>,
private_key: &PrivateKey,
payload: &[u8],
url: &str,
nonce: &str,
@ -86,11 +61,11 @@ pub fn encode_jwk(
url: url.into(),
};
let protected = serde_json::to_string(&protected)?;
get_data(private_key, &protected, payload, sign_alg)
get_data(private_key, &protected, payload)
}
pub fn encode_kid(
private_key: &PKey<Private>,
private_key: &PrivateKey,
key_id: &str,
payload: &[u8],
url: &str,
@ -104,16 +79,17 @@ pub fn encode_kid(
url: url.into(),
};
let protected = serde_json::to_string(&protected)?;
get_data(private_key, &protected, payload, sign_alg)
get_data(private_key, &protected, payload)
}
#[cfg(test)]
mod tests {
use super::{encode_jwk, encode_kid};
use acme_common::crypto::{gen_keypair, KeyType};
#[test]
fn test_default_jwk() {
let (priv_key, _) = acme_common::gen::p256().unwrap();
let (_, priv_key) = gen_keypair(KeyType::EcdsaP256).unwrap();
let payload = "Dummy payload 1";
let payload_b64 = "RHVtbXkgcGF5bG9hZCAx";
let s = encode_jwk(&priv_key, payload.as_bytes(), "", "");
@ -127,7 +103,7 @@ mod tests {
#[test]
fn test_default_nopad_jwk() {
let (priv_key, _) = acme_common::gen::p256().unwrap();
let (_, priv_key) = gen_keypair(KeyType::EcdsaP256).unwrap();
let payload = "Dummy payload";
let payload_b64 = "RHVtbXkgcGF5bG9hZA";
let payload_b64_pad = "RHVtbXkgcGF5bG9hZA==";
@ -143,7 +119,7 @@ mod tests {
#[test]
fn test_default_kid() {
let (priv_key, _) = acme_common::gen::p256().unwrap();
let (_, priv_key) = gen_keypair(KeyType::EcdsaP256).unwrap();
let payload = "Dummy payload 1";
let payload_b64 = "RHVtbXkgcGF5bG9hZCAx";
let key_id = "0x2a";

80
acmed/src/acme_proto/jws/algorithms.rs

@ -1,11 +1,6 @@
use super::jwk::{EdDsaEd25519Jwk, Es256Jwk, Jwk};
use acme_common::crypto::{gen_keypair, KeyType, PrivateKey, PublicKey};
use acme_common::error::Error;
use acme_common::{b64_encode, gen};
use openssl::bn::{BigNum, BigNumContext};
use openssl::ec::EcGroup;
use openssl::nid::Nid;
use openssl::pkey::{Id, PKey, Private, Public};
use serde_json::json;
use std::fmt;
use std::str::FromStr;
@ -52,71 +47,22 @@ impl FromStr for SignatureAlgorithm {
}
impl SignatureAlgorithm {
pub fn from_pkey(private_key: &PKey<Private>) -> Result<Self, Error> {
match private_key.id() {
Id::EC => match private_key.ec_key()?.group().curve_name() {
Some(nid) => {
if nid == Nid::X9_62_PRIME256V1 {
Ok(SignatureAlgorithm::Es256)
// TODO: add support for Ed25519 keys
} else {
Err(format!("{}: unsupported EC key type", nid.as_raw()).into())
pub fn from_pkey(private_key: &PrivateKey) -> Result<Self, Error> {
match private_key.key_type {
KeyType::EcdsaP256 => Ok(SignatureAlgorithm::Es256),
t => Err(format!("{}: unsupported key type", t).into()),
}
}
None => Err("EC curve: name not found".into()),
},
_ => Err(format!("{}: unsupported key id", private_key.id().as_raw()).into()),
}
}
fn get_p256_coordinates(private_key: &PKey<Private>) -> Result<(String, String), Error> {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let mut ctx = BigNumContext::new().unwrap();
let mut x = BigNum::new().unwrap();
let mut y = BigNum::new().unwrap();
private_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))
}
pub fn get_jwk_thumbprint(&self, private_key: &PKey<Private>) -> Result<String, Error> {
let jwk = match self {
SignatureAlgorithm::Es256 => {
let (x, y) = SignatureAlgorithm::get_p256_coordinates(private_key)?;
json!({
"crv": "P-256",
"kty": "EC",
"x": x,
"y": y,
})
}
SignatureAlgorithm::EdDsa(_crv) => json!({
// TODO: implement EdDsa
}),
};
Ok(jwk.to_string())
}
pub fn get_jwk(&self, private_key: &PKey<Private>) -> Result<Jwk, Error> {
let jwk = match self {
SignatureAlgorithm::Es256 => {
let (x, y) = SignatureAlgorithm::get_p256_coordinates(private_key)?;
Jwk::Es256(Es256Jwk::new(&x, &y))
}
// TODO: implement EdDsa
SignatureAlgorithm::EdDsa(_crv) => Jwk::EdDsaEd25519(EdDsaEd25519Jwk::new()),
};
pub fn get_jwk(&self, private_key: &PrivateKey) -> Result<Jwk, Error> {
let (x, y) = private_key.get_nist_ec_coordinates()?;
let jwk = Jwk::Es256(Es256Jwk::new(&x, &y));
Ok(jwk)
}
pub fn gen_key_pair(&self) -> Result<(PKey<Private>, PKey<Public>), Error> {
pub fn gen_key_pair(&self) -> Result<(PublicKey, PrivateKey), Error> {
match self {
SignatureAlgorithm::Es256 => gen::p256(),
SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256),
SignatureAlgorithm::EdDsa(EdDsaVariant::Ed25519) => Err("Not implemented".into()),
}
}
@ -125,8 +71,7 @@ impl SignatureAlgorithm {
#[cfg(test)]
mod tests {
use super::{EdDsaVariant, SignatureAlgorithm};
use openssl::ec::EcKey;
use openssl::pkey::PKey;
use acme_common::crypto::PrivateKey;
use std::str::FromStr;
#[test]
@ -170,8 +115,7 @@ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg6To1BW8qTehGhPca
0eMcW8iQU4yA02dvtKkuqfny4HChRANCAAQwxx+j3wYGzD5LSFNBTLlT7J+7rWrq
4BGdR8705iwpBeOQgMpLj+9vuFutlVtmoYpJSYa9+49Hxz8aCe1AQeWt
-----END PRIVATE KEY-----";
let ek = EcKey::private_key_from_pem(pem).unwrap();
let k = PKey::from_ec_key(ek).unwrap();
let k = PrivateKey::from_pem(pem).unwrap();
let s = SignatureAlgorithm::from_pkey(&k);
assert!(s.is_ok());
let s = s.unwrap();

10
acmed/src/acme_proto/structs/authorization.rs

@ -1,8 +1,7 @@
use crate::acme_proto::jws::algorithms::SignatureAlgorithm;
use crate::acme_proto::structs::{ApiError, HttpApiError, Identifier};
use acme_common::b64_encode;
use acme_common::crypto::PrivateKey;
use acme_common::error::Error;
use openssl::pkey::{PKey, Private};
use openssl::sha::sha256;
use serde::Deserialize;
use std::fmt;
@ -94,7 +93,7 @@ impl Challenge {
}
}
pub fn get_proof(&self, private_key: &PKey<Private>) -> Result<String, Error> {
pub fn get_proof(&self, private_key: &PrivateKey) -> Result<String, Error> {
match self {
Challenge::Http01(tc) => tc.key_authorization(private_key),
Challenge::Dns01(tc) => {
@ -156,9 +155,8 @@ pub struct TokenChallenge {
}
impl TokenChallenge {
fn key_authorization(&self, private_key: &PKey<Private>) -> Result<String, Error> {
let sa = SignatureAlgorithm::from_pkey(private_key)?;
let thumbprint = sa.get_jwk_thumbprint(private_key)?;
fn key_authorization(&self, private_key: &PrivateKey) -> Result<String, Error> {
let thumbprint = private_key.get_jwk_thumbprint()?;
let thumbprint = sha256(thumbprint.as_bytes());
let thumbprint = b64_encode(&thumbprint);
let auth = format!("{}.{}", self.token, thumbprint);

31
acmed/src/storage.rs

@ -2,8 +2,8 @@ use crate::certificate::Certificate;
use crate::config::HookType;
use crate::hooks::{self, FileStorageHookData, HookEnvData};
use acme_common::b64_encode;
use acme_common::crypto::{PrivateKey, PublicKey};
use acme_common::error::Error;
use openssl::pkey::{PKey, Private, Public};
use openssl::x509::X509;
use std::collections::HashMap;
use std::fmt;
@ -175,44 +175,45 @@ fn write_file(cert: &Certificate, file_type: FileType, data: &[u8]) -> Result<()
Ok(())
}
pub fn get_account_priv_key(cert: &Certificate) -> Result<PKey<Private>, Error> {
pub fn get_account_priv_key(cert: &Certificate) -> Result<PrivateKey, Error> {
let path = get_file_path(cert, FileType::AccountPrivateKey)?;
let raw_key = read_file(cert, &path)?;
let key = PKey::private_key_from_pem(&raw_key)?;
let key = PrivateKey::from_pem(&raw_key)?;
Ok(key)
}
pub fn set_account_priv_key(cert: &Certificate, key: &PKey<Private>) -> Result<(), Error> {
let data = key.private_key_to_pem_pkcs8()?;
pub fn set_account_priv_key(cert: &Certificate, key: &PrivateKey) -> Result<(), Error> {
let data = key.to_pem()?;
write_file(cert, FileType::AccountPrivateKey, &data)
}
pub fn get_account_pub_key(cert: &Certificate) -> Result<PKey<Public>, Error> {
pub fn get_account_pub_key(cert: &Certificate) -> Result<PublicKey, Error> {
let path = get_file_path(cert, FileType::AccountPublicKey)?;
let raw_key = read_file(cert, &path)?;
let key = PKey::public_key_from_pem(&raw_key)?;
let key = PublicKey::from_pem(&raw_key)?;
Ok(key)
}
pub fn set_account_pub_key(cert: &Certificate, key: &PKey<Public>) -> Result<(), Error> {
let data = key.public_key_to_pem()?;
pub fn set_account_pub_key(cert: &Certificate, key: &PublicKey) -> Result<(), Error> {
let data = key.to_pem()?;
write_file(cert, FileType::AccountPublicKey, &data)
}
pub fn get_priv_key(cert: &Certificate) -> Result<PKey<Private>, Error> {
pub fn get_priv_key(cert: &Certificate) -> Result<PrivateKey, Error> {
let path = get_file_path(cert, FileType::PrivateKey)?;
let raw_key = read_file(cert, &path)?;
let key = PKey::private_key_from_pem(&raw_key)?;
let key = PrivateKey::from_pem(&raw_key)?;
Ok(key)
}
pub fn set_priv_key(cert: &Certificate, key: &PKey<Private>) -> Result<(), Error> {
let data = key.private_key_to_pem_pkcs8()?;
pub fn set_priv_key(cert: &Certificate, key: &PrivateKey) -> Result<(), Error> {
let data = key.to_pem()?;
write_file(cert, FileType::PrivateKey, &data)
}
pub fn get_pub_key(cert: &Certificate) -> Result<PKey<Public>, Error> {
let pub_key = get_certificate(cert)?.public_key()?;
pub fn get_pub_key(cert: &Certificate) -> Result<PublicKey, Error> {
let raw_key = get_certificate(cert)?.public_key()?.public_key_to_pem()?;
let pub_key = PublicKey::from_pem(&raw_key)?;
Ok(pub_key)
}

17
tacd/src/certificate.rs

@ -1,9 +1,8 @@
use acme_common::crypto::{gen_keypair, KeyType, PrivateKey, PublicKey};
use acme_common::error::Error;
use acme_common::gen;
use openssl::asn1::Asn1Time;
use openssl::bn::{BigNum, MsbOption};
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Private, Public};
use openssl::x509::extension::{BasicConstraints, SubjectAlternativeName};
use openssl::x509::{X509Builder, X509Extension, X509NameBuilder, X509};
@ -14,8 +13,8 @@ const INVALID_EXT_MSG: &str = "Invalid acmeIdentifier extension.";
fn get_certificate(
domain: &str,
private_key: &PKey<Private>,
public_key: &PKey<Public>,
public_key: &PublicKey,
private_key: &PrivateKey,
acme_ext: &str,
) -> Result<X509, Error> {
let mut x509_name = X509NameBuilder::new()?;
@ -34,7 +33,7 @@ fn get_certificate(
builder.set_serial_number(&serial_number)?;
builder.set_subject_name(&x509_name)?;
builder.set_issuer_name(&x509_name)?;
builder.set_pubkey(public_key)?;
builder.set_pubkey(&public_key.inner_key)?;
let not_before = Asn1Time::days_from_now(0)?;
builder.set_not_before(&not_before)?;
let not_after = Asn1Time::days_from_now(CRT_NB_DAYS_VALIDITY)?;
@ -57,13 +56,13 @@ fn get_certificate(
builder
.append_extension(acme_ext)
.map_err(|_| Error::from(INVALID_EXT_MSG))?;
builder.sign(private_key, MessageDigest::sha256())?;
builder.sign(&private_key.inner_key, MessageDigest::sha256())?;
let cert = builder.build();
Ok(cert)
}
pub fn gen_certificate(domain: &str, acme_ext: &str) -> Result<(PKey<Private>, X509), Error> {
let (priv_key, pub_key) = gen::p256()?;
let cert = get_certificate(domain, &priv_key, &pub_key, acme_ext)?;
pub fn gen_certificate(domain: &str, acme_ext: &str) -> Result<(PrivateKey, X509), Error> {
let (pub_key, priv_key) = gen_keypair(KeyType::EcdsaP256)?;
let cert = get_certificate(domain, &pub_key, &priv_key, acme_ext)?;
Ok((priv_key, cert))
}

10
tacd/src/server.rs

@ -1,6 +1,6 @@
use acme_common::crypto::PrivateKey;
use acme_common::error::Error;
use log::debug;
use openssl::pkey::{PKey, Private};
use openssl::ssl::{self, AlpnError, SslAcceptor, SslMethod};
use openssl::x509::X509;
use std::net::TcpListener;
@ -30,17 +30,13 @@ macro_rules! listen_and_accept {
};
}
pub fn start(
listen_addr: &str,
certificate: &X509,
private_key: &PKey<Private>,
) -> Result<(), Error> {
pub fn start(listen_addr: &str, certificate: &X509, private_key: &PrivateKey) -> Result<(), Error> {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
acceptor.set_alpn_select_callback(|_, client| {
debug!("ALPN negociation");
ssl::select_next_proto(crate::ALPN_ACME_PROTO_NAME, client).ok_or(ALPN_ERROR)
});
acceptor.set_private_key(private_key)?;
acceptor.set_private_key(&private_key.inner_key)?;
acceptor.set_certificate(certificate)?;
acceptor.check_private_key()?;
let acceptor = Arc::new(acceptor.build());

Loading…
Cancel
Save