ncryptf/shared/
mod.rs

1use crate::{Keypair, Signature};
2use base64::{engine::general_purpose, Engine as _};
3use rand::{distr::Alphanumeric, Rng};
4use serde::{Deserialize, Serialize};
5
6/// The Ncryptf JSON content type
7pub const NCRYPTF_CONTENT_TYPE: &str = "application/vnd.ncryptf+json";
8
9/// The amount of time (in either direction) a request time may differ by and still be accepted.
10pub const NCRYPTF_DRIFT_ALLOWANCE: i32 = 90;
11
12/// Reusable encryption key data for client parsing
13///
14/// This is exported for use in your application for deserializing the request.
15#[derive(Serialize, Deserialize, Clone, Debug)]
16pub struct ExportableEncryptionKeyData {
17    pub public: String,
18    pub signature: String,
19    pub hash_id: String,
20    pub expires_at: i64,
21    pub ephemeral: bool,
22}
23
24impl ExportableEncryptionKeyData {
25    /// Returns true if this key is expired
26    pub fn is_expired(&self) -> bool {
27        return chrono::Utc::now().timestamp() >= self.expires_at;
28    }
29
30    /// Returns the public key as a Vec
31    pub fn get_public_key(&self) -> Option<Vec<u8>> {
32        if self.public.is_empty() {
33            return None;
34        }
35
36        return Some(general_purpose::STANDARD.decode(self.public.clone()).unwrap());
37    }
38
39    /// Returns the signature key as a Vec
40    pub fn get_signature_key(&self) -> Option<Vec<u8>> {
41        if self.public.is_empty() {
42            return None;
43        }
44
45        return Some(general_purpose::STANDARD.decode(self.signature.clone()).unwrap());
46    }
47}
48
49/// Represents an Encryption key used to encrypt and decrypt requests
50#[derive(Serialize, Deserialize, Debug, Clone)]
51pub struct EncryptionKey {
52    bkp: Keypair,
53    skp: Keypair,
54    ephemeral: bool,
55    pub expires_at: i64,
56    hash_id: String,
57}
58
59impl EncryptionKey {
60    /// Returns the box keypair
61    pub fn get_box_kp(&self) -> Keypair {
62        return self.bkp.clone();
63    }
64
65    /// Returns the signing keypair
66    pub fn get_sign_kp(&self) -> Keypair {
67        return self.skp.clone();
68    }
69
70    /// Returns true if the key is meant to be used only once
71    pub fn is_ephemeral(&self) -> bool {
72        return self.ephemeral;
73    }
74
75    /// Returns the hash id
76    pub fn get_hash_id(&self) -> String {
77        return self.hash_id.clone();
78    }
79
80    /// Returns true if the token is expired
81    /// Expiration should be handled server side
82    /// But the client should know if they need a new key
83    pub fn is_expired(&self) -> bool {
84        if chrono::Utc::now().timestamp() >= self.expires_at {
85            return true;
86        }
87
88        return false;
89    }
90
91    /// Creates a new struct with an ephemeral flag set
92    pub fn new(ephemeral: bool) -> Self {
93        let s: String = rand::rng()
94            .sample_iter(&Alphanumeric)
95            .take(24)
96            .map(char::from)
97            .collect();
98
99        // Encryption keys are valid for an hour
100        let expiration = chrono::Utc::now() + chrono::Duration::hours(1);
101        return Self {
102            bkp: Keypair::new(),
103            skp: Signature::new(),
104            ephemeral: ephemeral,
105            expires_at: expiration.timestamp(),
106            hash_id: s,
107        };
108    }
109}