openzeppelin_relayer/utils/serde/
repository_encryption.rs1use secrets::SecretVec;
4use serde::{Deserialize, Deserializer, Serializer};
5
6use crate::{
7 models::SecretString,
8 utils::{base64_decode, base64_encode, decrypt_sensitive_field, encrypt_sensitive_field},
9};
10
11pub fn serialize_secret_vec<S>(secret: &SecretVec<u8>, serializer: S) -> Result<S::Ok, S::Error>
13where
14 S: Serializer,
15{
16 let base64 = base64_encode(secret.borrow().as_ref());
18
19 let encrypted = encrypt_sensitive_field(&base64)
21 .map_err(|e| serde::ser::Error::custom(format!("Encryption failed: {}", e)))?;
22
23 serializer.serialize_str(&encrypted)
24}
25
26pub fn deserialize_secret_vec<'de, D>(deserializer: D) -> Result<SecretVec<u8>, D::Error>
28where
29 D: Deserializer<'de>,
30{
31 let encrypted_str = String::deserialize(deserializer)?;
32
33 let base64_str = decrypt_sensitive_field(&encrypted_str)
35 .map_err(|e| serde::de::Error::custom(format!("Decryption failed: {}", e)))?;
36
37 let decoded = base64_decode(&base64_str)
39 .map_err(|e| serde::de::Error::custom(format!("Invalid base64: {}", e)))?;
40
41 Ok(SecretVec::new(decoded.len(), |v| {
42 v.copy_from_slice(&decoded)
43 }))
44}
45
46pub fn serialize_secret_string<S>(secret: &SecretString, serializer: S) -> Result<S::Ok, S::Error>
48where
49 S: Serializer,
50{
51 let secret_content = secret.to_str();
52 let encrypted = encrypt_sensitive_field(&secret_content)
53 .map_err(|e| serde::ser::Error::custom(format!("Encryption failed: {}", e)))?;
54
55 let encoded = base64_encode(encrypted.as_bytes());
56
57 serializer.serialize_str(&encoded)
58}
59
60pub fn deserialize_secret_string<'de, D>(deserializer: D) -> Result<SecretString, D::Error>
62where
63 D: Deserializer<'de>,
64{
65 let base64_str = String::deserialize(deserializer)?;
66
67 let encrypted_bytes = base64_decode(&base64_str)
69 .map_err(|e| serde::de::Error::custom(format!("Invalid base64: {}", e)))?;
70
71 let encrypted_str = String::from_utf8(encrypted_bytes)
73 .map_err(|e| serde::de::Error::custom(format!("Invalid UTF-8: {}", e)))?;
74
75 let decrypted = decrypt_sensitive_field(&encrypted_str)
77 .map_err(|e| serde::de::Error::custom(format!("Decryption failed: {}", e)))?;
78
79 Ok(SecretString::new(&decrypted))
80}
81
82pub fn serialize_option_secret_string<S>(
84 secret: &Option<SecretString>,
85 serializer: S,
86) -> Result<S::Ok, S::Error>
87where
88 S: Serializer,
89{
90 match secret {
91 Some(secret_string) => {
92 let secret_content = secret_string.to_str();
93 let encrypted = encrypt_sensitive_field(&secret_content)
94 .map_err(|e| serde::ser::Error::custom(format!("Encryption failed: {}", e)))?;
95
96 let encoded = base64_encode(encrypted.as_bytes());
97 serializer.serialize_some(&encoded)
98 }
99 None => serializer.serialize_none(),
100 }
101}
102
103pub fn deserialize_option_secret_string<'de, D>(
105 deserializer: D,
106) -> Result<Option<SecretString>, D::Error>
107where
108 D: Deserializer<'de>,
109{
110 let opt_base64_str: Option<String> = Option::deserialize(deserializer)?;
111
112 match opt_base64_str {
113 Some(base64_str) => {
114 let encrypted_bytes = base64_decode(&base64_str)
116 .map_err(|e| serde::de::Error::custom(format!("Invalid base64: {}", e)))?;
117
118 let encrypted_str = String::from_utf8(encrypted_bytes)
120 .map_err(|e| serde::de::Error::custom(format!("Invalid UTF-8: {}", e)))?;
121
122 let decrypted = decrypt_sensitive_field(&encrypted_str)
124 .map_err(|e| serde::de::Error::custom(format!("Decryption failed: {}", e)))?;
125
126 Ok(Some(SecretString::new(&decrypted)))
127 }
128 None => Ok(None),
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use secrets::SecretVec;
136 use serde_json;
137
138 #[test]
139 fn test_serialize_deserialize_secret_string() {
140 let secret = SecretString::new("test-secret-content");
141
142 #[derive(serde::Serialize, serde::Deserialize)]
144 struct TestStruct {
145 #[serde(
146 serialize_with = "serialize_secret_string",
147 deserialize_with = "deserialize_secret_string"
148 )]
149 secret: SecretString,
150 }
151
152 let test_struct = TestStruct {
153 secret: secret.clone(),
154 };
155
156 let serialized = serde_json::to_string(&test_struct).unwrap();
158
159 let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
161
162 assert_eq!(secret.to_str(), deserialized.secret.to_str());
164 }
165
166 #[test]
167 fn test_serialize_deserialize_secret_vec() {
168 let original_data = vec![1, 2, 3, 4, 5];
169 let secret = SecretVec::new(original_data.len(), |v| v.copy_from_slice(&original_data));
170
171 #[derive(serde::Serialize, serde::Deserialize)]
173 struct TestStruct {
174 #[serde(
175 serialize_with = "serialize_secret_vec",
176 deserialize_with = "deserialize_secret_vec"
177 )]
178 secret_data: SecretVec<u8>,
179 }
180
181 let test_struct = TestStruct {
182 secret_data: secret,
183 };
184
185 let serialized = serde_json::to_string(&test_struct).unwrap();
187
188 let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
190
191 let original_borrowed = original_data;
193 let deserialized_borrowed = deserialized.secret_data.borrow();
194 assert_eq!(original_borrowed, *deserialized_borrowed);
195 }
196
197 #[test]
198 fn test_serialize_deserialize_option_secret_string_some() {
199 let secret = SecretString::new("test-optional-secret");
200
201 #[derive(serde::Serialize, serde::Deserialize)]
203 struct TestStruct {
204 #[serde(
205 serialize_with = "serialize_option_secret_string",
206 deserialize_with = "deserialize_option_secret_string"
207 )]
208 optional_secret: Option<SecretString>,
209 }
210
211 let test_struct = TestStruct {
212 optional_secret: Some(secret.clone()),
213 };
214
215 let serialized = serde_json::to_string(&test_struct).unwrap();
217
218 let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
220
221 assert!(deserialized.optional_secret.is_some());
223 assert_eq!(
224 secret.to_str(),
225 deserialized.optional_secret.unwrap().to_str()
226 );
227 }
228
229 #[test]
230 fn test_serialize_deserialize_option_secret_string_none() {
231 let secret: Option<SecretString> = None;
232
233 #[derive(serde::Serialize, serde::Deserialize)]
235 struct TestStruct {
236 #[serde(
237 serialize_with = "serialize_option_secret_string",
238 deserialize_with = "deserialize_option_secret_string"
239 )]
240 optional_secret: Option<SecretString>,
241 }
242
243 let test_struct = TestStruct {
244 optional_secret: secret,
245 };
246
247 let serialized = serde_json::to_string(&test_struct).unwrap();
249
250 let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
252
253 assert!(deserialized.optional_secret.is_none());
255 }
256
257 #[test]
258 fn test_round_trip_secret_string() {
259 let original = SecretString::new("complex-secret-with-special-chars-!@#$%^&*()");
260
261 #[derive(serde::Serialize, serde::Deserialize)]
262 struct TestStruct {
263 #[serde(
264 serialize_with = "serialize_secret_string",
265 deserialize_with = "deserialize_secret_string"
266 )]
267 secret: SecretString,
268 }
269
270 let test_struct = TestStruct {
271 secret: original.clone(),
272 };
273
274 let json = serde_json::to_string(&test_struct).unwrap();
276
277 let deserialized: TestStruct = serde_json::from_str(&json).unwrap();
279
280 assert_eq!(original.to_str(), deserialized.secret.to_str());
282 }
283
284 #[test]
285 fn test_round_trip_option_secret_string_with_multiple_values() {
286 let test_cases = vec![
287 Some(SecretString::new("test1")),
288 None,
289 Some(SecretString::new("")),
290 Some(SecretString::new("test-with-unicode-🔐")),
291 Some(SecretString::new(&"very-long-secret-".repeat(100))),
292 ];
293
294 #[derive(serde::Serialize, serde::Deserialize)]
295 struct TestStruct {
296 #[serde(
297 serialize_with = "serialize_option_secret_string",
298 deserialize_with = "deserialize_option_secret_string"
299 )]
300 optional_secret: Option<SecretString>,
301 }
302
303 for test_case in test_cases {
304 let test_struct = TestStruct {
305 optional_secret: test_case.clone(),
306 };
307
308 let json = serde_json::to_string(&test_struct).unwrap();
310
311 let deserialized: TestStruct = serde_json::from_str(&json).unwrap();
313
314 match (test_case, deserialized.optional_secret) {
316 (Some(original), Some(deserialized_secret)) => {
317 assert_eq!(original.to_str(), deserialized_secret.to_str());
318 }
319 (None, None) => {
320 }
322 _ => panic!("Mismatch between original and deserialized optional secret"),
323 }
324 }
325 }
326
327 #[test]
328 fn test_serialized_content_is_encrypted() {
329 let secret = SecretString::new("plaintext-secret");
330
331 #[derive(serde::Serialize)]
332 struct TestStruct {
333 #[serde(serialize_with = "serialize_secret_string")]
334 secret: SecretString,
335 }
336
337 let test_struct = TestStruct { secret };
338 let json = serde_json::to_string(&test_struct).unwrap();
339
340 assert!(!json.contains("plaintext-secret"));
342
343 let json_value: serde_json::Value = serde_json::from_str(&json).unwrap();
345 let serialized_secret = json_value["secret"].as_str().unwrap();
346
347 assert!(base64_decode(serialized_secret).is_ok());
349 }
350
351 #[test]
352 fn test_serialized_option_content_when_some() {
353 let secret = Some(SecretString::new("plaintext-secret"));
354
355 #[derive(serde::Serialize)]
356 struct TestStruct {
357 #[serde(serialize_with = "serialize_option_secret_string")]
358 optional_secret: Option<SecretString>,
359 }
360
361 let test_struct = TestStruct {
362 optional_secret: secret,
363 };
364 let json = serde_json::to_string(&test_struct).unwrap();
365
366 assert!(!json.contains("plaintext-secret"));
368
369 let json_value: serde_json::Value = serde_json::from_str(&json).unwrap();
371 assert!(json_value["optional_secret"].is_string());
372
373 let serialized_secret = json_value["optional_secret"].as_str().unwrap();
374 assert!(base64_decode(serialized_secret).is_ok());
376 }
377
378 #[test]
379 fn test_serialized_option_content_when_none() {
380 let secret: Option<SecretString> = None;
381
382 #[derive(serde::Serialize)]
383 struct TestStruct {
384 #[serde(serialize_with = "serialize_option_secret_string")]
385 optional_secret: Option<SecretString>,
386 }
387
388 let test_struct = TestStruct {
389 optional_secret: secret,
390 };
391 let json = serde_json::to_string(&test_struct).unwrap();
392
393 let json_value: serde_json::Value = serde_json::from_str(&json).unwrap();
395 assert!(json_value["optional_secret"].is_null());
396 }
397}