diff options
Diffstat (limited to 'vendor/pasetors/src/lib.rs')
-rw-r--r-- | vendor/pasetors/src/lib.rs | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/vendor/pasetors/src/lib.rs b/vendor/pasetors/src/lib.rs new file mode 100644 index 0000000..eb29a71 --- /dev/null +++ b/vendor/pasetors/src/lib.rs @@ -0,0 +1,360 @@ +//! # Getting started +//! This library has two ways of working with tokens. The first is the [`local`] and [`public`] module, +//! which the below examples make use of. These use the latest version of PASETO for tokens, +//! along with [`claims::Claims`], to enable a straightforward way of defining common claims. +//! [`claims::ClaimsValidationRules`] lets you define validation rules, that are covered when using +//! the [`local`] and [`public`] module. Using these modules means that validation of registered +//! claims is handled automatically. +//! +//! If more control over the input is needed, and validation is handled manually, the [`version4`]/[`version2`] +//! module provide a lower-level interface, where payloads are be provided as byte-slices. +//! +//! NOTE: [`claims`], [`local`] and [`public`] modules are __only available with default-features enabled__. +//! ## Creating and verifying public tokens +//! ```rust +//! use pasetors::claims::{Claims, ClaimsValidationRules}; +//! use pasetors::keys::{Generate, AsymmetricKeyPair, AsymmetricSecretKey, AsymmetricPublicKey}; +//! use pasetors::{public, Public, version4::V4}; +//! use pasetors::token::{UntrustedToken, TrustedToken}; +//! use core::convert::TryFrom; +//! +//! // Setup the default claims, which include `iat` and `nbf` as the current time and `exp` of one hour. +//! // Add a custom `data` claim as well. +//! let mut claims = Claims::new()?; +//! claims.add_additional("data", "A public, signed message")?; +//! +//! // Generate the keys and sign the claims. +//! let kp = AsymmetricKeyPair::<V4>::generate()?; +//! let pub_token = public::sign(&kp.secret, &claims, None, Some(b"implicit assertion"))?; +//! +//! // Decide how we want to validate the claims after verifying the token itself. +//! // The default verifies the `nbf`, `iat` and `exp` claims. `nbf` and `iat` are always +//! // expected to be present. +//! // NOTE: Custom claims, defined through `add_additional()`, are not validated. This must be done +//! // manually. +//! let validation_rules = ClaimsValidationRules::new(); +//! let untrusted_token = UntrustedToken::<Public, V4>::try_from(&pub_token)?; +//! let trusted_token = public::verify(&kp.public, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?; +//! assert_eq!(&claims, trusted_token.payload_claims().unwrap()); +//! +//! let claims = trusted_token.payload_claims().unwrap(); +//! +//! println!("{:?}", claims.get_claim("data")); +//! println!("{:?}", claims.get_claim("iat")); +//! +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` + +//! ## Creating and verifying local tokens +//! ```rust +//! use pasetors::claims::{Claims, ClaimsValidationRules}; +//! use pasetors::keys::{Generate, SymmetricKey}; +//! use pasetors::{local, Local, version4::V4}; +//! use pasetors::token::UntrustedToken; +//! use core::convert::TryFrom; +//! +//! // Setup the default claims, which include `iat` and `nbf` as the current time and `exp` of one hour. +//! // Add a custom `data` claim as well. +//! let mut claims = Claims::new()?; +//! claims.add_additional("data", "A secret, encrypted message")?; +//! +//! // Generate the key and encrypt the claims. +//! let sk = SymmetricKey::<V4>::generate()?; +//! let token = local::encrypt(&sk, &claims, None, Some(b"implicit assertion"))?; +//! +//! // Decide how we want to validate the claims after verifying the token itself. +//! // The default verifies the `nbf`, `iat` and `exp` claims. `nbf` and `iat` are always +//! // expected to be present. +//! // NOTE: Custom claims, defined through `add_additional()`, are not validated. This must be done +//! // manually. +//! let validation_rules = ClaimsValidationRules::new(); +//! let untrusted_token = UntrustedToken::<Local, V4>::try_from(&token)?; +//! let trusted_token = local::decrypt(&sk, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?; +//! assert_eq!(&claims, trusted_token.payload_claims().unwrap()); +//! +//! let claims = trusted_token.payload_claims().unwrap(); +//! +//! println!("{:?}", claims.get_claim("data")); +//! println!("{:?}", claims.get_claim("iat")); +//! +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` + +//! ## Additional claims and their validation +//! +//! ### Setting registered claims and how to validate them +//! ```rust +//! use pasetors::claims::{Claims, ClaimsValidationRules}; +//! +//! // `iat`, `nbf` and `exp` have been set automatically, but could also be overridden. +//! let mut claims = Claims::new()?; +//! claims.issuer("paragonie.com")?; +//! claims.subject("test")?; +//! claims.audience("pie-hosted.com")?; +//! claims.expiration("2039-01-01T00:00:00+00:00")?; +//! claims.not_before("2038-04-01T00:00:00+00:00")?; +//! claims.issued_at("2038-03-17T00:00:00+00:00")?; +//! claims.token_identifier("87IFSGFgPNtQNNuw0AtuLttPYFfYwOkjhqdWcLoYQHvL")?; +//! +//! let mut validation_rules = ClaimsValidationRules::new(); +//! validation_rules.validate_issuer_with("paragonie.com"); +//! validation_rules.validate_subject_with("test"); +//! validation_rules.validate_audience_with("pie-hosted.com"); +//! validation_rules.validate_token_identifier_with("87IFSGFgPNtQNNuw0AtuLttPYFfYwOkjhqdWcLoYQHvL"); +//! +//! // The token has been set to be issued in the future and not valid yet, so validation fails. +//! assert!(validation_rules.validate_claims(&claims).is_err()); +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` +//! ### Non-expiring tokens +//! ```rust +//! use pasetors::claims::{Claims, ClaimsValidationRules}; +//! +//! // Non-expiring tokens +//! let mut claims = Claims::new()?; +//! claims.add_additional("data", "A public, signed message")?; +//! claims.non_expiring(); +//! // Now claims can be validated as non-expiring when we define the validation rule as: +//! let mut validation_rules = ClaimsValidationRules::new(); +//! validation_rules.allow_non_expiring(); +//! +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` + +//! ## Footer with registered and custom claims +//! ```rust +//! use pasetors::paserk::{FormatAsPaserk, Id}; +//! use pasetors::claims::{Claims, ClaimsValidationRules}; +//! use pasetors::footer::Footer; +//! use pasetors::keys::{Generate, AsymmetricKeyPair}; +//! use pasetors::{public, Public, version4::V4}; +//! use pasetors::token::UntrustedToken; +//! use core::convert::TryFrom; +//! +//! // Generate the key used to later sign a token. +//! let kp = AsymmetricKeyPair::<V4>::generate()?; +//! // Serialize the public key to PASERK "pid". +//! let mut pid = Id::from(&kp.public); +//! // Add the "pid" to the "kid" claim of a footer. +//! let mut footer = Footer::new(); +//! footer.key_id(&pid); +//! footer.add_additional("custom_footer_claim", "custom_value")?; +//! +//! let mut claims = Claims::new()?; +//! let pub_token = public::sign(&kp.secret, &claims, Some(&footer), Some(b"implicit assertion"))?; +//! +//! // If we receive a token that needs to be verified, we can still try to parse a Footer from it +//! // as long one was used during creation, if we don't know it beforehand. +//! let validation_rules = ClaimsValidationRules::new(); +//! let untrusted_token = UntrustedToken::<Public, V4>::try_from(&pub_token)?; +//! let trusted_token = public::verify(&kp.public, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?; +//! let trusted_footer = Footer::try_from(&trusted_token)?; +//! +//! let mut kid = String::new(); +//! pid.fmt(&mut kid).unwrap(); +//! assert_eq!(trusted_footer.get_claim("kid").unwrap().as_str().unwrap(), kid); +//! +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` + +//! ## PASERK serialization +//! ```rust +//! use pasetors::paserk::FormatAsPaserk; +//! use pasetors::keys::{Generate, SymmetricKey}; +//! use pasetors::version4::V4; +//! use core::convert::TryFrom; +//! +//! // Generate the key and serialize to and from PASERK. +//! let sk = SymmetricKey::<V4>::generate()?; +//! let mut paserk = String::new(); +//! sk.fmt(&mut paserk).unwrap(); +//! let sk = SymmetricKey::<V4>::try_from(paserk.as_str())?; +//! +//! # Ok::<(), pasetors::errors::Error>(()) +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] +#![forbid(unsafe_code)] +#![deny(clippy::mem_forget)] +#![warn( + missing_docs, + rust_2018_idioms, + trivial_casts, + unused_qualifications, + overflowing_literals +)] +#![doc(html_root_url = "https://docs.rs/pasetors/0.6.7")] +#![cfg_attr(docsrs, feature(doc_cfg))] + +#[macro_use] +extern crate alloc; + +mod pae; + +/// Errors for token operations. +pub mod errors; + +mod common; + +#[cfg(feature = "std")] +/// Claims for tokens and validation thereof. +pub mod claims; + +#[cfg(feature = "std")] +/// Footer for tokens. +pub mod footer; + +/// Keys used for PASETO tokens. +pub mod keys; + +#[cfg(feature = "paserk")] +/// PASERK key-wrapping and serialization. +pub mod paserk; + +#[cfg(feature = "v2")] +/// PASETO version 2 tokens. +pub mod version2; + +#[cfg(feature = "v3")] +/// PASETO version 3 tokens. +pub mod version3; + +#[cfg(feature = "v4")] +/// PASETO version 4 tokens. +pub mod version4; + +/// Types for handling tokens. +pub mod token; + +#[cfg(feature = "serde")] +/// Serialization and deserialization support for various types. +mod serde; + +mod version; + +/// Public and local tokens. +pub use token::{Local, Public}; + +#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "v4"))))] +#[cfg(all(feature = "std", feature = "v4"))] +/// PASETO public tokens with [`version4`], using [`claims::Claims`]. +pub mod public { + use super::*; + use crate::claims::{Claims, ClaimsValidationRules}; + use crate::errors::Error; + use crate::footer::Footer; + use crate::keys::{AsymmetricPublicKey, AsymmetricSecretKey}; + use crate::token::{TrustedToken, UntrustedToken}; + use crate::version4::V4; + + /// Create a public token using the latest PASETO version (v4). + pub fn sign( + secret_key: &AsymmetricSecretKey<V4>, + message: &Claims, + footer: Option<&Footer>, + implicit_assert: Option<&[u8]>, + ) -> Result<String, Error> { + match footer { + Some(f) => crate::version4::PublicToken::sign( + secret_key, + message.to_string()?.as_bytes(), + Some(f.to_string()?.as_bytes()), + implicit_assert, + ), + None => crate::version4::PublicToken::sign( + secret_key, + message.to_string()?.as_bytes(), + None, + implicit_assert, + ), + } + } + + /// Verify a public token using the latest PASETO version (v4). If verification passes, + /// validate the claims according to the `validation_rules`. + pub fn verify( + public_key: &AsymmetricPublicKey<V4>, + token: &UntrustedToken<Public, V4>, + validation_rules: &ClaimsValidationRules, + footer: Option<&Footer>, + implicit_assert: Option<&[u8]>, + ) -> Result<TrustedToken, Error> { + let mut trusted_token = match footer { + Some(f) => crate::version4::PublicToken::verify( + public_key, + token, + Some(f.to_string()?.as_bytes()), + implicit_assert, + )?, + None => crate::version4::PublicToken::verify(public_key, token, None, implicit_assert)?, + }; + + let claims = Claims::from_string(trusted_token.payload())?; + validation_rules.validate_claims(&claims)?; + trusted_token.set_payload_claims(claims); + + Ok(trusted_token) + } +} + +#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "v4"))))] +#[cfg(all(feature = "std", feature = "v4"))] +/// PASETO local tokens with [`version4`], using [`claims::Claims`]. +pub mod local { + use super::*; + use crate::claims::{Claims, ClaimsValidationRules}; + use crate::errors::Error; + use crate::footer::Footer; + use crate::keys::SymmetricKey; + use crate::token::{TrustedToken, UntrustedToken}; + use crate::version4::V4; + + /// Create a local token using the latest PASETO version (v4). + pub fn encrypt( + secret_key: &SymmetricKey<V4>, + message: &Claims, + footer: Option<&Footer>, + implicit_assert: Option<&[u8]>, + ) -> Result<String, Error> { + match footer { + Some(f) => crate::version4::LocalToken::encrypt( + secret_key, + message.to_string()?.as_bytes(), + Some(f.to_string()?.as_bytes()), + implicit_assert, + ), + None => crate::version4::LocalToken::encrypt( + secret_key, + message.to_string()?.as_bytes(), + None, + implicit_assert, + ), + } + } + + /// Verify a local token using the latest PASETO version (v4). If verification passes, + /// validate the claims according to the `validation_rules`. + pub fn decrypt( + secret_key: &SymmetricKey<V4>, + token: &UntrustedToken<Local, V4>, + validation_rules: &ClaimsValidationRules, + footer: Option<&Footer>, + implicit_assert: Option<&[u8]>, + ) -> Result<TrustedToken, Error> { + let mut trusted_token = match footer { + Some(f) => crate::version4::LocalToken::decrypt( + secret_key, + token, + Some(f.to_string()?.as_bytes()), + implicit_assert, + )?, + None => crate::version4::LocalToken::decrypt(secret_key, token, None, implicit_assert)?, + }; + + let claims = Claims::from_string(trusted_token.payload())?; + validation_rules.validate_claims(&claims)?; + trusted_token.set_payload_claims(claims); + + Ok(trusted_token) + } +} |