1use alloc::boxed::Box;
4use core::fmt;
5
6use crate::paserk::{IdVersion, KeyId, KeyText};
7use crate::sealed::Sealed;
8use crate::version::{Local, PkePublic, PkeSecret, Public, SealingVersion, Secret, Version};
9use crate::{LocalKey, PasetoError, PublicKey, SecretKey};
10
11pub(crate) type KeyInner<V, K> = <V as HasKey<K>>::Key;
12
13pub struct Key<V: HasKey<K>, K: KeyType>(pub(crate) KeyInner<V, K>);
15
16impl<V: HasKey<K>, K: KeyType> Clone for Key<V, K>
17where
18 KeyInner<V, K>: Clone,
19{
20 fn clone(&self) -> Self {
21 Self(self.0.clone())
22 }
23}
24
25impl<V: SealingVersion<Public>> SecretKey<V> {
26 pub fn random() -> Result<Self, PasetoError> {
28 V::random().map(Self)
29 }
30
31 pub fn public_key(&self) -> PublicKey<V> {
33 Key(V::unsealing_key(&self.0))
34 }
35}
36
37impl<V: SealingVersion<Local>> LocalKey<V> {
38 pub fn random() -> Result<Self, PasetoError> {
40 V::random().map(Self)
41 }
42}
43
44impl<V: SealingVersion<Local>> From<[u8; 32]> for LocalKey<V> {
45 fn from(value: [u8; 32]) -> Self {
46 Self(V::decode(&value[..]).expect("all 32 bytes should be valid local keys"))
47 }
48}
49
50impl<V: HasKey<Public>> fmt::Display for PublicKey<V> {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 self.expose_key().fmt(f)
53 }
54}
55
56impl<V: HasKey<K>, K: KeyType> core::str::FromStr for Key<V, K> {
57 type Err = PasetoError;
58 fn from_str(s: &str) -> Result<Self, Self::Err> {
59 KeyText::<V, K>::from_str(s).and_then(|k| k.try_into())
60 }
61}
62
63impl<V: IdVersion + HasKey<K>, K: KeyType> Key<V, K> {
64 pub fn id(&self) -> KeyId<V, K> {
66 KeyId::from(&self.expose_key())
67 }
68}
69
70pub trait HasKey<K>: Version {
73 type Key;
74
75 fn encode(key: &Self::Key) -> Box<[u8]>;
77
78 fn decode(bytes: &[u8]) -> Result<Self::Key, PasetoError>;
80}
81
82pub trait KeyType: Send + Sync + Sealed + Sized + 'static {
84 const HEADER: &'static str;
86 const ID_HEADER: &'static str;
88}
89
90pub trait SealingKey: KeyType {
92 const PIE_WRAP_HEADER: &'static str;
93 const PW_WRAP_HEADER: &'static str;
94}
95
96impl KeyType for Secret {
97 const HEADER: &'static str = ".secret.";
98 const ID_HEADER: &'static str = ".sid.";
99}
100
101impl SealingKey for Secret {
102 const PIE_WRAP_HEADER: &'static str = ".secret-wrap.pie.";
103 const PW_WRAP_HEADER: &'static str = ".secret-pw.";
104}
105
106impl KeyType for Public {
107 const HEADER: &'static str = ".public.";
108 const ID_HEADER: &'static str = ".pid.";
109}
110
111impl KeyType for Local {
112 const HEADER: &'static str = ".local.";
113 const ID_HEADER: &'static str = ".lid.";
114}
115
116impl SealingKey for Local {
117 const PIE_WRAP_HEADER: &'static str = ".local-wrap.pie.";
118 const PW_WRAP_HEADER: &'static str = ".local-pw.";
119}
120
121impl KeyType for PkeSecret {
122 const HEADER: &'static str = ".secret.";
123 const ID_HEADER: &'static str = ".sid.";
124}
125
126impl KeyType for PkePublic {
127 const HEADER: &'static str = ".public.";
128 const ID_HEADER: &'static str = ".pid.";
129}