Browse Source

Add the HS256, HS384 and HS512 signature algorithms

pull/39/head
Rodolphe Breard 4 years ago
parent
commit
45ca322ea6
  1. 9
      acme_common/src/crypto/jws_signature_algorithm.rs
  2. 7
      acme_common/src/crypto/openssl_keys.rs
  3. 44
      acmed/src/jws.rs

9
acme_common/src/crypto/jws_signature_algorithm.rs

@ -4,6 +4,9 @@ use std::str::FromStr;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum JwsSignatureAlgorithm { pub enum JwsSignatureAlgorithm {
Hs256,
Hs384,
Hs512,
Rs256, Rs256,
Es256, Es256,
Es384, Es384,
@ -18,6 +21,9 @@ impl FromStr for JwsSignatureAlgorithm {
fn from_str(s: &str) -> Result<Self, Error> { fn from_str(s: &str) -> Result<Self, Error> {
match s.to_lowercase().as_str() { match s.to_lowercase().as_str() {
"hs256" => Ok(JwsSignatureAlgorithm::Hs256),
"hs384" => Ok(JwsSignatureAlgorithm::Hs384),
"hs512" => Ok(JwsSignatureAlgorithm::Hs512),
"rs256" => Ok(JwsSignatureAlgorithm::Rs256), "rs256" => Ok(JwsSignatureAlgorithm::Rs256),
"es256" => Ok(JwsSignatureAlgorithm::Es256), "es256" => Ok(JwsSignatureAlgorithm::Es256),
"es384" => Ok(JwsSignatureAlgorithm::Es384), "es384" => Ok(JwsSignatureAlgorithm::Es384),
@ -33,6 +39,9 @@ impl FromStr for JwsSignatureAlgorithm {
impl fmt::Display for JwsSignatureAlgorithm { impl fmt::Display for JwsSignatureAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match self { let s = match self {
JwsSignatureAlgorithm::Hs256 => "HS256",
JwsSignatureAlgorithm::Hs384 => "HS384",
JwsSignatureAlgorithm::Hs512 => "HS512",
JwsSignatureAlgorithm::Rs256 => "RS256", JwsSignatureAlgorithm::Rs256 => "RS256",
JwsSignatureAlgorithm::Es256 => "ES256", JwsSignatureAlgorithm::Es256 => "ES256",
JwsSignatureAlgorithm::Es384 => "ES384", JwsSignatureAlgorithm::Es384 => "ES384",

7
acme_common/src/crypto/openssl_keys.rs

@ -85,6 +85,13 @@ impl KeyPair {
pub fn sign(&self, alg: &JwsSignatureAlgorithm, data: &[u8]) -> Result<Vec<u8>, Error> { pub fn sign(&self, alg: &JwsSignatureAlgorithm, data: &[u8]) -> Result<Vec<u8>, Error> {
let _ = self.key_type.check_alg_compatibility(alg)?; let _ = self.key_type.check_alg_compatibility(alg)?;
match alg { match alg {
JwsSignatureAlgorithm::Hs256
| JwsSignatureAlgorithm::Hs384
| JwsSignatureAlgorithm::Hs512 => Err(format!(
"{} key pair cannot be used for the {} signature algorithm",
self.key_type, alg
)
.into()),
JwsSignatureAlgorithm::Rs256 => self.sign_rsa(&MessageDigest::sha256(), data), JwsSignatureAlgorithm::Rs256 => self.sign_rsa(&MessageDigest::sha256(), data),
JwsSignatureAlgorithm::Es256 => self.sign_ecdsa(&HashFunction::Sha256, data), JwsSignatureAlgorithm::Es256 => self.sign_ecdsa(&HashFunction::Sha256, data),
JwsSignatureAlgorithm::Es384 => self.sign_ecdsa(&HashFunction::Sha384, data), JwsSignatureAlgorithm::Es384 => self.sign_ecdsa(&HashFunction::Sha384, data),

44
acmed/src/jws.rs

@ -1,5 +1,5 @@
use acme_common::b64_encode; use acme_common::b64_encode;
use acme_common::crypto::{JwsSignatureAlgorithm, KeyPair};
use acme_common::crypto::{HashFunction, JwsSignatureAlgorithm, KeyPair};
use acme_common::error::Error; use acme_common::error::Error;
use serde::Serialize; use serde::Serialize;
use serde_json::value::Value; use serde_json::value::Value;
@ -26,6 +26,13 @@ struct JwsProtectedHeaderJwk {
url: String, url: String,
} }
#[derive(Serialize)]
struct JwsProtectedHeaderKidNoNonce {
alg: String,
kid: String,
url: String,
}
#[derive(Serialize)] #[derive(Serialize)]
struct JwsProtectedHeaderKid { struct JwsProtectedHeaderKid {
alg: String, alg: String,
@ -104,6 +111,41 @@ pub fn encode_kid(
get_data(key_pair, sign_alg, &protected, payload) get_data(key_pair, sign_alg, &protected, payload)
} }
pub fn encode_kid_mac(
key: &[u8],
sign_alg: &JwsSignatureAlgorithm,
key_id: &str,
payload: &[u8],
url: &str,
) -> Result<String, Error> {
let protected = JwsProtectedHeaderKidNoNonce {
alg: sign_alg.to_string(),
kid: key_id.to_string(),
url: url.into(),
};
let protected = serde_json::to_string(&protected)?;
let protected = b64_encode(&protected);
let payload = b64_encode(payload);
let signing_input = format!("{}.{}", protected, payload);
let hash_func = match sign_alg {
JwsSignatureAlgorithm::Hs256 => HashFunction::Sha256,
JwsSignatureAlgorithm::Hs384 => HashFunction::Sha384,
JwsSignatureAlgorithm::Hs512 => HashFunction::Sha512,
_ => {
return Err(format!("{}: not a HMAC-based signature algorithm", sign_alg).into());
}
};
let signature = hash_func.hmac(key, signing_input.as_bytes())?;
let signature = b64_encode(&signature);
let data = JwsData {
protected,
payload,
signature,
};
let str_data = serde_json::to_string(&data)?;
Ok(str_data)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{encode_jwk, encode_kid}; use super::{encode_jwk, encode_kid};

Loading…
Cancel
Save