Skip to main content

karak_kms/keystore/
local.rs

1use std::{
2    fs::File,
3    io::{Read, Write},
4    path::PathBuf,
5};
6
7use crate::keypair::traits::Encryptable;
8
9use super::traits::EncryptedKeystore;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
13pub enum LocalKeystoreError<Keypair: Encryptable + Send + Sync> {
14    #[error("Encryption error: {0}")]
15    EncryptionError(Keypair::EncryptionError),
16
17    #[error("IO error: {0}")]
18    IoError(#[from] std::io::Error),
19
20    #[error("Decoding error: {0}")]
21    DecodingError(#[from] bs58::decode::Error),
22}
23
24pub struct LocalEncryptedKeystore {
25    file_path: PathBuf,
26}
27
28impl LocalEncryptedKeystore {
29    pub fn new(file_path: PathBuf) -> Self {
30        Self { file_path }
31    }
32}
33
34impl<Keypair: Encryptable + Send + Sync + std::fmt::Debug> EncryptedKeystore<Keypair>
35    for LocalEncryptedKeystore
36{
37    type StorageError = LocalKeystoreError<Keypair>;
38
39    fn store(&self, keypair: &Keypair, passphrase: &str) -> Result<(), Self::StorageError> {
40        let encrypted_keypair = keypair
41            .encrypt(passphrase)
42            // TODO: Handle this error better. There has to be a more idiomatic way. cc @johanan
43            .map_err(|err| LocalKeystoreError::EncryptionError(err))?;
44
45        let mut file = File::create(&self.file_path)?;
46
47        file.write_all(bs58::encode(&encrypted_keypair).into_vec().as_slice())?;
48
49        Ok(())
50    }
51
52    fn retrieve(&self, passphrase: &str) -> Result<Keypair, Self::StorageError> {
53        let mut file = File::open(&self.file_path)?;
54        let mut buf = vec![];
55        file.read_to_end(&mut buf)?;
56
57        let encrypted_keypair = bs58::decode(buf).into_vec()?;
58
59        Keypair::decrypt(&encrypted_keypair, passphrase)
60            // TODO: Handle this error better. There has to be a more idiomatic way. cc @johanan
61            .map_err(|err| LocalKeystoreError::EncryptionError(err))
62    }
63}