Browse Source

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.
pull/35/head
Rodolphe Breard 4 years ago
parent
commit
1ab5b4012e
  1. 2
      acme_common/src/crypto.rs
  2. 4
      acme_common/src/crypto/openssl_hash.rs
  3. 8
      acme_common/src/crypto/openssl_keys.rs
  4. 9
      acmed/src/jws.rs
  5. 5
      acmed/src/jws/algorithms.rs

2
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};

4
acme_common/src/crypto/openssl_hash.rs

@ -1,3 +1,7 @@
pub fn sha256(data: &[u8]) -> Vec<u8> {
openssl::sha::sha256(data).to_vec()
}
pub fn sha384(data: &[u8]) -> Vec<u8> {
openssl::sha::sha384(data).to_vec()
}

8
acme_common/src/crypto/openssl_keys.rs

@ -99,9 +99,9 @@ impl KeyPair {
}
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),
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",

9
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<Strin
let protected = b64_encode(protected);
let payload = b64_encode(payload);
let signing_input = format!("{}.{}", protected, payload);
let fingerprint = sha256(signing_input.as_bytes());
let hash_func = match key_pair.key_type {
KeyType::EcdsaP256 | KeyType::Rsa2048 | KeyType::Rsa4096 => 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 {

5
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<Self, Self::Err> {
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<Self, Error> {
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<KeyPair, Error> {
match self {
SignatureAlgorithm::Es256 => gen_keypair(KeyType::EcdsaP256),
SignatureAlgorithm::Es384 => gen_keypair(KeyType::EcdsaP384),
}
}
}

Loading…
Cancel
Save