From 1ab5b4012e535a3bea1f9fde8c445cc9765d1f07 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Mon, 17 Aug 2020 18:09:36 +0200 Subject: [PATCH] Use the correct algorithm and hash function for JWK signatures Since there is currently no possibility to chose a different account key type, the current implementation only supports the ES256 algorithm. With the upcoming support of different key types, it had to be changed. This commit add support for ES384 although there is no configuration option that can activate the actual use of it through account keys using the NIST P-384 curve. --- acme_common/src/crypto.rs | 2 +- acme_common/src/crypto/openssl_hash.rs | 4 ++++ acme_common/src/crypto/openssl_keys.rs | 8 ++++---- acmed/src/jws.rs | 9 +++++++-- acmed/src/jws/algorithms.rs | 5 +++++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/acme_common/src/crypto.rs b/acme_common/src/crypto.rs index e9897a0..1919fcc 100644 --- a/acme_common/src/crypto.rs +++ b/acme_common/src/crypto.rs @@ -9,5 +9,5 @@ pub const TLS_LIB_VERSION: &str = env!("ACMED_TLS_LIB_VERSION"); pub use key_type::KeyType; pub use openssl_certificate::{Csr, X509Certificate}; -pub use openssl_hash::sha256; +pub use openssl_hash::{sha256, sha384}; pub use openssl_keys::{gen_keypair, KeyPair}; diff --git a/acme_common/src/crypto/openssl_hash.rs b/acme_common/src/crypto/openssl_hash.rs index 330c9b1..56ac65c 100644 --- a/acme_common/src/crypto/openssl_hash.rs +++ b/acme_common/src/crypto/openssl_hash.rs @@ -1,3 +1,7 @@ pub fn sha256(data: &[u8]) -> Vec { openssl::sha::sha256(data).to_vec() } + +pub fn sha384(data: &[u8]) -> Vec { + openssl::sha::sha384(data).to_vec() +} diff --git a/acme_common/src/crypto/openssl_keys.rs b/acme_common/src/crypto/openssl_keys.rs index 2c066ac..9d9716a 100644 --- a/acme_common/src/crypto/openssl_keys.rs +++ b/acme_common/src/crypto/openssl_keys.rs @@ -99,9 +99,9 @@ impl KeyPair { } 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), + let (crv, alg, curve) = match self.key_type { + KeyType::EcdsaP256 => ("P-256", "ES256", Nid::X9_62_PRIME256V1), + KeyType::EcdsaP384 => ("P-384", "ES384", Nid::SECP384R1), _ => { return Err("Not a NIST elliptic curve.".into()); } @@ -126,7 +126,7 @@ impl KeyPair { }) } else { json!({ - "alg": "ES256", + "alg": alg, "crv": crv, "kty": "EC", "use": "sig", diff --git a/acmed/src/jws.rs b/acmed/src/jws.rs index 3638cab..574963b 100644 --- a/acmed/src/jws.rs +++ b/acmed/src/jws.rs @@ -1,6 +1,6 @@ use crate::jws::algorithms::SignatureAlgorithm; use acme_common::b64_encode; -use acme_common::crypto::{sha256, KeyPair}; +use acme_common::crypto::{sha256, sha384, KeyPair, KeyType}; use acme_common::error::Error; use serde::Serialize; use serde_json::value::Value; @@ -34,7 +34,12 @@ fn get_data(key_pair: &KeyPair, protected: &str, payload: &[u8]) -> Result sha256, + KeyType::EcdsaP384 => sha384, + KeyType::Curve25519 => |d: &[u8]| d.to_vec(), + }; + let fingerprint = hash_func(signing_input.as_bytes()); let signature = key_pair.sign(&fingerprint)?; let signature = b64_encode(&signature); let data = JwsData { diff --git a/acmed/src/jws/algorithms.rs b/acmed/src/jws/algorithms.rs index fa04648..4c63224 100644 --- a/acmed/src/jws/algorithms.rs +++ b/acmed/src/jws/algorithms.rs @@ -6,12 +6,14 @@ use std::str::FromStr; #[derive(Debug, PartialEq, Eq)] pub enum SignatureAlgorithm { Es256, + Es384, } impl fmt::Display for SignatureAlgorithm { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match self { SignatureAlgorithm::Es256 => "ES256", + SignatureAlgorithm::Es384 => "ES384", }; write!(f, "{}", s) } @@ -23,6 +25,7 @@ impl FromStr for SignatureAlgorithm { fn from_str(data: &str) -> Result { match data.to_lowercase().as_str() { "es256" => Ok(SignatureAlgorithm::Es256), + "es384" => Ok(SignatureAlgorithm::Es384), _ => Err(format!("{}: unknown signature algorithm", data).into()), } } @@ -32,6 +35,7 @@ impl SignatureAlgorithm { pub fn from_pkey(key_pair: &KeyPair) -> Result { match key_pair.key_type { KeyType::EcdsaP256 => Ok(SignatureAlgorithm::Es256), + KeyType::EcdsaP384 => Ok(SignatureAlgorithm::Es384), t => Err(format!("{}: unsupported key type", t).into()), } } @@ -39,6 +43,7 @@ impl SignatureAlgorithm { pub fn gen_key_pair(&self) -> Result { match self { SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256), + SignatureAlgorithm::Es384 => gen_keypair(KeyType::EcdsaP384), } } }