Browse Source

Refactor the JWK implementation

pull/5/head
Rodolphe Breard 5 years ago
parent
commit
55f4d3416b
  1. 59
      acme_common/src/crypto/openssl_keys.rs
  2. 4
      acmed/src/acme_proto/structs/authorization.rs
  3. 6
      acmed/src/jws.rs
  4. 7
      acmed/src/jws/algorithms.rs
  5. 31
      acmed/src/jws/jwk.rs

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)
} }
} }

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)

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(),
}
}
}
Loading…
Cancel
Save