1use zeroize::{Zeroize, ZeroizeOnDrop};
7
8use crate::constants::{
9 CRYPTO_BOX_BEFORENMBYTES, CRYPTO_BOX_PUBLICKEYBYTES, CRYPTO_BOX_SECRETKEYBYTES,
10};
11use crate::types::{ByteArray, Bytes, MutByteArray, MutBytes, StackByteArray};
12
13type InnerKey = StackByteArray<CRYPTO_BOX_BEFORENMBYTES>;
14
15#[derive(Zeroize, ZeroizeOnDrop, Debug, PartialEq, Eq, Clone)]
26pub struct PrecalcSecretKey<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize>(InnerKey);
27
28impl<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Bytes + Zeroize> Bytes
29 for PrecalcSecretKey<InnerKey>
30{
31 #[inline]
32 fn as_slice(&self) -> &[u8] {
33 self.0.as_slice()
34 }
35
36 #[inline]
37 fn is_empty(&self) -> bool {
38 self.0.is_empty()
39 }
40
41 #[inline]
42 fn len(&self) -> usize {
43 self.0.len()
44 }
45}
46
47impl<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize> ByteArray<CRYPTO_BOX_BEFORENMBYTES>
48 for PrecalcSecretKey<InnerKey>
49{
50 #[inline]
51 fn as_array(&self) -> &[u8; CRYPTO_BOX_BEFORENMBYTES] {
52 self.0.as_array()
53 }
54}
55
56impl<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize + MutBytes> MutBytes
57 for PrecalcSecretKey<InnerKey>
58{
59 #[inline]
60 fn as_mut_slice(&mut self) -> &mut [u8] {
61 self.0.as_mut_slice()
62 }
63
64 #[inline]
65 fn copy_from_slice(&mut self, other: &[u8]) {
66 self.0.copy_from_slice(other);
67 }
68}
69
70impl<InnerKey: MutByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize>
71 MutByteArray<CRYPTO_BOX_BEFORENMBYTES> for PrecalcSecretKey<InnerKey>
72{
73 #[inline]
74 fn as_mut_array(&mut self) -> &mut [u8; CRYPTO_BOX_BEFORENMBYTES] {
75 self.0.as_mut_array()
76 }
77}
78
79impl PrecalcSecretKey<InnerKey> {
80 #[inline]
85 pub fn precalculate<
86 ThirdPartyPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
87 SecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
88 >(
89 third_party_public_key: &ThirdPartyPublicKey,
90 secret_key: &SecretKey,
91 ) -> Self {
92 use crate::classic::crypto_box::crypto_box_beforenm;
93
94 Self(crypto_box_beforenm(third_party_public_key.as_array(), secret_key.as_array()).into())
95 }
96}
97
98#[cfg(any(feature = "nightly", all(doc, not(doctest))))]
99#[cfg_attr(all(feature = "nightly", doc), doc(cfg(feature = "nightly")))]
100pub mod protected {
101 use super::*;
103 pub use crate::protected::*;
104
105 type InnerKey = HeapByteArray<CRYPTO_BOX_PUBLICKEYBYTES>;
106
107 impl PrecalcSecretKey<Locked<InnerKey>> {
108 pub fn precalculate_locked<
113 ThirdPartyPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
114 SecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
115 >(
116 third_party_public_key: &ThirdPartyPublicKey,
117 secret_key: &SecretKey,
118 ) -> Result<Self, std::io::Error> {
119 use crate::classic::crypto_box::crypto_box_beforenm;
120
121 let mut precalc = HeapByteArray::<CRYPTO_BOX_BEFORENMBYTES>::new_locked()?;
122 let mut key =
123 crypto_box_beforenm(third_party_public_key.as_array(), secret_key.as_array());
124
125 precalc.copy_from_slice(&key);
126 key.zeroize();
127
128 Ok(PrecalcSecretKey(precalc))
129 }
130 }
131
132 impl PrecalcSecretKey<LockedRO<InnerKey>> {
133 pub fn precalculate_readonly_locked<
139 ThirdPartyPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
140 SecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
141 >(
142 third_party_public_key: &ThirdPartyPublicKey,
143 secret_key: &SecretKey,
144 ) -> Result<Self, std::io::Error> {
145 use crate::classic::crypto_box::crypto_box_beforenm;
146
147 let mut precalc = HeapByteArray::<CRYPTO_BOX_BEFORENMBYTES>::new_locked()?;
148 let mut key =
149 crypto_box_beforenm(third_party_public_key.as_array(), secret_key.as_array());
150
151 precalc.copy_from_slice(&key);
152 key.zeroize();
153
154 Ok(PrecalcSecretKey(precalc.mprotect_readonly()?))
155 }
156 }
157}
158
159impl<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize> std::ops::Deref
160 for PrecalcSecretKey<InnerKey>
161{
162 type Target = InnerKey;
163
164 fn deref(&self) -> &Self::Target {
165 &self.0
166 }
167}
168
169impl<InnerKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize> std::ops::DerefMut
170 for PrecalcSecretKey<InnerKey>
171{
172 fn deref_mut(&mut self) -> &mut Self::Target {
173 &mut self.0
174 }
175}
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use crate::constants::{CRYPTO_BOX_PUBLICKEYBYTES, CRYPTO_BOX_SECRETKEYBYTES};
180
181 #[test]
182 fn test_precalculate() {
183 let public_key = StackByteArray::<CRYPTO_BOX_PUBLICKEYBYTES>::default();
184 let secret_key = StackByteArray::<CRYPTO_BOX_SECRETKEYBYTES>::default();
185 let precalc_key = PrecalcSecretKey::precalculate(&public_key, &secret_key);
186 assert!(!precalc_key.is_empty());
187 assert_eq!(precalc_key.len(), CRYPTO_BOX_BEFORENMBYTES);
188 }
189
190 #[cfg(feature = "nightly")]
191 #[test]
192 fn test_precalculate_locked() {
193 let public_key = StackByteArray::<CRYPTO_BOX_PUBLICKEYBYTES>::default();
194 let secret_key = StackByteArray::<CRYPTO_BOX_SECRETKEYBYTES>::default();
195 let mut precalc_key =
196 PrecalcSecretKey::precalculate_locked(&public_key, &secret_key).unwrap();
197 assert!(!precalc_key.is_empty());
198 assert_eq!(precalc_key.len(), CRYPTO_BOX_BEFORENMBYTES);
199
200 precalc_key.as_mut_slice()[0] = 0;
202 precalc_key.as_mut_array()[0] = 1;
203 precalc_key.copy_from_slice(&precalc_key.as_slice().to_owned());
204 }
205
206 #[cfg(feature = "nightly")]
207 #[test]
208 fn test_precalculate_readonly_locked() {
209 let public_key = StackByteArray::<CRYPTO_BOX_PUBLICKEYBYTES>::default();
210 let secret_key = StackByteArray::<CRYPTO_BOX_SECRETKEYBYTES>::default();
211 let precalc_key =
212 PrecalcSecretKey::precalculate_readonly_locked(&public_key, &secret_key).unwrap();
213 assert!(!precalc_key.is_empty());
214 assert_eq!(precalc_key.len(), CRYPTO_BOX_BEFORENMBYTES);
215 }
216}