securedrop_protocol_minimal/
storage.rs1use alloc::vec::Vec;
2use hashbrown::HashMap;
3use rand_core::{CryptoRng, RngCore};
4use uuid::Uuid;
5
6use crate::message::MessagePublicKey;
7use crate::primitives::ristretto255::DHPublicKey;
8use crate::sign::{JournalistLongTermKey, NewsroomOnJournalist, Signature, VerifyingKey};
9use crate::{Enrollment, Envelope, SignedKeyBundlePublic, SignedLongtermKeyBundle};
10
11pub type ServerMessageStore = HashMap<Uuid, Envelope>;
12
13#[derive(Default)]
14pub struct ServerStorage {
15 journalists: HashMap<
17 Uuid,
18 (
19 VerifyingKey,
20 SignedLongtermKeyBundle,
21 Signature<NewsroomOnJournalist>,
22 ),
23 >,
24
25 ephemeral_keys: HashMap<Uuid, Vec<SignedKeyBundlePublic>>,
30
31 messages: HashMap<Uuid, Envelope>,
33}
34
35impl ServerStorage {
36 pub fn new() -> Self {
38 Self::default()
39 }
40
41 pub fn add_ephemeral_keys(&mut self, journalist_id: Uuid, keys: Vec<SignedKeyBundlePublic>) {
43 let journalist_keys = self
44 .ephemeral_keys
45 .entry(journalist_id)
46 .or_insert(Vec::new());
48 journalist_keys.extend(keys);
49 }
50
51 pub fn pop_random_ephemeral_keys<R: RngCore + CryptoRng>(
57 &mut self,
58 journalist_id: Uuid,
59 rng: &mut R,
60 ) -> Option<SignedKeyBundlePublic> {
61 if let Some(keys) = self.ephemeral_keys.get_mut(&journalist_id) {
62 if keys.is_empty() {
63 return None;
64 }
65
66 let index = rng.next_u32() as usize % keys.len();
68
69 Some(keys.remove(index))
71 } else {
72 None
73 }
74 }
75
76 pub fn get_all_ephemeral_keys<R: RngCore + CryptoRng>(
83 &mut self,
84 rng: &mut R,
85 ) -> Vec<(Uuid, SignedKeyBundlePublic)> {
86 let mut result = Vec::new();
87 let journalist_ids: Vec<Uuid> = self.ephemeral_keys.keys().copied().collect();
88
89 for journalist_id in journalist_ids {
90 if let Some(keys) = self.pop_random_ephemeral_keys(journalist_id, rng) {
91 result.push((journalist_id, keys));
92 }
93 }
94
95 result
96 }
97
98 pub fn ephemeral_keys_count(&self, journalist_id: Uuid) -> usize {
100 self.ephemeral_keys
101 .get(&journalist_id)
102 .map_or(0, |keys| keys.len())
103 }
104
105 pub fn has_ephemeral_keys(&self, journalist_id: Uuid) -> bool {
107 self.ephemeral_keys_count(journalist_id) > 0
108 }
109
110 pub fn get_journalists(
112 &self,
113 ) -> &HashMap<
114 Uuid,
115 (
116 VerifyingKey,
117 SignedLongtermKeyBundle,
118 Signature<NewsroomOnJournalist>,
119 ),
120 > {
121 &self.journalists
122 }
123
124 pub fn add_journalist(
126 &mut self,
127 journalist: Enrollment,
128 newsroom_signature: Signature<NewsroomOnJournalist>,
129 ) -> Uuid {
130 let journalist_id = Uuid::new_v4();
131
132 let bundle = journalist.bundle;
134 let values = (journalist.verification_key, bundle, newsroom_signature);
135
136 self.journalists.insert(journalist_id, values);
137 journalist_id
138 }
139
140 pub fn find_journalist_by_verifying_key(&self, verifying_key: &VerifyingKey) -> Option<Uuid> {
145 for (journalist_id, (stored_vk, _, _)) in &self.journalists {
146 if stored_vk.into_bytes() == verifying_key.into_bytes() {
147 return Some(*journalist_id);
148 }
149 }
150 None
151 }
152
153 pub(crate) fn deterministic_uuid<R: RngCore + CryptoRng>(&mut self, rng: &mut R) -> Uuid {
154 let mut bytes = [0u8; 16];
155 rng.fill_bytes(&mut bytes);
156
157 uuid::Builder::from_random_bytes(bytes).into_uuid()
158 }
159
160 pub fn get_messages(&self) -> &HashMap<Uuid, Envelope> {
162 &self.messages
163 }
164
165 pub fn add_message(&mut self, message_id: Uuid, message: Envelope) {
167 self.messages.insert(message_id, message);
168 }
169}