From 55f4d3416b192a200550089ed02601e38a36ca75 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Sat, 29 Jun 2019 13:33:53 +0200 Subject: [PATCH 1/5] Refactor the JWK implementation --- acme_common/src/crypto/openssl_keys.rs | 59 +++++++++++-------- acmed/src/acme_proto/structs/authorization.rs | 4 +- acmed/src/jws.rs | 6 +- acmed/src/jws/algorithms.rs | 7 --- acmed/src/jws/jwk.rs | 31 ---------- 5 files changed, 38 insertions(+), 69 deletions(-) delete mode 100644 acmed/src/jws/jwk.rs diff --git a/acme_common/src/crypto/openssl_keys.rs b/acme_common/src/crypto/openssl_keys.rs index 9e6ca39..368c4ce 100644 --- a/acme_common/src/crypto/openssl_keys.rs +++ b/acme_common/src/crypto/openssl_keys.rs @@ -8,6 +8,7 @@ use openssl::nid::Nid; use openssl::pkey::{Id, PKey, Private}; use openssl::rsa::Rsa; use serde_json::json; +use serde_json::value::Value; macro_rules! get_key_type { ($key: expr) => { @@ -76,39 +77,28 @@ impl KeyPair { } } - pub fn get_jwk_thumbprint(&self) -> Result { - // TODO: implement Curve25519 and RSA JWK thumbprint + pub fn jwk_public_key(&self) -> Result { + self.get_jwk_public_key(false) + } + + pub fn jwk_public_key_thumbprint(&self) -> Result { + self.get_jwk_public_key(true) + } + + fn get_jwk_public_key(&self, thumbprint: bool) -> Result { match self.key_type { KeyType::Curve25519 => Err("Curve25519 thumbprint are not implemented yet".into()), - KeyType::EcdsaP256 | KeyType::EcdsaP384 => self.get_nist_ec_jwk(), + KeyType::EcdsaP256 | KeyType::EcdsaP384 => self.get_nist_ec_jwk(thumbprint), KeyType::Rsa2048 | KeyType::Rsa4096 => { Err("RSA jwk thumbprint are not implemented yet".into()) } } } - fn get_nist_ec_jwk(&self) -> Result { - 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, + fn get_nist_ec_jwk(&self, thumbprint: bool) -> Result { + let (crv, curve) = match self.key_type { + KeyType::EcdsaP256 => ("P-256", Nid::X9_62_PRIME256V1), + KeyType::EcdsaP384 => ("P-384", Nid::SECP384R1), _ => { return Err("Not a NIST elliptic curve.".into()); } @@ -124,7 +114,24 @@ impl KeyPair { .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)) + let jwk = if thumbprint { + json!({ + "crv": crv, + "kty": "EC", + "x": x, + "y": y, + }) + } else { + json!({ + "alg": "ES256", + "crv": crv, + "kty": "EC", + "use": "sig", + "x": x, + "y": y, + }) + }; + Ok(jwk) } } diff --git a/acmed/src/acme_proto/structs/authorization.rs b/acmed/src/acme_proto/structs/authorization.rs index 656129d..42b69b5 100644 --- a/acmed/src/acme_proto/structs/authorization.rs +++ b/acmed/src/acme_proto/structs/authorization.rs @@ -155,8 +155,8 @@ pub struct TokenChallenge { impl TokenChallenge { fn key_authorization(&self, key_pair: &KeyPair) -> Result { - let thumbprint = key_pair.get_jwk_thumbprint()?; - let thumbprint = sha256(thumbprint.as_bytes()); + let thumbprint = key_pair.jwk_public_key_thumbprint()?; + let thumbprint = sha256(thumbprint.to_string().as_bytes()); let thumbprint = b64_encode(&thumbprint); let auth = format!("{}.{}", self.token, thumbprint); Ok(auth) diff --git a/acmed/src/jws.rs b/acmed/src/jws.rs index 31617d4..3638cab 100644 --- a/acmed/src/jws.rs +++ b/acmed/src/jws.rs @@ -3,9 +3,9 @@ use acme_common::b64_encode; use acme_common::crypto::{sha256, KeyPair}; use acme_common::error::Error; use serde::Serialize; +use serde_json::value::Value; pub mod algorithms; -mod jwk; #[derive(Serialize)] struct JwsData { @@ -17,7 +17,7 @@ struct JwsData { #[derive(Serialize)] struct JwsProtectedHeaderJwk { alg: String, - jwk: jwk::Jwk, + jwk: Value, nonce: String, url: String, } @@ -55,7 +55,7 @@ pub fn encode_jwk( let sign_alg = SignatureAlgorithm::from_pkey(key_pair)?; let protected = JwsProtectedHeaderJwk { alg: sign_alg.to_string(), - jwk: sign_alg.get_jwk(key_pair)?, + jwk: key_pair.jwk_public_key()?, nonce: nonce.into(), url: url.into(), }; diff --git a/acmed/src/jws/algorithms.rs b/acmed/src/jws/algorithms.rs index aed4ffd..fa04648 100644 --- a/acmed/src/jws/algorithms.rs +++ b/acmed/src/jws/algorithms.rs @@ -1,4 +1,3 @@ -use super::jwk::{Es256Jwk, Jwk}; use acme_common::crypto::{gen_keypair, KeyPair, KeyType}; use acme_common::error::Error; use std::fmt; @@ -37,12 +36,6 @@ impl SignatureAlgorithm { } } - pub fn get_jwk(&self, key_pair: &KeyPair) -> Result { - let (x, y) = key_pair.get_nist_ec_coordinates()?; - let jwk = Jwk::Es256(Es256Jwk::new(&x, &y)); - Ok(jwk) - } - pub fn gen_key_pair(&self) -> Result { match self { SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256), diff --git a/acmed/src/jws/jwk.rs b/acmed/src/jws/jwk.rs deleted file mode 100644 index 7448bf3..0000000 --- a/acmed/src/jws/jwk.rs +++ /dev/null @@ -1,31 +0,0 @@ -use serde::Serialize; - -#[derive(Serialize)] -#[serde(untagged)] -pub enum Jwk { - Es256(Es256Jwk), -} - -#[derive(Serialize)] -pub struct Es256Jwk { - kty: String, - #[serde(rename = "use")] - jwk_use: String, - crv: String, - alg: String, - x: String, - y: String, -} - -impl Es256Jwk { - pub fn new(x: &str, y: &str) -> Self { - Es256Jwk { - kty: "EC".into(), - jwk_use: "sig".into(), - crv: "P-256".into(), - alg: "ES256".into(), - x: x.to_string(), - y: y.to_string(), - } - } -} From 3ccfc9e327263111ec2f2d1152c9b212921a3d1a Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Sat, 29 Jun 2019 13:48:54 +0200 Subject: [PATCH 2/5] Use the HookType enum from the hook module --- acmed/src/certificate.rs | 4 ++-- acmed/src/hooks.rs | 2 +- acmed/src/storage.rs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/acmed/src/certificate.rs b/acmed/src/certificate.rs index 1e86921..6a67b13 100644 --- a/acmed/src/certificate.rs +++ b/acmed/src/certificate.rs @@ -1,6 +1,6 @@ use crate::acme_proto::Challenge; -use crate::config::{Account, Domain, HookType}; -use crate::hooks::{self, ChallengeHookData, Hook, HookEnvData, PostOperationHookData}; +use crate::config::{Account, Domain}; +use crate::hooks::{self, ChallengeHookData, Hook, HookEnvData, HookType, PostOperationHookData}; use crate::storage::{certificate_files_exists, get_certificate}; use acme_common::crypto::X509Certificate; use acme_common::error::Error; diff --git a/acmed/src/hooks.rs b/acmed/src/hooks.rs index e5ca0aa..ad7e5c3 100644 --- a/acmed/src/hooks.rs +++ b/acmed/src/hooks.rs @@ -1,5 +1,5 @@ use crate::certificate::Certificate; -use crate::config::HookType; +pub use crate::config::HookType; use acme_common::error::Error; use handlebars::Handlebars; use serde::Serialize; diff --git a/acmed/src/storage.rs b/acmed/src/storage.rs index 2f17de8..6acad59 100644 --- a/acmed/src/storage.rs +++ b/acmed/src/storage.rs @@ -1,6 +1,5 @@ use crate::certificate::Certificate; -use crate::config::HookType; -use crate::hooks::{self, FileStorageHookData, HookEnvData}; +use crate::hooks::{self, FileStorageHookData, HookEnvData, HookType}; use acme_common::b64_encode; use acme_common::crypto::{KeyPair, X509Certificate}; use acme_common::error::Error; From b1c3d9d5da4c252860da0321256b293169d876b8 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Sat, 29 Jun 2019 14:20:23 +0200 Subject: [PATCH 3/5] Add Curve 25519 support to the CONTRIBUTING file --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a56356..62b840b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,10 @@ The [openssl](https://crates.io/crates/openssl) crate does not expose the Asn1Ti - https://github.com/sfackler/rust-openssl/issues/687 - https://github.com/sfackler/rust-openssl/pull/673 +An other improvement that would be appreciable is to add Curve 25519 support. + +- https://github.com/sfackler/rust-openssl/issues/947 + ## Improving the code From bdb0dcd05f6f6f2672b5ae05f334c37c9141b606 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Fri, 5 Jul 2019 11:53:41 +0200 Subject: [PATCH 4/5] Update the change log --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e04729..6f2d362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed +- A race condition when requesting multiple certificates on the same non-existent account has been fixed. + + ## [0.6.0] - 2019-06-05 ### Added From 405386e5a44645f17064f490d9de96afd0a081f6 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Wed, 31 Jul 2019 12:01:45 +0200 Subject: [PATCH 5/5] Prevent the crates from being published to a registry This project provides binaries without any link to Rust or Cargo. It is just normal binaries that appears to be written in Rust. Therefore, it does not makes any sense to distribute them in a Rust-specific registry. Furthermore, such publication would not include the man pages installation may not respect some distribution-specific policies. --- acme_common/Cargo.toml | 1 + acmed/Cargo.toml | 1 + tacd/Cargo.toml | 1 + 3 files changed, 3 insertions(+) diff --git a/acme_common/Cargo.toml b/acme_common/Cargo.toml index e5ba571..dc42e97 100644 --- a/acme_common/Cargo.toml +++ b/acme_common/Cargo.toml @@ -7,6 +7,7 @@ repository = "https://github.com/breard-r/libreauth" readme = "../README.md" license = "MIT OR Apache-2.0" include = ["src/**/*", "Cargo.toml", "Licence_*.txt"] +publish = false [lib] name = "acme_common" diff --git a/acmed/Cargo.toml b/acmed/Cargo.toml index 52a964f..9917ec0 100644 --- a/acmed/Cargo.toml +++ b/acmed/Cargo.toml @@ -10,6 +10,7 @@ readme = "../README.md" license = "MIT OR Apache-2.0" include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"] build = "build.rs" +publish = false [dependencies] acme_common = { path = "../acme_common" } diff --git a/tacd/Cargo.toml b/tacd/Cargo.toml index c443c40..37276d7 100644 --- a/tacd/Cargo.toml +++ b/tacd/Cargo.toml @@ -9,6 +9,7 @@ repository = "https://github.com/breard-r/acmed" readme = "../README.md" license = "MIT OR Apache-2.0" include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"] +publish = false [dependencies] acme_common = { path = "../acme_common" }