diff --git a/src/system/keys/filestorage.rs b/src/system/keys/filestorage.rs
new file mode 100644
index 0000000..da14682
--- /dev/null
+++ b/src/system/keys/filestorage.rs
@@ -0,0 +1,160 @@
+//! ## FileStorage
+//!
+//! `filestorage` provides an implementation of the `KeyStorage` trait using a file
+
+/*
+*
+* Copyright (C) 2020-2021 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "TermSCP"
+*
+* TermSCP is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* TermSCP is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with TermSCP. If not, see .
+*
+*/
+
+use super::{KeyStorage, KeyStorageError};
+
+use std::fs::{OpenOptions, Permissions};
+use std::io::{Read, Write};
+use std::path::{Path, PathBuf};
+
+/// ## FileStorage
+///
+/// File storage is an implementation o the `KeyStorage` which uses a file to store the key
+pub struct FileStorage {
+ dir_path: PathBuf,
+}
+
+impl FileStorage {
+ /// ### new
+ ///
+ /// Instantiates a new `FileStorage`
+ pub fn new(dir_path: &Path) -> Self {
+ FileStorage {
+ dir_path: PathBuf::from(dir_path),
+ }
+ }
+
+ /// ### make_file_path
+ ///
+ /// Make file path for key file from `dir_path` and the application id
+ fn make_file_path(&self, storage_id: &str) -> PathBuf {
+ let mut p: PathBuf = self.dir_path.clone();
+ let file_name = format!(".{}.key", storage_id);
+ p.push(file_name);
+ p
+ }
+}
+
+impl KeyStorage for FileStorage {
+ /// ### get_key
+ ///
+ /// Retrieve key from the key storage.
+ /// The key might be acccess through an identifier, which identifies
+ /// the key in the storage
+ fn get_key(&self, storage_id: &str) -> Result {
+ let key_file: PathBuf = self.make_file_path(storage_id);
+ // Check if file exists
+ if !key_file.exists() {
+ return Err(KeyStorageError::NoSuchKey);
+ }
+ // Read key from file
+ match OpenOptions::new().read(true).open(key_file.as_path()) {
+ Ok(mut file) => {
+ let mut key: String = String::new();
+ match file.read_to_string(&mut key) {
+ Ok(_) => Ok(key),
+ Err(_) => Err(KeyStorageError::Io),
+ }
+ }
+ Err(_) => Err(KeyStorageError::Io),
+ }
+ }
+
+ /// ### set_key
+ ///
+ /// Set the key into the key storage
+ fn set_key(&self, storage_id: &str, key: &str) -> Result<(), KeyStorageError> {
+ let key_file: PathBuf = self.make_file_path(storage_id);
+ // Write key
+ match OpenOptions::new()
+ .write(true)
+ .create(true)
+ .truncate(true)
+ .open(key_file.as_path())
+ {
+ Ok(mut file) => {
+ // Write key to file
+ if let Err(_) = file.write_all(key.as_bytes()) {
+ return Err(KeyStorageError::Io);
+ }
+ // Set file to readonly
+ let mut permissions: Permissions = file.metadata().unwrap().permissions();
+ permissions.set_readonly(true);
+ let _ = file.set_permissions(permissions);
+ Ok(())
+ }
+ Err(_) => Err(KeyStorageError::Io),
+ }
+ }
+
+ /// is_supported
+ ///
+ /// Returns whether the key storage is supported on the host system
+ fn is_supported(&self) -> bool {
+ true
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn test_system_keys_filestorage_make_dir() {
+ let storage: FileStorage = FileStorage::new(&Path::new("/tmp/"));
+ assert_eq!(
+ storage.make_file_path("bookmarks").as_path(),
+ Path::new("/tmp/.bookmarks.key")
+ );
+ }
+
+ #[test]
+ fn test_system_keys_filestorage_ok() {
+ let key_dir: tempfile::TempDir =
+ tempfile::TempDir::new().expect("Could not create tempdir");
+ let storage: FileStorage = FileStorage::new(key_dir.path());
+ let app_name: &str = "termscp";
+ let secret: &str = "Th15-15/My-Супер-Секрет";
+ // Secret should not exist
+ assert_eq!(
+ storage.get_key(app_name).err().unwrap(),
+ KeyStorageError::NoSuchKey
+ );
+ // Write secret
+ assert!(storage.set_key(app_name, secret).is_ok());
+ // Get secret
+ assert_eq!(storage.get_key(app_name).ok().unwrap().as_str(), secret);
+ }
+
+ #[test]
+ fn test_system_keys_filestorage_err() {
+ let bad_dir: &Path = Path::new("/piro/poro/pero/");
+ let storage: FileStorage = FileStorage::new(bad_dir);
+ let app_name: &str = "termscp";
+ let secret: &str = "Th15-15/My-Супер-Секрет";
+ assert!(storage.set_key(app_name, secret).is_err());
+ }
+}
diff --git a/src/system/keys/mod.rs b/src/system/keys/mod.rs
new file mode 100644
index 0000000..5ef9802
--- /dev/null
+++ b/src/system/keys/mod.rs
@@ -0,0 +1,72 @@
+//! ## KeyStorage
+//!
+//! `keystorage` provides the trait to manipulate to a KeyStorage
+
+/*
+*
+* Copyright (C) 2020-2021 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "TermSCP"
+*
+* TermSCP is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* TermSCP is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with TermSCP. If not, see .
+*
+*/
+
+// Storages
+pub mod filestorage;
+
+/// ## KeyStorageError
+///
+/// defines the error type for the `KeyStorage`
+#[derive(PartialEq, std::fmt::Debug)]
+pub enum KeyStorageError {
+ BadKey,
+ Io,
+ NoSuchKey,
+}
+
+impl std::fmt::Display for KeyStorageError {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ let err: String = String::from(match &self {
+ KeyStorageError::BadKey => "Bad key syntax",
+ KeyStorageError::Io => "Input/Output error",
+ KeyStorageError::NoSuchKey => "No such key",
+ });
+ write!(f, "{}", err)
+ }
+}
+
+/// ## KeyStorage
+///
+/// this traits provides the methods to communicate and interact with the key storage.
+pub trait KeyStorage {
+
+ /// ### get_key
+ ///
+ /// Retrieve key from the key storage.
+ /// The key might be acccess through an identifier, which identifies
+ /// the key in the storage
+ fn get_key(&self, storage_id: &str) -> Result;
+
+ /// ### set_key
+ ///
+ /// Set the key into the key storage
+ fn set_key(&self, storage_id: &str, key: &str) -> Result<(), KeyStorageError>;
+
+ /// is_supported
+ ///
+ /// Returns whether the key storage is supported on the host system
+ fn is_supported(&self) -> bool;
+
+}
diff --git a/src/system/mod.rs b/src/system/mod.rs
index 2e2e624..371d408 100644
--- a/src/system/mod.rs
+++ b/src/system/mod.rs
@@ -27,4 +27,5 @@
pub mod bookmarks_client;
pub mod config_client;
pub mod environment;
+pub(crate) mod keys;
pub mod sshkey_storage;