redact_crypto/nonce/
sodiumoxide.rs1use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
2use sodiumoxide::crypto::{
3 box_::{self, Nonce as ExternalAsymmetricNonce, NONCEBYTES as EXTERNALASYMMETRICNONCEBYTES},
4 secretbox::{self, Nonce as ExternalSymmetricNonce, NONCEBYTES as EXTERNALSYMMETRICNONCEBYTES},
5};
6
7#[derive(Serialize, Deserialize, Debug, Clone)]
8pub struct SodiumOxideSymmetricNonce {
9 #[serde(
10 serialize_with = "symmetric_nonce_serialize",
11 deserialize_with = "symmetric_nonce_deserialize"
12 )]
13 pub nonce: ExternalSymmetricNonce,
14}
15
16fn symmetric_nonce_serialize<S>(nonce: &ExternalSymmetricNonce, s: S) -> Result<S::Ok, S::Error>
18where
19 S: Serializer,
20{
21 let b64_encoded = base64::encode(nonce.as_ref());
22 s.serialize_some(&Some(b64_encoded))
23}
24
25fn symmetric_nonce_deserialize<'de, D>(deserializer: D) -> Result<ExternalSymmetricNonce, D::Error>
27where
28 D: Deserializer<'de>,
29{
30 let b64_encoded: String = de::Deserialize::deserialize(deserializer)?;
31 let decoded = base64::decode(b64_encoded).map_err(de::Error::custom)?;
32 let nonce = ExternalSymmetricNonce::from_slice(decoded.as_ref());
33 match nonce {
34 Some(n) => Ok(n),
35 None => Err(de::Error::custom(format!(
36 "deserialized nonce was {} bytes long, expected 24 bytes",
37 decoded.len()
38 ))),
39 }
40}
41
42impl SodiumOxideSymmetricNonce {
43 pub const NONCEBYTES: usize = EXTERNALSYMMETRICNONCEBYTES;
44
45 pub fn from_slice(bs: &[u8]) -> Option<Self> {
46 Some(SodiumOxideSymmetricNonce {
47 nonce: ExternalSymmetricNonce::from_slice(bs)?,
48 })
49 }
50
51 pub fn new() -> Self {
52 SodiumOxideSymmetricNonce {
53 nonce: secretbox::gen_nonce(),
54 }
55 }
56}
57
58#[derive(Serialize, Deserialize, Debug, Clone)]
59pub struct SodiumOxideAsymmetricNonce {
60 #[serde(
61 serialize_with = "asymmetric_nonce_serialize",
62 deserialize_with = "asymmetric_nonce_deserialize"
63 )]
64 pub nonce: ExternalAsymmetricNonce,
65}
66
67fn asymmetric_nonce_serialize<S>(nonce: &ExternalAsymmetricNonce, s: S) -> Result<S::Ok, S::Error>
69where
70 S: Serializer,
71{
72 let b64_encoded = base64::encode(nonce.as_ref());
73 s.serialize_some(&Some(b64_encoded))
74}
75
76fn asymmetric_nonce_deserialize<'de, D>(
78 deserializer: D,
79) -> Result<ExternalAsymmetricNonce, D::Error>
80where
81 D: Deserializer<'de>,
82{
83 let b64_encoded: String = de::Deserialize::deserialize(deserializer)?;
84 let decoded = base64::decode(b64_encoded).map_err(de::Error::custom)?;
85 let nonce = ExternalAsymmetricNonce::from_slice(decoded.as_ref());
86 match nonce {
87 Some(n) => Ok(n),
88 None => Err(de::Error::custom(format!(
89 "deserialized nonce was {} bytes long, expected 24 bytes",
90 decoded.len()
91 ))),
92 }
93}
94
95impl SodiumOxideAsymmetricNonce {
96 pub const NONCEBYTES: usize = EXTERNALASYMMETRICNONCEBYTES;
97
98 pub fn from_slice(bs: &[u8]) -> Option<Self> {
99 Some(SodiumOxideAsymmetricNonce {
100 nonce: ExternalAsymmetricNonce::from_slice(bs)?,
101 })
102 }
103
104 pub fn new() -> Self {
105 SodiumOxideAsymmetricNonce {
106 nonce: box_::gen_nonce(),
107 }
108 }
109}