1use secrecy::{ExposeSecret, ExposeSecretMut, SecretBox};
6use subtle::ConstantTimeEq;
7use zeroize::{Zeroize, ZeroizeOnDrop};
8
9use crate::constants::{
10 AEAD_NONCE_12_LENGTH, AES_256_GCM_KEY_LENGTH, ARGON2_SALT_16_LENGTH, ARGON2_SALT_32_LENGTH,
11 ML_DSA_87_SEED_LENGTH, ML_KEM_1024_SEED_LENGTH,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct AeadNonce12([u8; AEAD_NONCE_12_LENGTH]);
17
18impl AeadNonce12 {
19 pub const fn as_bytes(&self) -> &[u8; AEAD_NONCE_12_LENGTH] {
21 &self.0
22 }
23
24 pub(crate) fn from_array(bytes: [u8; AEAD_NONCE_12_LENGTH]) -> Self {
25 Self(bytes)
26 }
27}
28
29#[derive(Zeroize, ZeroizeOnDrop)]
34pub struct Argon2Salt16([u8; ARGON2_SALT_16_LENGTH]);
35
36impl PartialEq for Argon2Salt16 {
37 fn eq(&self, other: &Self) -> bool {
38 bool::from(self.0.ct_eq(&other.0))
39 }
40}
41
42impl Eq for Argon2Salt16 {}
43
44impl core::hash::Hash for Argon2Salt16 {
45 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
46 core::hash::Hash::hash(&self.0, state);
47 }
48}
49
50impl Argon2Salt16 {
51 pub const fn as_bytes(&self) -> &[u8; ARGON2_SALT_16_LENGTH] {
53 &self.0
54 }
55
56 pub(crate) fn from_array(bytes: [u8; ARGON2_SALT_16_LENGTH]) -> Self {
57 Self(bytes)
58 }
59}
60
61impl core::fmt::Debug for Argon2Salt16 {
62 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63 formatter.write_str("Argon2Salt16(<redacted>)")
64 }
65}
66
67#[derive(Zeroize, ZeroizeOnDrop)]
72pub struct Argon2Salt32([u8; ARGON2_SALT_32_LENGTH]);
73
74impl PartialEq for Argon2Salt32 {
75 fn eq(&self, other: &Self) -> bool {
76 bool::from(self.0.ct_eq(&other.0))
77 }
78}
79
80impl Eq for Argon2Salt32 {}
81
82impl core::hash::Hash for Argon2Salt32 {
83 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
84 core::hash::Hash::hash(&self.0, state);
85 }
86}
87
88impl Argon2Salt32 {
89 pub const fn as_bytes(&self) -> &[u8; ARGON2_SALT_32_LENGTH] {
91 &self.0
92 }
93
94 pub(crate) fn from_array(bytes: [u8; ARGON2_SALT_32_LENGTH]) -> Self {
95 Self(bytes)
96 }
97}
98
99impl core::fmt::Debug for Argon2Salt32 {
100 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101 formatter.write_str("Argon2Salt32(<redacted>)")
102 }
103}
104
105#[derive(Zeroize, ZeroizeOnDrop)]
109pub struct Aes256GcmKeyMaterial {
110 bytes: SecretBox<[u8; AES_256_GCM_KEY_LENGTH]>,
111}
112
113impl Aes256GcmKeyMaterial {
114 pub fn as_bytes(&self) -> &[u8; AES_256_GCM_KEY_LENGTH] {
116 self.bytes.expose_secret()
117 }
118
119 pub fn into_bytes(mut self) -> [u8; AES_256_GCM_KEY_LENGTH] {
124 let output = *self.bytes.expose_secret();
125 self.bytes.zeroize();
126 output
127 }
128
129 pub(crate) fn from_array(mut bytes: [u8; AES_256_GCM_KEY_LENGTH]) -> Self {
130 let mut secret = SecretBox::new(Box::new([0u8; AES_256_GCM_KEY_LENGTH]));
131 *secret.expose_secret_mut() = bytes;
132 bytes.zeroize();
133 Self { bytes: secret }
134 }
135}
136
137#[derive(Zeroize, ZeroizeOnDrop)]
141pub struct MlKem1024Seed {
142 bytes: SecretBox<[u8; ML_KEM_1024_SEED_LENGTH]>,
143}
144
145impl MlKem1024Seed {
146 pub fn as_bytes(&self) -> &[u8; ML_KEM_1024_SEED_LENGTH] {
148 self.bytes.expose_secret()
149 }
150
151 pub fn into_bytes(mut self) -> [u8; ML_KEM_1024_SEED_LENGTH] {
156 let output = *self.bytes.expose_secret();
157 self.bytes.zeroize();
158 output
159 }
160
161 pub(crate) fn from_array(mut bytes: [u8; ML_KEM_1024_SEED_LENGTH]) -> Self {
162 let mut secret = SecretBox::new(Box::new([0u8; ML_KEM_1024_SEED_LENGTH]));
163 *secret.expose_secret_mut() = bytes;
164 bytes.zeroize();
165 Self { bytes: secret }
166 }
167}
168
169#[derive(Zeroize, ZeroizeOnDrop)]
173pub struct MlDsa87Seed {
174 bytes: SecretBox<[u8; ML_DSA_87_SEED_LENGTH]>,
175}
176
177impl MlDsa87Seed {
178 pub fn as_bytes(&self) -> &[u8; ML_DSA_87_SEED_LENGTH] {
180 self.bytes.expose_secret()
181 }
182
183 pub fn into_bytes(mut self) -> [u8; ML_DSA_87_SEED_LENGTH] {
188 let output = *self.bytes.expose_secret();
189 self.bytes.zeroize();
190 output
191 }
192
193 pub(crate) fn from_array(mut bytes: [u8; ML_DSA_87_SEED_LENGTH]) -> Self {
194 let mut secret = SecretBox::new(Box::new([0u8; ML_DSA_87_SEED_LENGTH]));
195 *secret.expose_secret_mut() = bytes;
196 bytes.zeroize();
197 Self { bytes: secret }
198 }
199}
200
201#[derive(Zeroize, ZeroizeOnDrop)]
205pub struct RandomBytes<const N: usize> {
206 bytes: [u8; N],
207}
208
209impl<const N: usize> RandomBytes<N> {
210 pub const fn as_bytes(&self) -> &[u8; N] {
212 &self.bytes
213 }
214
215 pub fn into_bytes(self) -> [u8; N] {
219 self.bytes
220 }
221
222 pub(crate) fn from_array(bytes: [u8; N]) -> Self {
223 Self { bytes }
224 }
225}