1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![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::*;