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
//! 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(())
//! }
//! ````
//!
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;