Browse Source

Merge branch 'master' of github.com:breard-r/acmed

pull/10/head
Rodolphe Breard 5 years ago
parent
commit
83e137c61b
  1. 6
      CHANGELOG.md
  2. 4
      CONTRIBUTING.md
  3. 1
      acme_common/Cargo.toml
  4. 59
      acme_common/src/crypto/openssl_keys.rs
  5. 1
      acmed/Cargo.toml
  6. 4
      acmed/src/acme_proto/structs/authorization.rs
  7. 4
      acmed/src/certificate.rs
  8. 2
      acmed/src/hooks.rs
  9. 6
      acmed/src/jws.rs
  10. 7
      acmed/src/jws/algorithms.rs
  11. 31
      acmed/src/jws/jwk.rs
  12. 3
      acmed/src/storage.rs
  13. 1
      tacd/Cargo.toml

6
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). 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 ## [0.6.0] - 2019-06-05
### Added ### Added

4
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/issues/687
- https://github.com/sfackler/rust-openssl/pull/673 - 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 ## Improving the code

1
acme_common/Cargo.toml

@ -7,6 +7,7 @@ repository = "https://github.com/breard-r/libreauth"
readme = "../README.md" readme = "../README.md"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
include = ["src/**/*", "Cargo.toml", "Licence_*.txt"] include = ["src/**/*", "Cargo.toml", "Licence_*.txt"]
publish = false
[lib] [lib]
name = "acme_common" name = "acme_common"

59
acme_common/src/crypto/openssl_keys.rs

@ -8,6 +8,7 @@ use openssl::nid::Nid;
use openssl::pkey::{Id, PKey, Private}; use openssl::pkey::{Id, PKey, Private};
use openssl::rsa::Rsa; use openssl::rsa::Rsa;
use serde_json::json; use serde_json::json;
use serde_json::value::Value;
macro_rules! get_key_type { macro_rules! get_key_type {
($key: expr) => { ($key: expr) => {
@ -76,39 +77,28 @@ impl KeyPair {
} }
} }
pub fn get_jwk_thumbprint(&self) -> Result<String, Error> {
// TODO: implement Curve25519 and RSA JWK thumbprint
pub fn jwk_public_key(&self) -> Result<Value, Error> {
self.get_jwk_public_key(false)
}
pub fn jwk_public_key_thumbprint(&self) -> Result<Value, Error> {
self.get_jwk_public_key(true)
}
fn get_jwk_public_key(&self, thumbprint: bool) -> Result<Value, Error> {
match self.key_type { match self.key_type {
KeyType::Curve25519 => Err("Curve25519 thumbprint are not implemented yet".into()), 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 => { KeyType::Rsa2048 | KeyType::Rsa4096 => {
Err("RSA jwk thumbprint are not implemented yet".into()) 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,
fn get_nist_ec_jwk(&self, thumbprint: bool) -> Result<Value, Error> {
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()); return Err("Not a NIST elliptic curve.".into());
} }
@ -124,7 +114,24 @@ impl KeyPair {
.affine_coordinates_gfp(&group, &mut x, &mut y, &mut ctx)?; .affine_coordinates_gfp(&group, &mut x, &mut y, &mut ctx)?;
let x = b64_encode(&x.to_vec()); let x = b64_encode(&x.to_vec());
let y = b64_encode(&y.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)
} }
} }

1
acmed/Cargo.toml

@ -10,6 +10,7 @@ readme = "../README.md"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"] include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"]
build = "build.rs" build = "build.rs"
publish = false
[dependencies] [dependencies]
acme_common = { path = "../acme_common" } acme_common = { path = "../acme_common" }

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

@ -155,8 +155,8 @@ pub struct TokenChallenge {
impl TokenChallenge { impl TokenChallenge {
fn key_authorization(&self, key_pair: &KeyPair) -> Result<String, Error> { fn key_authorization(&self, key_pair: &KeyPair) -> Result<String, Error> {
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 thumbprint = b64_encode(&thumbprint);
let auth = format!("{}.{}", self.token, thumbprint); let auth = format!("{}.{}", self.token, thumbprint);
Ok(auth) Ok(auth)

4
acmed/src/certificate.rs

@ -1,6 +1,6 @@
use crate::acme_proto::Challenge; 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 crate::storage::{certificate_files_exists, get_certificate};
use acme_common::crypto::X509Certificate; use acme_common::crypto::X509Certificate;
use acme_common::error::Error; use acme_common::error::Error;

2
acmed/src/hooks.rs

@ -1,5 +1,5 @@
use crate::certificate::Certificate; use crate::certificate::Certificate;
use crate::config::HookType;
pub use crate::config::HookType;
use acme_common::error::Error; use acme_common::error::Error;
use handlebars::Handlebars; use handlebars::Handlebars;
use serde::Serialize; use serde::Serialize;

6
acmed/src/jws.rs

@ -3,9 +3,9 @@ use acme_common::b64_encode;
use acme_common::crypto::{sha256, KeyPair}; use acme_common::crypto::{sha256, KeyPair};
use acme_common::error::Error; use acme_common::error::Error;
use serde::Serialize; use serde::Serialize;
use serde_json::value::Value;
pub mod algorithms; pub mod algorithms;
mod jwk;
#[derive(Serialize)] #[derive(Serialize)]
struct JwsData { struct JwsData {
@ -17,7 +17,7 @@ struct JwsData {
#[derive(Serialize)] #[derive(Serialize)]
struct JwsProtectedHeaderJwk { struct JwsProtectedHeaderJwk {
alg: String, alg: String,
jwk: jwk::Jwk,
jwk: Value,
nonce: String, nonce: String,
url: String, url: String,
} }
@ -55,7 +55,7 @@ pub fn encode_jwk(
let sign_alg = SignatureAlgorithm::from_pkey(key_pair)?; let sign_alg = SignatureAlgorithm::from_pkey(key_pair)?;
let protected = JwsProtectedHeaderJwk { let protected = JwsProtectedHeaderJwk {
alg: sign_alg.to_string(), alg: sign_alg.to_string(),
jwk: sign_alg.get_jwk(key_pair)?,
jwk: key_pair.jwk_public_key()?,
nonce: nonce.into(), nonce: nonce.into(),
url: url.into(), url: url.into(),
}; };

7
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::crypto::{gen_keypair, KeyPair, KeyType};
use acme_common::error::Error; use acme_common::error::Error;
use std::fmt; use std::fmt;
@ -37,12 +36,6 @@ impl SignatureAlgorithm {
} }
} }
pub fn get_jwk(&self, key_pair: &KeyPair) -> Result<Jwk, Error> {
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<KeyPair, Error> { pub fn gen_key_pair(&self) -> Result<KeyPair, Error> {
match self { match self {
SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256), SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256),

31
acmed/src/jws/jwk.rs

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

3
acmed/src/storage.rs

@ -1,6 +1,5 @@
use crate::certificate::Certificate; 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::b64_encode;
use acme_common::crypto::{KeyPair, X509Certificate}; use acme_common::crypto::{KeyPair, X509Certificate};
use acme_common::error::Error; use acme_common::error::Error;

1
tacd/Cargo.toml

@ -9,6 +9,7 @@ repository = "https://github.com/breard-r/acmed"
readme = "../README.md" readme = "../README.md"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"] include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"]
publish = false
[dependencies] [dependencies]
acme_common = { path = "../acme_common" } acme_common = { path = "../acme_common" }

Loading…
Cancel
Save