aranya_crypto_core/
keys.rs1use core::{borrow::Borrow, fmt::Debug, iter::IntoIterator, mem, result::Result};
4
5use generic_array::{ArrayLength, GenericArray, IntoArrayLength};
6use subtle::{Choice, ConstantTimeEq};
7use typenum::{generic_const_mappings::Const, IsLess, Unsigned, U65536};
8
9use crate::{
10 csprng::{Csprng, Random},
11 import::{ExportError, Import},
12 kdf::{Expand, Kdf, KdfError, Prk},
13 zeroize::ZeroizeOnDrop,
14};
15
16pub trait SecretKey: Clone + ConstantTimeEq + for<'a> Import<&'a [u8]> + ZeroizeOnDrop {
21 fn new<R: Csprng>(rng: &mut R) -> Self;
26
27 type Size: ArrayLength + 'static;
29 const SIZE: usize = Self::Size::USIZE;
31
32 fn try_export_secret(&self) -> Result<SecretKeyBytes<Self::Size>, ExportError>;
34}
35
36#[derive(Clone, Default, ZeroizeOnDrop)]
38#[repr(transparent)]
39pub struct SecretKeyBytes<N: ArrayLength>(GenericArray<u8, N>);
40
41impl<N: ArrayLength> SecretKeyBytes<N> {
42 pub const SIZE: usize = N::USIZE;
44
45 #[inline]
47 pub const fn new(secret: GenericArray<u8, N>) -> Self {
48 Self(secret)
49 }
50
51 #[allow(clippy::len_without_is_empty)]
53 #[inline]
54 pub const fn len(&self) -> usize {
55 N::USIZE
56 }
57
58 pub(crate) fn as_array<const U: usize>(&self) -> &[u8; U]
60 where
61 Const<U>: IntoArrayLength<ArrayLength = N>,
62 {
63 self.0.as_ref()
64 }
65
66 #[inline]
68 pub const fn as_bytes(&self) -> &[u8] {
69 self.0.as_slice()
70 }
71
72 pub(crate) fn as_bytes_mut(&mut self) -> &mut [u8] {
74 &mut self.0
75 }
76
77 #[inline]
79 pub fn into_bytes(mut self) -> GenericArray<u8, N> {
80 mem::take(&mut self.0)
85 }
86}
87
88impl<N: ArrayLength> ConstantTimeEq for SecretKeyBytes<N> {
89 #[inline]
90 fn ct_eq(&self, other: &Self) -> Choice {
91 self.0.ct_eq(&other.0)
92 }
93}
94
95impl<N: ArrayLength> Random for SecretKeyBytes<N> {
96 fn random<R: Csprng>(rng: &mut R) -> Self {
97 Self(Random::random(rng))
98 }
99}
100
101impl<N: ArrayLength> Expand for SecretKeyBytes<N>
102where
103 N: IsLess<U65536>,
104{
105 type Size = N;
106
107 fn expand_multi<'a, K, I>(prk: &Prk<K::PrkSize>, info: I) -> Result<Self, KdfError>
108 where
109 K: Kdf,
110 I: IntoIterator<Item = &'a [u8]>,
111 I::IntoIter: Clone,
112 {
113 Ok(Self(Expand::expand_multi::<K, I>(prk, info)?))
114 }
115}
116
117pub trait PublicKey: Clone + Debug + Eq + for<'a> Import<&'a [u8]> {
119 type Data: Borrow<[u8]> + Clone + Sized;
121
122 fn export(&self) -> Self::Data;
124}
125
126raw_key! {
127 pub RawKey,
129}
130
131#[macro_export]
146macro_rules! raw_key {
147 () => {};
148 (
149 $(#[$meta:meta])*
150 $vis:vis $name:ident,
151 $($tail:tt)*
152 ) => {
153 $(#[$meta])*
154 #[derive(::core::clone::Clone, $crate::zeroize::ZeroizeOnDrop)]
155 #[repr(transparent)]
156 $vis struct $name<N: ::generic_array::ArrayLength>($crate::keys::SecretKeyBytes<N>);
157
158 impl<N: ::generic_array::ArrayLength> $name<N> {
159 #[inline]
161 pub const fn new(key: $crate::keys::SecretKeyBytes<N>) -> Self {
162 Self(key)
163 }
164
165 #[allow(clippy::len_without_is_empty)]
169 #[inline]
170 pub const fn len(&self) -> usize {
171 self.0.len()
172 }
173
174 #[inline]
176 pub const fn as_slice(&self) -> &[u8] {
177 self.0.as_bytes()
178 }
179
180 #[inline]
182 pub const fn as_bytes(&self) -> &$crate::keys::SecretKeyBytes<N> {
183 &self.0
184 }
185
186 #[inline]
188 pub fn into_bytes(mut self) -> $crate::keys::SecretKeyBytes<N> {
189 ::core::mem::take(&mut self.0)
194 }
195 }
196
197 impl<N: ::generic_array::ArrayLength> $crate::keys::SecretKey for $name<N>
198 {
199 type Size = N;
200
201 #[inline]
202 fn new<R: $crate::csprng::Csprng>(rng: &mut R) -> Self {
203 Self($crate::csprng::Random::random(rng))
204 }
205
206 #[inline]
207 fn try_export_secret(&self) -> ::core::result::Result<
208 $crate::keys::SecretKeyBytes<Self::Size>,
209 $crate::import::ExportError,
210 > {
211 ::core::result::Result::Ok(self.0.clone())
212 }
213 }
214
215 impl<N: ::generic_array::ArrayLength> $crate::csprng::Random for $name<N> {
216 fn random<R: $crate::csprng::Csprng>(rng: &mut R) -> Self {
217 let sk = <$crate::keys::SecretKeyBytes<N> as $crate::csprng::Random>::random(rng);
218 Self(sk)
219 }
220 }
221
222
223 impl<N: ::generic_array::ArrayLength> $crate::kdf::Expand for $name<N>
224 where
225 N: ::typenum::IsLess<::typenum::U65536>
226 {
227 type Size = N;
228
229 fn expand_multi<'a, K, I>(
230 prk: &$crate::kdf::Prk<K::PrkSize>,
231 info: I,
232 ) -> ::core::result::Result<Self, $crate::kdf::KdfError>
233 where
234 K: $crate::kdf::Kdf,
235 I: ::core::iter::IntoIterator<Item = &'a [u8]>,
236 I::IntoIter: ::core::clone::Clone,
237 {
238 ::core::result::Result::Ok(Self($crate::kdf::Expand::expand_multi::<K, I>(prk, info)?))
239 }
240 }
241
242 impl<N: ::generic_array::ArrayLength> ::subtle::ConstantTimeEq for $name<N> {
243 #[inline]
244 fn ct_eq(&self, other: &Self) -> ::subtle::Choice {
245 self.0.ct_eq(&other.0)
246 }
247 }
248
249 impl<N, const U: usize> $crate::import::Import<[u8; U]> for $name<N>
250 where
251 N: ::generic_array::ArrayLength,
252 ::typenum::generic_const_mappings::Const<U>: ::generic_array::IntoArrayLength<ArrayLength = N>,
253 {
254 #[inline]
255 fn import(key: [u8; U]) -> ::core::result::Result<Self, $crate::import::ImportError> {
256 let sk = $crate::keys::SecretKeyBytes::new(key.into());
257 ::core::result::Result::Ok(Self(sk))
258 }
259 }
260
261 impl<N: ::generic_array::ArrayLength> $crate::import::Import<&[u8]> for $name<N> {
262 #[inline]
263 fn import(data: &[u8]) -> ::core::result::Result<Self, $crate::import::ImportError> {
264 let bytes = $crate::import::Import::<_>::import(data)?;
265 let sk = $crate::keys::SecretKeyBytes::new(bytes);
266 ::core::result::Result::Ok(Self(sk))
267 }
268 }
269
270 raw_key!{ $($tail)* }
271 };
272}
273pub(crate) use raw_key;