Skip to content

Commit

Permalink
Merge pull request #16 from alexrudy:yacme-compat
Browse files Browse the repository at this point in the history
Compatibility for YACME
  • Loading branch information
alexrudy authored Dec 2, 2023
2 parents 0f54bfa + be0c9f0 commit ba8d8ba
Show file tree
Hide file tree
Showing 10 changed files with 483 additions and 59 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ digest = { version = "0.10" }
ecdsa = { version = "0.16", features = ["signing", "der"], optional = true }
hmac = { version = "0.12", optional = true }
p256 = { version = "0.13", features = ["ecdsa", "jwk"], optional = true }
p384 = { version = "0.13", optional = true }
p521 = { version = "0.13", optional = true }
p384 = { version = "0.13", features = ["ecdsa", "jwk"], optional = true }
p521 = { version = "0.13", features = ["ecdsa", "jwk"], optional = true }
pkcs8 = "0.10"
rand_core = { version = "0.6.4", optional = true, default-features = false }
rsa = { version = "0.9", features = ["sha2"], optional = true }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ ecosystem.

This is an example [JWT][], taken from the ACME standard ([RFC 8555][RFC8555]):

```json
```javascript
{
"protected": base64url({
"alg": "ES256",
Expand Down
40 changes: 40 additions & 0 deletions src/algorithms/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,4 +454,44 @@ mod test {
)
.expect("signature verification for RFC7515a3 example failed");
}

macro_rules! ecdsa_algorithm_test {
($name:ident, $curve:ty) => {
#[cfg(feature = "rand")]
#[test]
fn $name() {
let key = SigningKey::<$curve>::random(&mut rand_core::OsRng);
let verify = *key.verifying_key();

let payload = json! {
{
"iss": "joe",
"exp": 1300819380,
"http://example.com/is_root": true
}
};

let token = crate::Token::compact((), payload);

let signed = token
.clone()
.sign::<_, ecdsa::Signature<$curve>>(&key)
.unwrap();
let unverified = signed.unverify();
unverified
.verify::<_, ecdsa::Signature<$curve>>(&verify)
.unwrap();

let signed = token.clone().sign::<_, SignatureBytes>(&key).unwrap();
let unverified = signed.unverify();
unverified.verify::<_, SignatureBytes>(&verify).unwrap();
}
};
}

#[cfg(feature = "p256")]
ecdsa_algorithm_test!(p256_roundtrip, NistP256);

#[cfg(feature = "p384")]
ecdsa_algorithm_test!(p384_roundtrip, NistP384);
}
24 changes: 22 additions & 2 deletions src/algorithms/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ use digest::{Digest, Mac};
use hmac::SimpleHmac;
use signature::{Keypair, SignatureEncoding};

use crate::key::{JWKeyType, SerializeJWK};
use crate::{
key::{JWKeyType, SerializeJWK},
SignatureBytes,
};

use super::JsonWebAlgorithm;

Expand Down Expand Up @@ -204,6 +207,23 @@ where
}
}

impl<D> super::TokenSigner<SignatureBytes> for Hmac<D>
where
Hmac<D>: JsonWebAlgorithm,
D: Digest + digest::core_api::BlockSizeUser + Clone,
{
fn try_sign_token(
&self,
header: &str,
payload: &str,
) -> Result<SignatureBytes, signature::Error> {
let signature = <Self as super::TokenSigner<DigestSignature<D>>>::try_sign_token(
self, header, payload,
)?;
Ok(signature.to_bytes().as_ref().into())
}
}

impl<D> super::TokenVerifier<DigestSignature<D>> for Hmac<D>
where
Hmac<D>: JsonWebAlgorithm,
Expand Down Expand Up @@ -269,7 +289,7 @@ mod test {

let algorithm: Hmac<Sha256> = Hmac::new(key);

let signature = algorithm.sign_token(&header, &payload);
let signature: DigestSignature<_> = algorithm.sign_token(&header, &payload);

let sig = base64ct::Base64UrlUnpadded::encode_string(signature.to_bytes().as_ref());

Expand Down
11 changes: 7 additions & 4 deletions src/algorithms/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
//! - RS512: RSASSA-PKCS1-v1_5 using SHA-512 via [`rsa::pkcs1v15::SigningKey<Sha512>`][rsa::pkcs1v15::SigningKey] / [`rsa::pkcs1v15::VerifyingKey<Sha512>`][rsa::pkcs1v15::VerifyingKey]
//! - PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256 via [`rsa::pss::SigningKey<Sha256>`][rsa::pss::SigningKey] / [`rsa::pss::VerifyingKey<Sha256>`][rsa::pss::VerifyingKey]
//! - PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384 via [`rsa::pss::SigningKey<Sha384>`][rsa::pss::SigningKey] / [`rsa::pss::VerifyingKey<Sha384>`][rsa::pss::VerifyingKey]
//! - PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-384 via [`rsa::pss::SigningKey<Sha512>`][rsa::pss::SigningKey] / [`rsa::pss::VerifyingKey<Sha512>`][rsa::pss::VerifyingKey]
//!
//! ## ECDSA
//!
Expand Down Expand Up @@ -159,7 +160,7 @@ pub trait JsonWebAlgorithm {
const IDENTIFIER: AlgorithmIdentifier;
}

/// A trait to associate an alogritm identifier with an algorithm.
/// An object-safe trait to associate an alogritm identifier with an algorithm.
///
/// This is a dynamic version of [`JsonWebAlgorithm`], which allows for
/// dynamic dispatch of the algorithm, and object-safety for the trait.
Expand Down Expand Up @@ -189,7 +190,7 @@ pub trait JsonWebAlgorithmDigest: JsonWebAlgorithm {
/// A trait to represent an algorithm which can sign a JWT.
///
/// This trait should apply to signing keys.
pub trait TokenSigner<S>: DynJsonWebAlgorithm + SerializePublicJWK
pub trait TokenSigner<S = SignatureBytes>: DynJsonWebAlgorithm + SerializePublicJWK
where
S: SignatureEncoding,
{
Expand Down Expand Up @@ -229,7 +230,8 @@ where
#[cfg(feature = "rand")]
/// A trait to represent an algorithm which can sign a JWT, with a source of
/// randomness.
pub trait RandomizedTokenSigner<S>: DynJsonWebAlgorithm + SerializePublicJWK
pub trait RandomizedTokenSigner<S = SignatureBytes>:
DynJsonWebAlgorithm + SerializePublicJWK
where
S: SignatureEncoding,
{
Expand Down Expand Up @@ -259,7 +261,7 @@ where
///
/// This trait should apply to the equivalent of public keys, which have enough information
/// to verify a JWT signature, but not necessarily to sing it.
pub trait TokenVerifier<S>: DynJsonWebAlgorithm
pub trait TokenVerifier<S = SignatureBytes>: DynJsonWebAlgorithm
where
S: SignatureEncoding,
{
Expand Down Expand Up @@ -434,4 +436,5 @@ mod test {
// a concrete `Signature` type, or an object-safe trait.
sa::assert_obj_safe!(TokenSigner<SignatureBytes>);
sa::assert_obj_safe!(TokenVerifier<SignatureBytes>);
sa::assert_obj_safe!(DynJsonWebAlgorithm);
}
Loading

0 comments on commit ba8d8ba

Please sign in to comment.