From 55f4d3416b192a200550089ed02601e38a36ca75 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Sat, 29 Jun 2019 13:33:53 +0200 Subject: [PATCH] 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(), - } - } -}