extern crate openssl;
extern crate serde;
extern crate base64;
#[cfg(test)]
#[macro_use]
extern crate serde_json;
#[cfg(not(test))]
extern crate serde_json;
pub mod error;
use std::fs::File;
use std::path::{PathBuf};
use std::io::Read;
use std::str;
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Private};
use openssl::rsa::Rsa;
use openssl::sign::{Signer, Verifier};
use openssl::ec::EcKey;
use serde_json::Value as JsonValue;
use base64::{encode_config as b64_enc, decode_config as b64_dec};
pub use error::Error;
const SEGMENTS_COUNT: usize = 3;
const STANDARD_HEADER_TYPE: &str = "JWT";
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Algorithm {
HS256,
HS384,
HS512,
RS256,
RS384,
RS512,
ES256,
ES384,
ES512
}
impl ToString for Algorithm {
fn to_string(&self) -> String {
match *self {
Algorithm::HS256 => "HS256",
Algorithm::HS384 => "HS384",
Algorithm::HS512 => "HS512",
Algorithm::RS256 => "RS256",
Algorithm::RS384 => "RS384",
Algorithm::RS512 => "RS512",
Algorithm::ES256 => "ES256",
Algorithm::ES384 => "ES384",
Algorithm::ES512 => "ES512"
}.to_string()
}
}
pub trait ToKey {
fn to_key(&self) -> Result<Vec<u8>, Error>;
}
impl ToKey for PathBuf {
fn to_key(&self) -> Result<Vec<u8>, Error> {
let mut file = File::open(self)?;
let mut buffer:Vec<u8> = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}
}
impl ToKey for String {
fn to_key(&self) -> Result<Vec<u8>, Error> {
Ok(self.as_bytes().to_vec())
}
}
impl ToKey for Vec<u8> {
fn to_key(&self) -> Result<Vec<u8>, Error> {
Ok(self.clone())
}
}
pub fn encode<P: ToKey>(mut header: JsonValue, signing_key: &P, payload: &JsonValue, algorithm: Algorithm) -> Result<String, Error> {
header["alg"] = JsonValue::String(algorithm.to_string());
if header["typ"].is_null() {
header["typ"] = JsonValue::String(STANDARD_HEADER_TYPE.to_owned());
}
let signing_input = get_signing_input(&payload, &header)?;
let signature = match algorithm {
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => sign_hmac(&signing_input, signing_key, algorithm)?,
Algorithm::RS256 | Algorithm::RS384 | Algorithm::RS512 => sign_rsa(&signing_input, signing_key, algorithm)?,
Algorithm::ES256 | Algorithm::ES384 | Algorithm::ES512 => sign_es(&signing_input, signing_key, algorithm)?,
};
Ok(format!("{}.{}", signing_input, signature))
}
pub fn decode<P: ToKey>(encoded_token: &String, signing_key: &P, algorithm: Algorithm) -> Result<(JsonValue, JsonValue), Error> {
let (header, payload, signature, signing_input) = decode_segments(encoded_token)?;
if !verify_signature(algorithm, signing_input, &signature, signing_key)? {
Err(Error::SignatureInvalid)
} else {
Ok((header, payload))
}
}
pub fn validate_signature<P: ToKey>(encoded_token: &String, signing_key: &P, algorithm: Algorithm) -> Result<bool, Error> {
let (signature, signing_input) = decode_signature_segments(encoded_token)?;
verify_signature(algorithm, signing_input, &signature, signing_key)
}
fn get_signing_input(payload: &JsonValue, header: &JsonValue) -> Result<String, Error> {
let header_json_str = serde_json::to_string(header)?;
let encoded_header = b64_enc(header_json_str.as_bytes(), base64::URL_SAFE_NO_PAD);
let payload_json_str = serde_json::to_string(payload)?;
let encoded_payload = b64_enc(payload_json_str.as_bytes(), base64::URL_SAFE_NO_PAD);
Ok(format!("{}.{}", encoded_header, encoded_payload))
}
fn sign_hmac<P: ToKey>(data: &str, key_path: &P, algorithm: Algorithm) -> Result<String, Error> {
let stp = match algorithm {
Algorithm::HS256 => MessageDigest::sha256(),
Algorithm::HS384 => MessageDigest::sha384(),
Algorithm::HS512 => MessageDigest::sha512(),
_ => panic!("Invalid hmac algorithm")
};
let key = PKey::hmac(&key_path.to_key()?)?;
let mut signer = Signer::new(stp, &key)?;
signer.update(data.as_bytes())?;
let hmac = signer.sign_to_vec()?;
Ok(b64_enc(hmac.as_slice(), base64::URL_SAFE_NO_PAD))
}
fn sign_rsa<P: ToKey>(data: &str, private_key_path: &P, algorithm: Algorithm) -> Result<String, Error> {
let stp = match algorithm {
Algorithm::RS256 => MessageDigest::sha256(),
Algorithm::RS384 => MessageDigest::sha384(),
Algorithm::RS512 => MessageDigest::sha512(),
_ => panic!("Invalid hmac algorithm")
};
let rsa = Rsa::private_key_from_pem(&private_key_path.to_key()?)?;
let key = PKey::from_rsa(rsa)?;
sign(data, key, stp)
}
fn sign_es<P: ToKey>(data: &str, private_key_path: &P, algorithm: Algorithm) -> Result<String, Error> {
let ec_key = EcKey::private_key_from_pem(&private_key_path.to_key()?)?;
let key = PKey::from_ec_key(ec_key)?;
let stp = match algorithm {
Algorithm::ES256 => MessageDigest::sha256(),
Algorithm::ES384 => MessageDigest::sha384(),
Algorithm::ES512 => MessageDigest::sha512(),
_ => panic!("Invalid hmac algorithm")
};
sign(data, key, stp)
}
fn sign(data: &str, private_key: PKey<Private>, digest: MessageDigest) -> Result<String, Error> {
let mut signer = Signer::new(digest, &private_key)?;
signer.update(data.as_bytes())?;
let signature = signer.sign_to_vec()?;
Ok(b64_enc(signature.as_slice(), base64::URL_SAFE_NO_PAD))
}
fn decode_segments(encoded_token: &String) -> Result<(JsonValue, JsonValue, Vec<u8>, String), Error> {
let raw_segments: Vec<&str> = encoded_token.split(".").collect();
if raw_segments.len() != SEGMENTS_COUNT {
return Err(Error::JWTInvalid);
}
let header_segment = raw_segments[0];
let payload_segment = raw_segments[1];
let crypto_segment = raw_segments[2];
let (header, payload) = decode_header_and_payload(header_segment, payload_segment)?;
let signature = b64_dec(crypto_segment.as_bytes(), base64::URL_SAFE_NO_PAD)?;
let signing_input = format!("{}.{}", header_segment, payload_segment);
Ok((header, payload, signature.clone(), signing_input))
}
fn decode_signature_segments(encoded_token: &String) -> Result<(Vec<u8>, String), Error> {
let raw_segments: Vec<&str> = encoded_token.split(".").collect();
if raw_segments.len() != SEGMENTS_COUNT {
return Err(Error::JWTInvalid);
}
let header_segment = raw_segments[0];
let payload_segment = raw_segments[1];
let crypto_segment = raw_segments[2];
let signature = b64_dec(crypto_segment.as_bytes(), base64::URL_SAFE_NO_PAD)?;
let signing_input = format!("{}.{}", header_segment, payload_segment);
Ok((signature.clone(), signing_input))
}
fn decode_header_and_payload(header_segment: &str, payload_segment: &str) -> Result<(JsonValue, JsonValue), Error> {
let b64_to_json = |seg| -> Result<JsonValue, Error> {
serde_json::from_slice(b64_dec(seg, base64::URL_SAFE_NO_PAD)?.as_slice()).map_err(Error::from)
};
let header_json = b64_to_json(header_segment)?;
let payload_json = b64_to_json(payload_segment)?;
Ok((header_json, payload_json))
}
fn sign_hmac2(data: &str, key: &Vec<u8>, algorithm: Algorithm) -> Result<Vec<u8>, Error> {
let stp = match algorithm {
Algorithm::HS256 => MessageDigest::sha256(),
Algorithm::HS384 => MessageDigest::sha384(),
Algorithm::HS512 => MessageDigest::sha512(),
_ => panic!("Invalid HMAC algorithm")
};
let pkey = PKey::hmac(key)?;
let mut signer = Signer::new(stp, &pkey)?;
signer.update(data.as_bytes())?;
signer.sign_to_vec().map_err(Error::from)
}
fn verify_signature<P: ToKey>(algorithm: Algorithm, signing_input: String, signature: &[u8], public_key: &P) -> Result<bool, Error> {
match algorithm {
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
let signature2 = sign_hmac2(&signing_input, &public_key.to_key()?, algorithm)?;
Ok(secure_compare(signature, &signature2))
},
Algorithm::RS256 | Algorithm::RS384 | Algorithm::RS512 => {
let rsa = Rsa::public_key_from_pem(&public_key.to_key()?)?;
let key = PKey::from_rsa(rsa)?;
let digest = get_sha_algorithm(algorithm);
let mut verifier = Verifier::new(digest, &key)?;
verifier.update(signing_input.as_bytes())?;
verifier.verify(&signature).map_err(Error::from)
},
Algorithm::ES256 | Algorithm::ES384 | Algorithm::ES512 => {
let key = PKey::public_key_from_pem(&public_key.to_key()?).map_err(Error::from)?;
let digest = get_sha_algorithm(algorithm);
let mut verifier = Verifier::new(digest, &key)?;
verifier.update(signing_input.as_bytes())?;
verifier.verify(&signature).map_err(Error::from)
},
}
}
fn get_sha_algorithm(alg: Algorithm) -> MessageDigest {
match alg {
Algorithm::RS256 | Algorithm::ES256 => MessageDigest::sha256(),
Algorithm::RS384 | Algorithm::ES384 => MessageDigest::sha384(),
Algorithm::RS512 | Algorithm::ES512 => MessageDigest::sha512(),
_ => panic!("Invalid RSA algorithm")
}
}
fn secure_compare(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false
}
let mut res = 0_u8;
for (&x, &y) in a.iter().zip(b.iter()) {
res |= x ^ y;
}
res == 0
}
fn verify_not_before() {
unimplemented!()
}
fn verify_sub() {
unimplemented!()
}
fn verify_jti() {
unimplemented!()
}
fn verify_iss() {
unimplemented!()
}
fn verify_iat() {
unimplemented!()
}
fn verify_expiration() {
unimplemented!()
}
fn verify_aud() {
unimplemented!()
}
#[cfg(test)]
mod tests {
use super::{Algorithm, encode, decode, validate_signature, secure_compare, STANDARD_HEADER_TYPE};
use std::env;
use std::path::PathBuf;
#[test]
fn test_encode_and_decode_jwt_hs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS256).unwrap();
let maybe_res = decode(&jwt1, &secret, Algorithm::HS256);
assert!(maybe_res.is_ok());
}
#[test]
fn test_decode_valid_jwt_hs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2"
});
let secret = "secret123".to_string();
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxMSI6InZhbDEiLCJrZXkyMiI6InZhbDIifQ.jrcoVcRsmQqDEzSW9qOhG1HIrzV_n3nMhykNPnGvp9c".to_string();
let maybe_res = decode(&jwt, &secret, Algorithm::HS256);
assert!(maybe_res.is_ok());
}
#[test]
fn test_validate_signature_jwt_hs256() {
let secret = "secret123".to_string();
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxMSI6InZhbDEiLCJrZXkyMiI6InZhbDIifQ.jrcoVcRsmQqDEzSW9qOhG1HIrzV_n3nMhykNPnGvp9c".to_string();
let maybe_res = validate_signature(&jwt, &secret, Algorithm::HS256);
assert!(maybe_res.unwrap());
}
#[test]
fn test_validate_signature_with_header_jwt_hs256() {
let secret = "secret".to_string();
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJDUklTUCIsImdyb3VwIjoiQVRJIiwicmVzb3VyY2VzIjpbXX0.K9nfZnbMzF1-P1zXEQHeYYUz35NTbTPpT560wNG16DM".to_string();
let maybe_res = validate_signature(&jwt, &secret, Algorithm::HS256);
assert!(maybe_res.unwrap());
}
#[test]
fn test_validate_signature_jwt_hs256_invalid() {
let secret = "secret123".to_string();
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ8.eyJrZXkxMSI6InZhbDEiLCJrZXkyMiI6InZhbDIifQ.jrcoVcRsmQqDEzSW9qOhG1HIrzV_n3nMhykNPnGvp9c".to_string();
let maybe_res = validate_signature(&jwt, &secret, Algorithm::HS256);
assert!(!maybe_res.unwrap());
}
#[test]
fn test_secure_compare_same_strings() {
let str1 = "same same".as_bytes();
let str2 = "same same".as_bytes();
let res = secure_compare(str1, str2);
assert!(res);
}
#[test]
fn test_fails_when_secure_compare_different_strings() {
let str1 = "same same".as_bytes();
let str2 = "same same but different".as_bytes();
let res = secure_compare(str1, str2);
assert!(!res);
}
#[test]
fn test_encode_and_decode_jwt_hs384() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS384).unwrap();
let maybe_res = decode(&jwt1, &secret, Algorithm::HS384);
assert!(maybe_res.is_ok());
}
#[test]
fn test_validate_signature_jwt_hs384() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS384).unwrap();
let maybe_res = validate_signature(&jwt1, &secret, Algorithm::HS384);
assert!(maybe_res.unwrap());
}
#[test]
fn test_validate_signature_jwt_hs384_invalid() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS384).unwrap();
let bad_secret = "secret1234".to_string();
let maybe_res = validate_signature(&jwt1, &bad_secret, Algorithm::HS384);
assert!(!maybe_res.unwrap());
}
#[test]
fn test_encode_and_decode_jwt_hs512() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123456".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS512).unwrap();
let maybe_res = decode(&jwt1, &secret, Algorithm::HS512);
assert!(maybe_res.is_ok());
}
#[test]
fn test_validate_signature_jwt_hs512() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123456".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS512).unwrap();
let maybe_res = validate_signature(&jwt1, &secret, Algorithm::HS512);
assert!(maybe_res.unwrap());
}
#[test]
fn test_validate_signature_jwt_hs512_invalid() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let secret = "secret123456".to_string();
let header = json!({});
let jwt1 = encode(header, &secret, &p1, Algorithm::HS512).unwrap();
let bad_secret = "secret123456789".to_string();
let maybe_res = validate_signature(&jwt1, &bad_secret, Algorithm::HS512);
assert!(!maybe_res.unwrap());
}
#[test]
fn test_encode_and_decode_jwt_rs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_rsa_2048_key.pem");
path.to_str().unwrap().to_string();
let jwt1 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let maybe_res = decode(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(maybe_res.is_ok());
}
#[test]
fn test_encoded_validate_signature_jwt_rs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_rsa_2048_key.pem");
path.to_str().unwrap().to_string();
let jwt1 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let maybe_res = validate_signature(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(maybe_res.unwrap());
}
#[test]
fn test_encoded_validate_signature_jwt_rs256_invalid() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_rsa_2048_key.pem");
path.to_str().unwrap().to_string();
let jwt1 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let maybe_res = validate_signature(&jwt1, &get_bad_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(!maybe_res.unwrap());
}
#[test]
fn test_decode_valid_jwt_rs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2"
});
let header = json!({});
let jwt1 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxIjoidmFsMSIsImtleTIiOiJ2YWwyIn0.DFusERCFWCL3CkKBaoVKsi1Z3QO2NTTRDTGHPqm7ctzypKHxLslJXfS1p_8_aRX30V2osMAEfGzXO9U0S9J1Z7looIFNf5rWSEcqA3ah7b7YQ2iTn9LOiDWwzVG8rm_HQXkWq-TXqayA-IXeiX9pVPB9bnguKXy3YrLWhP9pxnhl2WmaE9ryn8WTleMiElwDq4xw5JDeopA-qFS-AyEwlc-CE7S_afBd5OQBRbvgtfv1a9soNW3KP_mBg0ucz5eUYg_ON17BG6bwpAwyFuPdDAXphG4hCsa7GlXea0f7DnYD5e5-CA6O7BPW_EvjaGhL_D9LNWHJuDiSDBwZ4-IEIg".to_string();
let (h1, p1) = decode(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256).unwrap();
println!("\n{}",h1);
println!("{}",p1);
let jwt2 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let (h2, p2) = decode(&jwt2, &get_rsa_256_public_key_full_path(), Algorithm::RS256).unwrap();
println!("{}",h2);
println!("{}",p2);
assert_eq!(jwt1, jwt2);
}
#[test]
fn test_validate_signature_jwt_rs256() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2"
});
let header = json!({});
let jwt1 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxIjoidmFsMSIsImtleTIiOiJ2YWwyIn0.RQdLX70LEWL3PFePR2ec7fsBLwi29qK9GL_YfiBKcOWnWsgWMrw0PeJw8h21FloKAYYRq73GmSlF39B5TWbquscf3obfD_y3TYmSjY_STlQ1UTMBnCmwZeMgxuIlq4l7RNpGh_j-42u6YJ3b4zwFiiIGWANYTL0pzXjdIFcUhuY7yeYlFHmWgUOOfv_E_MaP0CgCK6rgeorPtFZ80Z-zYc2R7oXLylgiwJQmwLGzxAcOOcNaZurhQxUQ7GrErY9fOLxfw0vmF4FMSIhQvWIiUV9Meh3MoIwybDhuy5-Y85WZwtXYC7blAZhU0h6tFqwBozt7PS34htj8rkCIqqi0Ng".to_string();
let maybe_valid_sign1 = validate_signature(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(maybe_valid_sign1.is_ok());
let jwt2 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let maybe_valid_sign2 = validate_signature(&jwt2, &get_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(maybe_valid_sign2.unwrap());
}
#[test]
fn test_validate_signature_jwt_rs256_invalid() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2"
});
let header = json!({});
let jwt1 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxIjoidmFsMSIsImtleTIiOiJ2YWwyIn0=.RQdLX70LEWL3PFePR2ec7fsBLwi29qK9GL_YfiBKcOWnWsgWMrw0PeJw8h21FloKAYYRq73GmSlF39B5TWbquscf3obfD_y3TYmSjY_STlQ1UTMBnCmwZeMgxuIlq4l7RNpGh_j-42u6YJ3b4zwFiiIGWANYTL0pzXjdIFcUhuY7yeYlFHmWgUOOfv_E_MaP0CgCK6rgeorPtFZ80Z-zYc2R7oXLylgiwJQmwLGzxAcOOcNaZurhQxUQ7GrErY9fOLxfw0vmF4FMSIhQvWIiUV9Meh3MoIwybDhuy5-Y85WZwtXYC7blAZhU0h6tFqwBozt7PS34htj8rkCIqqi0Ng==".to_string();
let maybe_valid_sign1 = validate_signature(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(maybe_valid_sign1.is_ok());
let jwt2 = encode(header, &get_rsa_256_private_key_full_path(), &p1, Algorithm::RS256).unwrap();
let maybe_valid_sign2 = validate_signature(&jwt2, &get_bad_rsa_256_public_key_full_path(), Algorithm::RS256);
assert!(!maybe_valid_sign2.unwrap());
}
#[test]
fn test_decode_valid_jwt_rs256_and_check_deeply() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2"
});
let h1 = json!({"typ" : STANDARD_HEADER_TYPE, "alg" : Algorithm::RS256.to_string()});
let jwt1 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkxIjoidmFsMSIsImtleTIiOiJ2YWwyIn0=.RQdLX70LEWL3PFePR2ec7fsBLwi29qK9GL_YfiBKcOWnWsgWMrw0PeJw8h21FloKAYYRq73GmSlF39B5TWbquscf3obfD_y3TYmSjY_STlQ1UTMBnCmwZeMgxuIlq4l7RNpGh_j-42u6YJ3b4zwFiiIGWANYTL0pzXjdIFcUhuY7yeYlFHmWgUOOfv_E_MaP0CgCK6rgeorPtFZ80Z-zYc2R7oXLylgiwJQmwLGzxAcOOcNaZurhQxUQ7GrErY9fOLxfw0vmF4FMSIhQvWIiUV9Meh3MoIwybDhuy5-Y85WZwtXYC7blAZhU0h6tFqwBozt7PS34htj8rkCIqqi0Ng==".to_string();
let (h2, p2) = decode(&jwt1, &get_rsa_256_public_key_full_path(), Algorithm::RS256).unwrap();
assert_eq!(h1.get("typ").unwrap(), h2.get("typ").unwrap());
assert_eq!(h1.get("alg").unwrap(), h2.get("alg").unwrap());
assert_eq!(p1, p2);
}
#[test]
fn test_encode_and_decode_jwt_ec() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let h1 = json!({"typ" : STANDARD_HEADER_TYPE, "alg" : Algorithm::ES512.to_string()});
let jwt1 = encode(header, &get_ec_private_key_path(), &p1, Algorithm::ES512).unwrap();
let (header, payload) = decode(&jwt1, &get_ec_public_key_path(), Algorithm::ES512).unwrap();
assert_eq!(p1, payload);
assert_eq!(h1, header);
}
#[test]
fn test_validate_signature_jwt_ec() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let jwt1 = encode(header, &get_ec_private_key_path(), &p1, Algorithm::ES512).unwrap();
let maybe_valid_sign = validate_signature(&jwt1, &get_ec_public_key_path(), Algorithm::ES512);
assert!(maybe_valid_sign.unwrap());
}
#[test]
fn test_validate_signature_jwt_ec_invalid() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let header = json!({});
let jwt1 = encode(header, &get_ec_private_key_path(), &p1, Algorithm::ES512).unwrap();
let maybe_valid_sign = validate_signature(&jwt1, &get_bad_ec_public_key_path(), Algorithm::ES512);
assert!(!maybe_valid_sign.unwrap());
}
#[test]
fn test_header_typ_override() {
let p1 = json!({
"key1" : "val1",
"key2" : "val2",
"key3" : "val3"
});
let h1 = json!({"typ" : "cust", "alg" : Algorithm::ES512.to_string()});
let header = json!({"typ" : "cust"});
let jwt1 = encode(header, &get_ec_private_key_path(), &p1, Algorithm::ES512).unwrap();
let (header, payload) = decode(&jwt1, &get_ec_public_key_path(), Algorithm::ES512).unwrap();
assert_eq!(h1, header);
assert_eq!(p1, payload);
}
fn get_ec_private_key_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("ec_x9_62_prime256v1.private.key.pem");
path.to_path_buf()
}
fn get_ec_public_key_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("ec_x9_62_prime256v1.public.key.pem");
path.to_path_buf()
}
fn get_bad_ec_public_key_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("ec_2_x9_62_prime256v1.public.key.pem");
path.to_path_buf()
}
fn get_rsa_256_private_key_full_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_rsa_2048_key.pem");
path.to_path_buf()
}
fn get_rsa_256_public_key_full_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_rsa_public_2048_key.pem");
path.to_path_buf()
}
fn get_bad_rsa_256_public_key_full_path() -> PathBuf {
let mut path = env::current_dir().unwrap();
path.push("test");
path.push("my_bad_rsa_public_2048_key.pem");
path.to_path_buf()
}
}