lite-session 1.0.0

Create Session Tokens that are Resilient to Misuse and Highjacking
Documentation
#![forbid(unsafe_code)]
#![deny(missing_docs)]

//! LiteSession is a token generator for secure tokens that can be used in
//! HTTP auth headers, cookies, in place of Json Web Tokens, in IoT and
//! anywhere else where secure tokens are needed for communication between
//! clients and servers. It provides Keyed-Hash Message authentication codes
//! with associated client data in either encrypted (default settings) or
//! unencrypted form.
//!
//! The general form of the algorithm is
//!
//! ```text
//! identifier | issued | expiry | (data)k | nonce | ConfidentialityMode | Blake3HMAC( username | issued | expiration | data | session key, k)
//!             where `k = Blake3HMAC(user | issued | expiry | ConfidentialityMode, sk)`
//! ```
//! The steps involved include:
//! 1. Generate a `random identifier`
//! 2. Generate an `issued time` and `expiry time` in nanoseconds accuracy
//! 3. generate the `encryption key` to encrypt the data portion of the token.
//! using algorithm  `k = Blake3HMAC(identifier | issued | expiry | ConfidentialityMode, sk)`
//!
//!     - Create an empty string `encryption_key`
//!     - Append `identifier` to `encryption_key`
//!     - Append `issued` to `encryption_key`
//!     - Append `expiry` to `encryption_key`
//!     - Append `ConfidentialityMode` to `encryption_key`
//!     - Perform a HMAC function to the `encryption_key` using Blake3 in keyed mode and the `server_key` as the key
//!     - Return the result of the Blake3 operation above in `hex` or as a `string`
//! 4. Encrypt the data using `ChaCha8` encryption using the Blake3Hash above as the encryption key
//! 5. Return the encrypted data and `nonce`
//! 6. Perform a Blake3Hmac on `identifier | issued | expiry | (data)k | nonce | ConfidentialityMode`
//! 7. Generate the token:
//!
//!     - Create an empty string called `token`
//!     - Append `identifier` to `token`
//!     - Append `issued` to `token`
//!     - Append `expiry` to `token`
//!     - Append `encrypted data` to `token`
//!     - Append `nonce` to `token`
//!     - Append `ConfidentialityMode` to `token`
//!     - Append `Blake3Hmac` to `token`
//!     - Return the token as a string or hex
//! The token generated is in the format `identifier⊕issued⊕expiry⊕ciphertext⊕nonce⊕confidentiality⊕hmac`
//!
//!
//! Verifying the token takes the following steps
//!
//! 1. Check if the token structure is valid
//! 2. Destructure the token into its component fields
//! 3. Compare the `expiry`  to the server's `current time` and return `SessionExpired` as the `TokenOutcome`
//! 4. Compute the encryption key as follows: `k=HMAC(identifier | issued | expiry | ConfidentialityMode, sk)`
//! 5. Decrypt the encrypted data using `k`.
//! 6. Compute `Blake3HMAC(identifier |issued | expiry | ciphertext | nonce | ConfidentialityMode | session key, k),`
//! 7. Return `TokenOutcome::TokenAuthetic` if the token matches or `TokenOutcome::TokenRejected` if the token does not match
//!
//!
//! The `Blake3` algorithm is used in `keyed` mode where the key is a `32byte/256bit` in length
//! The `ChaCha8` algorithm takes a `32byte/256bit` key and `12byte/96bit nonce`
//! `International Atomic Time(TAI)` is used for nanosecond accuracy and not having to deal with leap seconds and timezones
//! Using the `session key` prevents `volume` and `Denning-Sacco` attacks
//!
//!
//! ### Usage
//!
//!
//! #### Creating a token
//!
//! ```rust
//! use lite_session::{LiteSessionToken, LiteSessionError, ConfidentialityMode, LiteSessionData, Role, LiteSessionMode};
//! use core::time::Duration;
//!
//! fn main() -> Result<(), LiteSessionError> {
//!     let mut token = LiteSessionToken::default();
//!
//!     let expiry = 60*60_u64;
//!     token.expiry(expiry);
//!
//!     let mut data = LiteSessionData::default();
//!     data.username("foo_user");
//!     data.role(Role::SuperUser);
//!     data.tag("Foo-Tag");
//!     data.add_acl("Network-TCP");
//!     data.add_acl("Network-UDP");
//!     token.hmac_data(data);
//!     token.confidential(true);
//!     token.mode(LiteSessionMode::SessionID("foobarbaz".into()));
//!
//!     let server_key = [0_u8; 32];
//!     let session_token = token.build_secure(&server_key)?;
//!
//!     Ok(())
//! }
//! ```
//!
//!
//! #### Verifying a token
//!
//! ```rust
//! use lite_session::{LiteSessionToken, LiteSessionError, ConfidentialityMode, LiteSessionData, LiteSessionMode};
//! fn main() -> Result<(), LiteSessionError> {
//!     let server_key = [0_u8; 32];
//!
//!     let mut destructured = LiteSessionToken::default();
//!     let session_token = "5tl726krvgmhoe1pyc4jadqs3fw09bi8⊕40000000602e51ab3a8e2d17⊕40000000603013ab3a8e2d17⊕3cf157bed212d5b34122a713ea860ec373800e5004bff1a195d603305bd5b7921d1017e70ef599bc1f7ed949bd3c66c696d74a16487f95a3f6fd⊕jrzapflsi618⊕ConfidentialityMode::High⊕4faab373d7247dfb2d50e213e5cb66e415afc22066f71c2b966fdeabb11cac64";
//!     let outcome = destructured.from_string(&server_key, &session_token)?;
//!     
//!     Ok(())
//! }
//! ````
//!

mod ciphertext;
pub use ciphertext::*;
mod data;
pub use data::*;
mod errors;
pub use errors::*;
mod global;
pub use global::*;
mod mode;
pub use mode::*;
mod token;
pub use token::*;