Skip to main content

mesh_session/
lib.rs

1use base64::{engine::general_purpose, Engine as _};
2use hmac::{Hmac, Mac};
3use sha2::Sha256;
4use subtle::ConstantTimeEq;
5
6#[cfg(feature = "enterprise")]
7pub mod enterprise;
8
9// Note: enterprise placeholder does not pull extra crates by default.
10
11type HmacSha256 = Hmac<Sha256>;
12
13pub fn issue_simple_token(secret: &[u8], session_id: &str, consumer_did: &str, provider_did: &str) -> String {
14    let mut mac = HmacSha256::new_from_slice(secret).expect("HMAC can take key of any size");
15    let msg = format!("{}|{}|{}", session_id, consumer_did, provider_did);
16    mac.update(msg.as_bytes());
17    let result = mac.finalize().into_bytes();
18    general_purpose::URL_SAFE_NO_PAD.encode(result)
19}
20
21pub fn validate_simple_token(token: &str, secret: &[u8], session_id: &str, consumer_did: &str, provider_did: &str) -> bool {
22    let expected = issue_simple_token(secret, session_id, consumer_did, provider_did);
23    // constant time compare
24    expected.as_bytes().ct_eq(token.as_bytes()).into()
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn roundtrip_token() {
33        let secret = b"supersecret";
34        let token = issue_simple_token(secret, "sess-1", "did:mesh:agent:consumer", "did:mesh:agent:provider");
35        assert!(validate_simple_token(&token, secret, "sess-1", "did:mesh:agent:consumer", "did:mesh:agent:provider"));
36    }
37}