1use std::{
19 fmt::{self, Debug, Display},
20 marker::PhantomData,
21};
22
23use crate::{crypto::Crypto, Keypair, Keystore, SecretKeyExt};
24
25struct Stored<PK, S, M> {
26 public_key: PK,
27 secret_key: S,
28 metadata: M,
29}
30
31pub struct MemoryStorage<C: Crypto, PK, SK, M> {
38 key: Option<Stored<PK, C::SecretBox, M>>,
39 crypto: C,
40
41 _marker: PhantomData<SK>,
42}
43
44impl<C: Crypto, PK, SK, M> MemoryStorage<C, PK, SK, M> {
45 pub fn new(crypto: C) -> Self {
46 Self {
47 key: None,
48 crypto,
49
50 _marker: PhantomData,
51 }
52 }
53}
54
55#[derive(Debug)]
56pub enum Error<Crypto, Conversion> {
57 KeyExists,
58 NoSuchKey,
59 Crypto(Crypto),
60 Conversion(Conversion),
61}
62
63impl<Crypto, Conversion> std::error::Error for Error<Crypto, Conversion>
64where
65 Crypto: Display + Debug,
66 Conversion: Display + Debug,
67{
68}
69
70impl<Crypto, Conversion> Display for Error<Crypto, Conversion>
71where
72 Crypto: Display,
73 Conversion: Display,
74{
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 match self {
77 Self::KeyExists => f.write_str("Key exists, refusing to overwrite"),
78 Self::NoSuchKey => f.write_str("No key found"),
79 Self::Conversion(e) => write!(f, "Error reconstructing sealed key: {}", e),
80 Self::Crypto(e) => write!(f, "Error unsealing key: {}", e),
81 }
82 }
83}
84
85impl<C, PK, SK, M> Keystore for MemoryStorage<C, PK, SK, M>
86where
87 C: Crypto,
88 C::Error: Display + Debug,
89 C::SecretBox: Clone,
90
91 SK: AsRef<[u8]> + SecretKeyExt<Metadata = M>,
92 <SK as SecretKeyExt>::Error: Display + Debug,
93
94 PK: Clone + From<SK>,
95 M: Clone,
96{
97 type PublicKey = PK;
98 type SecretKey = SK;
99 type Metadata = M;
100 type Error = Error<C::Error, <SK as SecretKeyExt>::Error>;
101
102 fn put_key(&mut self, key: Self::SecretKey) -> Result<(), Self::Error> {
103 if self.key.is_some() {
104 return Err(Error::KeyExists);
105 }
106
107 let metadata = key.metadata();
108 let sealed_key = self.crypto.seal(&key).map_err(Error::Crypto)?;
109 self.key = Some(Stored {
110 public_key: Self::PublicKey::from(key),
111 secret_key: sealed_key,
112 metadata,
113 });
114
115 Ok(())
116 }
117
118 fn get_key(&self) -> Result<Keypair<Self::PublicKey, Self::SecretKey>, Self::Error> {
119 match &self.key {
120 None => Err(Error::NoSuchKey),
121 Some(ref stored) => {
122 let sk = {
123 let sbox = stored.secret_key.clone();
124 let meta = stored.metadata.clone();
125
126 self.crypto
127 .unseal(sbox)
128 .map_err(Error::Crypto)
129 .and_then(|sec| {
130 Self::SecretKey::from_bytes_and_meta(sec, &meta)
131 .map_err(Error::Conversion)
132 })
133 }?;
134
135 Ok(Keypair {
136 public_key: stored.public_key.clone(),
137 secret_key: sk,
138 })
139 },
140 }
141 }
142
143 fn show_key(&self) -> Result<(Self::PublicKey, Self::Metadata), Self::Error> {
144 self.key
145 .as_ref()
146 .ok_or(Error::NoSuchKey)
147 .map(|sealed| (sealed.public_key.clone(), sealed.metadata.clone()))
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 use super::*;
154 use crate::{
155 crypto::{self, Pwhash, SecretBoxError},
156 pinentry::Pinentry,
157 test::*,
158 };
159
160 fn with_mem_store<F, P>(pin: P, f: F)
161 where
162 F: FnOnce(MemoryStorage<Pwhash<P>, PublicKey, SecretKey, ()>),
163 P: Pinentry,
164 P::Error: std::error::Error + 'static,
165 {
166 f(MemoryStorage::new(Pwhash::new(
167 pin,
168 *crypto::KDF_PARAMS_TEST,
169 )))
170 }
171
172 #[test]
173 fn test_get_after_put() {
174 with_mem_store(default_passphrase(), get_after_put)
175 }
176
177 #[test]
178 fn test_put_twice() {
179 with_mem_store(default_passphrase(), |store| {
180 put_twice(store, Error::KeyExists)
181 })
182 }
183
184 #[test]
185 fn test_get_empty() {
186 with_mem_store(default_passphrase(), |store| {
187 get_empty(store, Error::NoSuchKey)
188 })
189 }
190
191 #[test]
192 fn test_passphrase_mismatch() {
193 with_mem_store(PinCycle::new(&["right".into(), "wrong".into()]), |store| {
194 passphrase_mismatch(store, Error::Crypto(SecretBoxError::InvalidKey))
195 })
196 }
197}