trustchain_core/
key_manager.rs

1//! Key management API with default implementations.
2use crate::{JSON_FILE_EXTENSION, TRUSTCHAIN_DATA};
3use serde_json::{from_str, to_string_pretty as to_json};
4use ssi::jwk::JWK;
5use ssi::one_or_many::OneOrMany;
6use std::fs::{File, OpenOptions};
7use std::io::{Read, Write};
8use std::path::{Path, PathBuf};
9use thiserror::Error;
10
11/// An error relating to Trustchain key management.
12#[derive(Error, Debug)]
13pub enum KeyManagerError {
14    /// Key does not exist.
15    #[error("Key does not exist.")]
16    FailedToLoadKey,
17    /// Key could not be saved.
18    #[error("Key could not be saved.")]
19    FailedToSaveKey,
20    /// Failed to read UTF-8 data.
21    #[error("Failed to read UTF-8 data.")]
22    FailedToReadUTF8,
23    /// Failed to parse JSON string to JWK.
24    #[error("Failed to parse JSON string to JWK.")]
25    FailedToParseJWK,
26    /// Failed to create path for DID keys during save.
27    #[error("Failed to create path for DID keys during save.")]
28    FailedToCreateDir,
29    /// Failed to remove key.
30    #[error("Failed to remove key.")]
31    FailedToRemoveKey,
32    /// No TRUSTCHAIN_DATA environment variable.
33    #[error("No TRUSTCHAIN_DATA environment variable.")]
34    TrustchainDataNotPresent,
35    /// Expected only one key but found many.
36    #[error("Expected only one key but found many.")]
37    InvalidManyKeys,
38    /// Wrapped SSI JWK error.
39    #[error(transparent)]
40    SSIJWKError(#[from] ssi::jwk::Error),
41}
42
43/// KeyType enum.
44#[derive(Debug, PartialEq, Eq, Hash)]
45pub enum KeyType {
46    UpdateKey,
47    NextUpdateKey,
48    RecoveryKey,
49    SigningKey,
50}
51
52pub trait ControllerKeyManager: KeyManager {
53    /// Reads a recovery key.
54    fn read_recovery_key(&self, did_suffix: &str) -> Result<JWK, KeyManagerError> {
55        let key = self.read_key(did_suffix, &KeyType::RecoveryKey);
56        self.only_one_key(key)
57    }
58    /// Reads an update key.
59    fn read_update_key(&self, did_suffix: &str) -> Result<JWK, KeyManagerError> {
60        let key = self.read_key(did_suffix, &KeyType::UpdateKey);
61        self.only_one_key(key)
62    }
63
64    /// Reads a candidate next update key.
65    fn read_next_update_key(&self, did_suffix: &str) -> Result<JWK, KeyManagerError> {
66        let key = self.read_key(did_suffix, &KeyType::NextUpdateKey);
67        self.only_one_key(key)
68    }
69
70    /// Apply the `next_update_key` to `update_key` and remove next_update_key
71    fn apply_next_update_key(
72        &self,
73        did_suffix: &str,
74        next_update_key: &JWK,
75    ) -> Result<(), KeyManagerError> {
76        // Save as update key
77        self.save_key(did_suffix, KeyType::UpdateKey, next_update_key, true)?;
78
79        // Remove "next_update_key"
80        self.remove_keys(did_suffix, &KeyType::NextUpdateKey)?;
81
82        Ok(())
83    }
84}
85
86pub trait AttestorKeyManager: KeyManager {
87    /// Reads one or more signing keys.
88    fn read_signing_keys(&self, did_suffix: &str) -> Result<OneOrMany<JWK>, KeyManagerError> {
89        self.read_key(did_suffix, &KeyType::SigningKey)
90    }
91}
92
93pub trait KeyManager {
94    /// Reads a key of a given type.
95    fn read_key(
96        &self,
97        did_suffix: &str,
98        key_type: &KeyType,
99    ) -> Result<OneOrMany<JWK>, KeyManagerError> {
100        // Make path
101        let path = &self.get_path(did_suffix, key_type, false)?;
102
103        // Open the file
104        let file = File::open(path);
105
106        // Read from the file and return
107        if let Ok(file) = file {
108            self.read_keys_from(Box::new(file))
109        } else {
110            Err(KeyManagerError::FailedToLoadKey)
111        }
112    }
113
114    /// Check only one key is present and return key.
115    fn only_one_key(
116        &self,
117        key: Result<OneOrMany<JWK>, KeyManagerError>,
118    ) -> Result<JWK, KeyManagerError> {
119        match key {
120            Ok(OneOrMany::One(x)) => Ok(x),
121            Ok(OneOrMany::Many(_)) => Err(KeyManagerError::InvalidManyKeys),
122            Err(e) => Err(e),
123        }
124    }
125
126    /// Reads one key from a Reader.
127    fn read_keys_from(&self, mut reader: Box<dyn Read>) -> Result<OneOrMany<JWK>, KeyManagerError> {
128        // Read a UTF-8 string from the reader.
129        let buf: &mut String = &mut String::new();
130        let read_result = reader.read_to_string(buf);
131
132        // Read the string as a serialized JWK instance.
133        let jwk_result = match read_result {
134            Ok(_) => from_str::<OneOrMany<JWK>>(buf),
135            Err(_) => return Err(KeyManagerError::FailedToReadUTF8),
136        };
137
138        // Return the JWK.
139        match jwk_result {
140            Ok(x) => Ok(x),
141            Err(_) => Err(KeyManagerError::FailedToParseJWK),
142        }
143    }
144
145    /// Gets path for a given DID and key type
146    fn get_path(
147        &self,
148        did_suffix: &str,
149        key_type: &KeyType,
150        dir_only: bool,
151    ) -> Result<PathBuf, KeyManagerError> {
152        // Get the stem for the corresponding key type
153        let file_name = match key_type {
154            KeyType::UpdateKey => format!("update_key{}", JSON_FILE_EXTENSION),
155            KeyType::NextUpdateKey => format!("next_update_key{}", JSON_FILE_EXTENSION),
156            KeyType::RecoveryKey => format!("recovery_key{}", JSON_FILE_EXTENSION),
157            KeyType::SigningKey => format!("signing_key{}", JSON_FILE_EXTENSION),
158        };
159
160        // Get environment for TRUSTCHAIN_DATA
161        let path: String = match std::env::var(TRUSTCHAIN_DATA) {
162            Ok(val) => val,
163            Err(_) => return Err(KeyManagerError::TrustchainDataNotPresent),
164        };
165
166        // Makre directory name
167        let directory = Path::new(path.as_str())
168            .join("key_manager")
169            .join(did_suffix);
170
171        // Make a path
172        if dir_only {
173            Ok(directory)
174        } else {
175            Ok(directory.join(file_name))
176        }
177    }
178
179    /// Checks whether keys already exist on disk.
180    fn keys_exist(&self, did_suffix: &str, key_type: &KeyType) -> bool {
181        self.get_path(did_suffix, key_type, false).unwrap().exists()
182    }
183
184    /// Saves a key to disk.
185    fn save_key(
186        &self,
187        did_suffix: &str,
188        key_type: KeyType,
189        key: &JWK,
190        overwrite: bool,
191    ) -> Result<(), KeyManagerError> {
192        self.save_keys(
193            did_suffix,
194            key_type,
195            &OneOrMany::One(key.clone()),
196            overwrite,
197        )
198    }
199
200    /// Saves one or more keys to disk.
201    fn save_keys(
202        &self,
203        did_suffix: &str,
204        key_type: KeyType,
205        keys: &OneOrMany<JWK>,
206        overwrite: bool,
207    ) -> Result<(), KeyManagerError> {
208        // Get directory and path
209        let directory = &self.get_path(did_suffix, &key_type, true)?;
210        let path = &self.get_path(did_suffix, &key_type, false)?;
211
212        // Stop if keys already exist and overwrite is false.
213        if self.keys_exist(did_suffix, &key_type) && !overwrite {
214            return Err(KeyManagerError::FailedToSaveKey);
215        }
216
217        // Make directory if non-existent
218        match std::fs::create_dir_all(directory) {
219            Ok(_) => (),
220            Err(_) => return Err(KeyManagerError::FailedToCreateDir),
221        };
222
223        // Open the new file
224        let file = OpenOptions::new()
225            .create(true)
226            .write(true)
227            .truncate(true)
228            .open(path);
229
230        // Write key to file
231        if let Ok(mut file) = file {
232            match writeln!(file, "{}", &to_json(keys).unwrap()) {
233                Ok(_) => Ok(()),
234                Err(_) => Err(KeyManagerError::FailedToSaveKey),
235            }
236        } else {
237            Err(KeyManagerError::FailedToSaveKey)
238        }
239    }
240
241    /// Removes file from disk for `key_type` of `did_suffix`.
242    fn remove_keys(&self, did_suffix: &str, key_type: &KeyType) -> Result<(), KeyManagerError> {
243        // Make path
244        let path = &self.get_path(did_suffix, key_type, false)?;
245
246        // Check path exists as a file
247        if path.is_file() {
248            match std::fs::remove_file(path) {
249                Ok(_) => Ok(()),
250                Err(_) => Err(KeyManagerError::FailedToRemoveKey),
251            }
252        } else {
253            Err(KeyManagerError::FailedToRemoveKey)
254        }
255    }
256}
257
258#[cfg(test)]
259pub mod tests {
260    use super::*;
261    use crate::data::{
262        TEST_NEXT_UPDATE_KEY, TEST_RECOVERY_KEY, TEST_SIGNING_KEYS, TEST_UPDATE_KEY,
263    };
264    use crate::utils::{generate_key, init};
265    use mockall::mock;
266    use ssi::jwk::Params;
267    use std::io::Read;
268
269    pub struct TestKeyManager;
270
271    impl KeyManager for TestKeyManager {}
272    impl AttestorKeyManager for TestKeyManager {}
273    impl ControllerKeyManager for TestKeyManager {}
274
275    #[test]
276    fn test_generate_key() {
277        let result = generate_key();
278
279        // Check for the expected elliptic curve (used by ION to generate keys).
280        match result.params {
281            ssi::jwk::Params::EC(ecparams) => {
282                assert_eq!(ecparams.curve, Some(String::from("secp256k1")))
283            }
284            _ => panic!(),
285        }
286    }
287
288    // Mock the std::io::Read trait.
289    mock! {
290        Reader {}     // Name of the mock struct, less the "Mock" prefix
291        impl Read for Reader {   // specification of the trait to mock
292            fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>;
293            fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize>;
294        }
295    }
296
297    #[test]
298    fn test_read_update_key() -> Result<(), Box<dyn std::error::Error>> {
299        // Init env
300        init();
301
302        // Make path for this test
303        let did_suffix = "test_read_update_key";
304
305        // Save key to temp file
306        let expected_key: JWK = serde_json::from_str(TEST_UPDATE_KEY).unwrap();
307
308        let target = TestKeyManager;
309        target.save_key(did_suffix, KeyType::UpdateKey, &expected_key, true)?;
310
311        // Read key from file
312        let res = target.read_update_key(did_suffix);
313
314        // Assert read is ok
315        assert!(res.is_ok());
316
317        // Assert same key is read back
318        assert_eq!(expected_key, res.unwrap());
319
320        Ok(())
321    }
322
323    #[test]
324    fn test_read_recovery_key() -> Result<(), Box<dyn std::error::Error>> {
325        // Init env
326        init();
327
328        // Make path for this test
329        let did_suffix = "test_read_recovery_key";
330
331        // Save key to temp file
332        let expected_key: JWK = serde_json::from_str(TEST_RECOVERY_KEY)?;
333
334        let target = TestKeyManager;
335        target.save_key(did_suffix, KeyType::RecoveryKey, &expected_key, true)?;
336
337        // Read key from file
338        let res = target.read_recovery_key(did_suffix);
339
340        // Assert read is ok
341        assert!(res.is_ok());
342
343        // Assert same key is read back
344        assert_eq!(expected_key, res.unwrap());
345
346        Ok(())
347    }
348
349    #[test]
350    fn test_read_keys_from() {
351        // Construct a mock Reader.
352        let mut mock_reader = MockReader::new();
353        mock_reader.expect_read_to_string().return_once(move |buf| {
354            // Implement the side effect of filling the buffer.
355            buf.push_str(TEST_UPDATE_KEY);
356            // Dummy return value
357            std::io::Result::Ok(0)
358        });
359
360        let target = TestKeyManager;
361        let result = target.read_keys_from(Box::new(mock_reader));
362        assert!(result.is_ok());
363
364        let key = result.unwrap();
365
366        // Check for the expected elliptic curve.
367        if let OneOrMany::One(key) = key {
368            match &key.params {
369                Params::EC(ecparams) => assert_eq!(ecparams.curve, Some(String::from("secp256k1"))),
370                _ => panic!(),
371            }
372        } else {
373            panic!()
374        }
375    }
376
377    #[test]
378    fn test_keys_exist() -> Result<(), Box<dyn std::error::Error>> {
379        // Set env var
380        init();
381
382        let target = TestKeyManager;
383
384        // Make keys
385        let expected_key: JWK = serde_json::from_str(TEST_UPDATE_KEY)?;
386
387        // Make path for this test
388        let did_suffix = "test_keys_exist";
389
390        assert!(!target.keys_exist(did_suffix, &KeyType::UpdateKey));
391
392        // Save to temp
393        target.save_key(did_suffix, KeyType::UpdateKey, &expected_key, true)?;
394
395        assert!(target.keys_exist(did_suffix, &KeyType::UpdateKey));
396
397        // Failing overwrite
398        let try_overwrite = target.save_key(did_suffix, KeyType::UpdateKey, &expected_key, false);
399        assert!(try_overwrite.is_err());
400
401        // Successful overwrite
402        let try_overwrite = target.save_key(did_suffix, KeyType::UpdateKey, &expected_key, true);
403        assert!(try_overwrite.is_ok());
404
405        Ok(())
406    }
407
408    #[test]
409    fn test_save_key() -> Result<(), Box<dyn std::error::Error>> {
410        // Set env var
411        init();
412
413        // Make path for this test
414        let did_suffix = "test_save_key";
415
416        // Make keys
417        let expected_key: JWK = serde_json::from_str(TEST_UPDATE_KEY)?;
418
419        // Save to temp
420        let target = TestKeyManager;
421        target.save_key(did_suffix, KeyType::UpdateKey, &expected_key, true)?;
422
423        // Read keys
424        let actual_key = target.read_update_key(did_suffix)?;
425
426        // Check keys saved are same as those read back
427        assert_eq!(expected_key, actual_key);
428
429        Ok(())
430    }
431
432    #[test]
433    fn test_save_keys() -> Result<(), Box<dyn std::error::Error>> {
434        // Set env var
435        init();
436
437        // Make path for this test
438        let did_suffix = "test_save_keys";
439
440        // Make keys
441        let keys: OneOrMany<JWK> = serde_json::from_str(TEST_SIGNING_KEYS)?;
442
443        // Save to temp
444        let target = TestKeyManager;
445        target.save_keys(did_suffix, KeyType::SigningKey, &keys, true)?;
446
447        // Read keys
448        let actual_signing = target.read_signing_keys(did_suffix)?;
449
450        // Check keys saved are same as those read back
451        assert_eq!(keys, actual_signing);
452
453        Ok(())
454    }
455
456    #[test]
457    fn test_apply_next_update_key() -> Result<(), Box<dyn std::error::Error>> {
458        // Set env var
459        init();
460
461        // Make path for this test
462        let did_suffix = "test_apply_next_update_key";
463
464        let target = TestKeyManager;
465
466        // Save update key and next update key
467        let update_key: JWK = serde_json::from_str(TEST_UPDATE_KEY)?;
468        let next_update_key: JWK = serde_json::from_str(TEST_NEXT_UPDATE_KEY)?;
469        target.save_key(did_suffix, KeyType::UpdateKey, &update_key, true)?;
470        target.save_key(did_suffix, KeyType::NextUpdateKey, &next_update_key, true)?;
471
472        // Read next update
473        let loaded_update_key = target.read_update_key(did_suffix)?;
474        let loaded_next_update_key = target.read_next_update_key(did_suffix)?;
475        assert_eq!(loaded_update_key, update_key);
476        assert_eq!(loaded_next_update_key, next_update_key);
477
478        // // Apply next update key
479        target.apply_next_update_key(did_suffix, &next_update_key)?;
480
481        // // Check if next_update_key is removed
482        let path = target.get_path(did_suffix, &KeyType::NextUpdateKey, false)?;
483        if path.is_file() {
484            return Err(Box::new(KeyManagerError::FailedToRemoveKey));
485        }
486
487        // Check the update key is now next_update_key
488        let actual_update_key = target.read_update_key(did_suffix)?;
489
490        // Check update key is now next_update_key
491        assert_eq!(next_update_key, actual_update_key);
492
493        Ok(())
494    }
495}