You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-04 18:22:34 +03:00
234 lines
8.6 KiB
Rust
234 lines
8.6 KiB
Rust
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
static HS256_JWT: &str = include_str!("./jwts/hs256.jwt");
|
|
static HS384_JWT: &str = include_str!("./jwts/hs384.jwt");
|
|
static HS512_JWT: &str = include_str!("./jwts/hs512.jwt");
|
|
static RS256_JWT: &str = include_str!("./jwts/rs256.jwt");
|
|
static RS384_JWT: &str = include_str!("./jwts/rs384.jwt");
|
|
static RS512_JWT: &str = include_str!("./jwts/rs512.jwt");
|
|
static PS256_JWT: &str = include_str!("./jwts/ps256.jwt");
|
|
static PS384_JWT: &str = include_str!("./jwts/ps384.jwt");
|
|
static PS512_JWT: &str = include_str!("./jwts/ps512.jwt");
|
|
static ES256_JWT: &str = include_str!("./jwts/es256.jwt");
|
|
static ES384_JWT: &str = include_str!("./jwts/es384.jwt");
|
|
static ES512_JWT: &str = include_str!("./jwts/es512.jwt");
|
|
static ES256K_JWT: &str = include_str!("./jwts/es256k.jwt");
|
|
static EDDSA_ED25519_JWT: &str = include_str!("./jwts/eddsa-ed25519.jwt");
|
|
static EDDSA_ED448_JWT: &str = include_str!("./jwts/eddsa-ed448.jwt");
|
|
static OCT_KEY: &[u8] = include_bytes!("./keys/oct.bin");
|
|
|
|
fn public_jwks() -> mas_jose::jwk::PublicJsonWebKeySet {
|
|
serde_json::from_str(include_str!("./keys/jwks.pub.json")).unwrap()
|
|
}
|
|
|
|
fn private_jwks() -> mas_jose::jwk::PrivateJsonWebKeySet {
|
|
serde_json::from_str(include_str!("./keys/jwks.priv.json")).unwrap()
|
|
}
|
|
|
|
fn oct_key() -> Vec<u8> {
|
|
OCT_KEY.to_vec()
|
|
}
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize)]
|
|
struct Payload {
|
|
hello: String,
|
|
}
|
|
|
|
macro_rules! conditional {
|
|
{ true => $($tt:tt)* } => {
|
|
$($tt)*
|
|
};
|
|
{ false => $($tt:tt)* } => {};
|
|
}
|
|
|
|
macro_rules! asymetric_jwt_test {
|
|
($test_name:ident, $alg:ident, $jwt:ident) => {
|
|
asymetric_jwt_test!($test_name, $alg, $jwt, supported = true);
|
|
};
|
|
($test_name:ident, $alg:ident, $jwt:ident, supported = $supported:ident) => {
|
|
mod $test_name {
|
|
use std::ops::Deref;
|
|
|
|
use mas_iana::jose::JsonWebSignatureAlg;
|
|
use mas_jose::{constraints::ConstraintSet, jwt::Jwt};
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn validate_jwt() {
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
assert_eq!(jwt.payload().hello, "world");
|
|
assert_eq!(*jwt.header().alg(), JsonWebSignatureAlg::$alg);
|
|
}
|
|
|
|
#[test]
|
|
fn find_public_key() {
|
|
let jwks = public_jwks();
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
|
|
let constraints = ConstraintSet::from(jwt.header());
|
|
let candidates = constraints.filter(jwks.deref());
|
|
assert_eq!(candidates.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn find_private_key() {
|
|
let jwks = private_jwks();
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
|
|
let constraints = ConstraintSet::from(jwt.header());
|
|
let candidates = constraints.filter(jwks.deref());
|
|
assert_eq!(candidates.len(), 1);
|
|
}
|
|
|
|
conditional! { $supported =>
|
|
use mas_jose::jwt::JsonWebSignatureHeader;
|
|
use rand_chacha::ChaCha8Rng;
|
|
use rand::SeedableRng;
|
|
|
|
#[test]
|
|
fn verify_jwt() {
|
|
let jwks = public_jwks();
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
|
|
let key = jwks.find_key(&jwt.header().into()).unwrap();
|
|
|
|
let key = mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(
|
|
key.params(),
|
|
&JsonWebSignatureAlg::$alg,
|
|
)
|
|
.unwrap();
|
|
|
|
jwt.verify(&key).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn sign_jwt() {
|
|
let mut rng = ChaCha8Rng::seed_from_u64(42);
|
|
let alg = JsonWebSignatureAlg::$alg;
|
|
let payload = Payload {
|
|
hello: "world".to_string(),
|
|
};
|
|
let header = JsonWebSignatureHeader::new(alg.clone());
|
|
|
|
let jwks = private_jwks();
|
|
let key = jwks.signing_key_for_algorithm(&alg).unwrap();
|
|
|
|
let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg(key.params(), &alg)
|
|
.unwrap();
|
|
|
|
let jwt: Jwt<'_, Payload> = Jwt::sign_with_rng(&mut rng, header, payload, &key).unwrap();
|
|
insta::assert_snapshot!(jwt.as_str());
|
|
}
|
|
|
|
#[test]
|
|
fn sign_and_verify_jwt() {
|
|
let alg = JsonWebSignatureAlg::$alg;
|
|
let payload = Payload {
|
|
hello: "world".to_string(),
|
|
};
|
|
let header = JsonWebSignatureHeader::new(alg.clone());
|
|
|
|
let jwks = private_jwks();
|
|
let key = jwks.signing_key_for_algorithm(&alg).unwrap();
|
|
|
|
let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg(key.params(), &alg)
|
|
.unwrap();
|
|
|
|
let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap();
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from(jwt.as_str()).unwrap();
|
|
|
|
let jwks = public_jwks();
|
|
let key = jwks.find_key(&jwt.header().into()).unwrap();
|
|
|
|
let key =
|
|
mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(key.params(), &alg)
|
|
.unwrap();
|
|
|
|
jwt.verify(&key).unwrap();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! symetric_jwt_test {
|
|
($test_name:ident, $alg:ident, $jwt:ident) => {
|
|
mod $test_name {
|
|
use mas_iana::jose::JsonWebSignatureAlg;
|
|
use mas_jose::jwt::{JsonWebSignatureHeader, Jwt};
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn validate_jwt() {
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
assert_eq!(jwt.payload().hello, "world");
|
|
assert_eq!(*jwt.header().alg(), JsonWebSignatureAlg::$alg);
|
|
}
|
|
|
|
#[test]
|
|
fn verify_jwt() {
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap();
|
|
let key =
|
|
mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), &JsonWebSignatureAlg::$alg)
|
|
.unwrap();
|
|
jwt.verify(&key).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn sign_and_verify_jwt() {
|
|
let alg = JsonWebSignatureAlg::$alg;
|
|
let payload = Payload {
|
|
hello: "world".to_string(),
|
|
};
|
|
let header = JsonWebSignatureHeader::new(alg.clone());
|
|
|
|
let key = mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), &alg).unwrap();
|
|
|
|
let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap();
|
|
let jwt: Jwt<'_, Payload> = Jwt::try_from(jwt.as_str()).unwrap();
|
|
|
|
jwt.verify(&key).unwrap();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
symetric_jwt_test!(hs256, Hs256, HS256_JWT);
|
|
symetric_jwt_test!(hs384, Hs384, HS384_JWT);
|
|
symetric_jwt_test!(hs512, Hs512, HS512_JWT);
|
|
|
|
asymetric_jwt_test!(rs256, Rs256, RS256_JWT);
|
|
asymetric_jwt_test!(rs384, Rs384, RS384_JWT);
|
|
asymetric_jwt_test!(rs512, Rs512, RS512_JWT);
|
|
asymetric_jwt_test!(ps256, Ps256, PS256_JWT);
|
|
asymetric_jwt_test!(ps384, Ps384, PS384_JWT);
|
|
asymetric_jwt_test!(ps512, Ps512, PS512_JWT);
|
|
asymetric_jwt_test!(es256, Es256, ES256_JWT);
|
|
asymetric_jwt_test!(es384, Es384, ES384_JWT);
|
|
asymetric_jwt_test!(es512, Es512, ES512_JWT, supported = false);
|
|
asymetric_jwt_test!(es256k, Es256K, ES256K_JWT);
|
|
asymetric_jwt_test!(eddsa_ed25519, EdDsa, EDDSA_ED25519_JWT, supported = false);
|
|
asymetric_jwt_test!(eddsa_ed448, EdDsa, EDDSA_ED448_JWT, supported = false);
|
|
|
|
#[test]
|
|
fn test_private_to_public_jwks() {
|
|
let priv_jwks = private_jwks();
|
|
let pub_jwks = mas_jose::jwk::PublicJsonWebKeySet::from(priv_jwks);
|
|
|
|
assert_eq!(pub_jwks, public_jwks());
|
|
}
|