Files
Notes/notes-service/vendor/jsonwebtoken/src/jws.rs
T
2026-08-01 16:11:49 +03:00

85 lines
2.9 KiB
Rust

//! JSON Web Signatures data type.
use std::marker::PhantomData;
use crate::crypto::{CryptoProvider, sign};
use crate::errors::{ErrorKind, Result, new_error};
use crate::serialization::{DecodedJwtPartClaims, b64_encode_part};
use crate::validation::validate;
use crate::{DecodingKey, EncodingKey, Header, TokenData, Validation};
use crate::decoding::verify_signature_body;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
/// This is a serde-compatible JSON Web Signature structure.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Jws<C> {
/// The base64 encoded header data.
///
/// Defined in [RFC7515#3.2](https://tools.ietf.org/html/rfc7515#section-3.2).
pub protected: String,
/// The base64 encoded claims data.
///
/// Defined in [RFC7515#3.2](https://tools.ietf.org/html/rfc7515#section-3.2).
pub payload: String,
/// The signature on the other fields.
///
/// Defined in [RFC7515#3.2](https://tools.ietf.org/html/rfc7515#section-3.2).
pub signature: String,
/// Unused, for associating type metadata.
#[serde(skip)]
pub _pd: PhantomData<C>,
}
/// Encode the header and claims given and sign the payload using the algorithm from the header and the key.
/// If the algorithm given is RSA or EC, the key needs to be in the PEM format. This produces a JWS instead of
/// a JWT -- usage is similar to `encode`, see that for more details.
pub fn encode<T: Serialize>(
header: &Header,
claims: Option<&T>,
key: &EncodingKey,
) -> Result<Jws<T>> {
if key.family() != header.alg.family() {
return Err(new_error(ErrorKind::InvalidAlgorithm));
}
let encoded_header = b64_encode_part(header)?;
let encoded_claims = match claims {
Some(claims) => b64_encode_part(claims)?,
None => "".to_string(),
};
let message = [encoded_header.as_str(), encoded_claims.as_str()].join(".");
let signature = sign(message.as_bytes(), key, header.alg)?;
Ok(Jws {
protected: encoded_header,
payload: encoded_claims,
signature,
_pd: Default::default(),
})
}
/// Validate a received JWS and decode into the header and claims.
pub fn decode<T: DeserializeOwned>(
jws: &Jws<T>,
key: &DecodingKey,
validation: &Validation,
) -> Result<TokenData<T>> {
let header = Header::from_encoded(&jws.protected)?;
let message = [jws.protected.as_str(), jws.payload.as_str()].join(".");
let verifying_provider = (CryptoProvider::get_default().verifier_factory)(&header.alg, key)?;
verify_signature_body(
message.as_bytes(),
jws.signature.as_bytes(),
&header,
validation,
verifying_provider,
)?;
let decoded_claims = DecodedJwtPartClaims::from_jwt_part_claims(&jws.payload)?;
let claims = decoded_claims.deserialize()?;
validate(decoded_claims.deserialize()?, validation)?;
Ok(TokenData { header, claims })
}