1use core::{borrow::Borrow, fmt, iter::IntoIterator, mem, result::Result};
4
5use generic_array::{ArrayLength, GenericArray, IntoArrayLength};
6use subtle::{Choice, ConstantTimeEq};
7use typenum::{generic_const_mappings::Const, IsLess, U65536};
8
9use crate::{
10 csprng::{Csprng, Random},
11 import::{ExportError, Import},
12 kdf::{Expand, Kdf, KdfError, Prk},
13 zeroize::{zeroize_flat_type, ZeroizeOnDrop},
14};
15
16pub trait SecretKey:
21 Clone + ConstantTimeEq + for<'a> Import<&'a [u8]> + Random + ZeroizeOnDrop
22{
23 type Size: ArrayLength + 'static;
25
26 fn try_export_secret(&self) -> Result<SecretKeyBytes<Self::Size>, ExportError>;
28}
29
30pub trait RawSecretBytes {
32 fn raw_secret_bytes(&self) -> &[u8];
34}
35
36impl<T: RawSecretBytes> RawSecretBytes for &T {
37 #[inline]
38 fn raw_secret_bytes(&self) -> &[u8] {
39 (**self).raw_secret_bytes()
40 }
41}
42
43impl RawSecretBytes for [u8] {
44 #[inline]
45 fn raw_secret_bytes(&self) -> &[u8] {
46 self
47 }
48}
49
50#[derive(Clone, Default)]
52#[repr(transparent)]
53pub struct SecretKeyBytes<N: ArrayLength>(GenericArray<u8, N>);
54
55impl<N: ArrayLength> fmt::Debug for SecretKeyBytes<N> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.debug_struct("SecretKeyBytes").finish_non_exhaustive()
58 }
59}
60
61impl<N: ArrayLength> ZeroizeOnDrop for SecretKeyBytes<N> {}
62impl<N: ArrayLength> Drop for SecretKeyBytes<N> {
63 fn drop(&mut self) {
64 unsafe {
71 zeroize_flat_type(&mut self.0);
72 }
73 }
74}
75
76impl<N: ArrayLength> SecretKeyBytes<N> {
77 pub const SIZE: usize = N::USIZE;
79
80 #[inline]
82 pub const fn new(secret: GenericArray<u8, N>) -> Self {
83 Self(secret)
84 }
85
86 #[allow(clippy::len_without_is_empty)]
88 #[inline]
89 pub const fn len(&self) -> usize {
90 N::USIZE
91 }
92
93 pub(crate) fn as_array<const U: usize>(&self) -> &[u8; U]
95 where
96 Const<U>: IntoArrayLength<ArrayLength = N>,
97 {
98 self.0.as_ref()
99 }
100
101 #[inline]
103 pub const fn as_bytes(&self) -> &[u8] {
104 self.0.as_slice()
105 }
106
107 pub(crate) fn as_bytes_mut(&mut self) -> &mut [u8] {
109 &mut self.0
110 }
111
112 #[inline]
114 pub fn into_bytes(mut self) -> GenericArray<u8, N> {
115 mem::take(&mut self.0)
120 }
121}
122
123impl<N: ArrayLength> ConstantTimeEq for SecretKeyBytes<N> {
124 #[inline]
125 fn ct_eq(&self, other: &Self) -> Choice {
126 self.0.ct_eq(&other.0)
127 }
128}
129
130impl<N: ArrayLength> Random for SecretKeyBytes<N> {
131 fn random<R: Csprng>(rng: R) -> Self {
132 Self(Random::random(rng))
133 }
134}
135
136impl<N: ArrayLength> Expand for SecretKeyBytes<N>
137where
138 N: IsLess<U65536>,
139{
140 type Size = N;
141
142 fn expand_multi<'a, K, I>(prk: &Prk<K::PrkSize>, info: I) -> Result<Self, KdfError>
143 where
144 K: Kdf,
145 I: IntoIterator<Item = &'a [u8]>,
146 I::IntoIter: Clone,
147 {
148 Ok(Self(Expand::expand_multi::<K, I>(prk, info)?))
149 }
150}
151
152impl<N: ArrayLength> RawSecretBytes for SecretKeyBytes<N> {
153 #[inline]
154 fn raw_secret_bytes(&self) -> &[u8] {
155 self.as_bytes()
156 }
157}
158
159pub trait PublicKey: Clone + fmt::Debug + Eq + for<'a> Import<&'a [u8]> {
161 type Data: Borrow<[u8]> + Clone + Sized;
163
164 fn export(&self) -> Self::Data;
166}
167
168raw_key! {
169 pub RawKey,
171}
172
173#[macro_export]
188macro_rules! raw_key {
189 () => {};
190 (
191 $(#[$meta:meta])*
192 $vis:vis $name:ident,
193 $($tail:tt)*
194 ) => {
195 $(#[$meta])*
196 #[derive(::core::clone::Clone)]
197 #[repr(transparent)]
198 $vis struct $name<N: $crate::generic_array::ArrayLength>($crate::keys::SecretKeyBytes<N>);
199
200 impl<N: ::generic_array::ArrayLength> $name<N> {
201 #[inline]
203 pub const fn new(key: $crate::keys::SecretKeyBytes<N>) -> Self {
204 Self(key)
205 }
206
207 #[allow(clippy::len_without_is_empty)]
211 #[inline]
212 pub const fn len(&self) -> usize {
213 self.0.len()
214 }
215
216 #[inline]
218 pub const fn as_slice(&self) -> &[u8] {
219 self.0.as_bytes()
220 }
221
222 #[inline]
224 pub const fn as_bytes(&self) -> &$crate::keys::SecretKeyBytes<N> {
225 &self.0
226 }
227
228 #[inline]
230 pub fn into_bytes(mut self) -> $crate::keys::SecretKeyBytes<N> {
231 ::core::mem::take(&mut self.0)
236 }
237 }
238
239 impl<N: $crate::generic_array::ArrayLength> $crate::keys::SecretKey for $name<N> {
240 type Size = N;
241
242 #[inline]
243 fn try_export_secret(&self) -> ::core::result::Result<
244 $crate::keys::SecretKeyBytes<Self::Size>,
245 $crate::import::ExportError,
246 > {
247 ::core::result::Result::Ok(self.0.clone())
248 }
249 }
250
251 impl<N: $crate::generic_array::ArrayLength> $crate::csprng::Random for $name<N> {
252 fn random<R: $crate::csprng::Csprng>(rng: R) -> Self {
253 let sk = <$crate::keys::SecretKeyBytes<N> as $crate::csprng::Random>::random(rng);
254 Self(sk)
255 }
256 }
257
258 impl<N: $crate::generic_array::ArrayLength> $crate::keys::RawSecretBytes for $name<N> {
259 #[inline]
260 fn raw_secret_bytes(&self) -> &[u8] {
261 $crate::keys::RawSecretBytes::raw_secret_bytes(&self.0)
262 }
263 }
264
265 impl<N: $crate::generic_array::ArrayLength> $crate::kdf::Expand for $name<N>
266 where
267 N: ::typenum::IsLess<::typenum::U65536>
268 {
269 type Size = N;
270
271 fn expand_multi<'a, K, I>(
272 prk: &$crate::kdf::Prk<K::PrkSize>,
273 info: I,
274 ) -> ::core::result::Result<Self, $crate::kdf::KdfError>
275 where
276 K: $crate::kdf::Kdf,
277 I: ::core::iter::IntoIterator<Item = &'a [u8]>,
278 I::IntoIter: ::core::clone::Clone,
279 {
280 ::core::result::Result::Ok(Self($crate::kdf::Expand::expand_multi::<K, I>(prk, info)?))
281 }
282 }
283
284 impl<N: $crate::generic_array::ArrayLength> ::subtle::ConstantTimeEq for $name<N> {
285 #[inline]
286 fn ct_eq(&self, other: &Self) -> ::subtle::Choice {
287 self.0.ct_eq(&other.0)
288 }
289 }
290
291 impl<N, const U: usize> $crate::import::Import<[u8; U]> for $name<N>
292 where
293 N: $crate::generic_array::ArrayLength,
294 ::typenum::generic_const_mappings::Const<U>: $crate::generic_array::IntoArrayLength<ArrayLength = N>,
295 {
296 #[inline]
297 fn import(key: [u8; U]) -> ::core::result::Result<Self, $crate::import::ImportError> {
298 let sk = $crate::keys::SecretKeyBytes::new(key.into());
299 ::core::result::Result::Ok(Self(sk))
300 }
301 }
302
303 impl<N: $crate::generic_array::ArrayLength> $crate::import::Import<&[u8]> for $name<N> {
304 #[inline]
305 fn import(data: &[u8]) -> ::core::result::Result<Self, $crate::import::ImportError> {
306 let bytes = $crate::import::Import::<_>::import(data)?;
307 let sk = $crate::keys::SecretKeyBytes::new(bytes);
308 ::core::result::Result::Ok(Self(sk))
309 }
310 }
311
312 impl<N: ::generic_array::ArrayLength> ::core::fmt::Debug for $name<N> {
313 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
314 f.debug_struct(stringify!($name)).finish_non_exhaustive()
315 }
316 }
317
318 impl<N: $crate::generic_array::ArrayLength> $crate::zeroize::ZeroizeOnDrop for $name<N> {}
319 impl<N: $crate::generic_array::ArrayLength> Drop for $name<N> {
320 fn drop(&mut self) {
321 unsafe {
330 $crate::zeroize::zeroize_flat_type(&mut self.0);
331 }
332 }
333 }
334
335 raw_key!{ $($tail)* }
336 };
337}
338pub(crate) use raw_key;
339
340#[derive(Copy, Clone, Debug, Eq, PartialEq, thiserror::Error)]
343#[error("invalid key length")]
344pub struct InvalidKey;