🚧 Just fix intermediate state

feature/database-encription
German Lashevich 7 years ago
parent 69cf557386
commit 49ffb08499
No known key found for this signature in database
GPG Key ID: 3446FAE369C9A8B4

45
Cargo.lock generated

@ -42,6 +42,11 @@ name = "byte-tools"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.2"
@ -148,6 +153,11 @@ dependencies = [
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hmac"
version = "0.1.1"
@ -174,13 +184,14 @@ dependencies = [
[[package]]
name = "keyring"
version = "0.5.1"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"secret-service 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -320,17 +331,6 @@ dependencies = [
"redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rpassword"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rpassword"
version = "2.0.0"
@ -378,10 +378,11 @@ dependencies = [
"base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"keyring 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keyring 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"oath 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -491,14 +492,6 @@ dependencies = [
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termios"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.9.0"
@ -580,6 +573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum byte-tools 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0919189ba800c7ffe8778278116b7e0de3905ab81c72abb69c85cbfef7991279"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
@ -594,10 +588,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum generic-array 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe043cf9b85297937897087de81f590361686e1ac2d4d471b45435de5dfb6a6"
"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
"checksum hmac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb5aa9647ba4711e9d6968dc1c810cd23989ed435443ca962e1bf6d8b8b83ff"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum keyring 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a13a4970024d20522520ecf2218f31fa9fc12dd4497a3901f79a137b425a184e"
"checksum keyring 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c503cc96b828521df71d8ef94edb17d3b7c0ef2caededd064b78fc5e1205de7b"
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
"checksum nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
@ -614,7 +609,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5f78082e6a6d042862611e9640cf20776185fee506cf6cf67e93c6225cee31"
"checksum redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "07b8f011e3254d5a9b318fde596d409a0001c9ae4c6e7907520c2eaa4d988c99"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0eee8d16609fa0ec2a13c8d812fc6049f71d3cdd93f6f713fedf6397868c5c"
"checksum rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d127299b02abda51634f14025aec43ae87a7aa7a95202b6a868ec852607d1451"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rust-gmp 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cd7d57377b309a73f69e164109203aa9ab3fee6ea68ac5fb76e2edb50662e9b"
@ -631,7 +625,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
"checksum typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a99dc6780ef33c78780b826cf9d2a78840b72cae9474de4bcaf9051e60ebbd"

@ -14,14 +14,18 @@ version = "0.2.1"
[dependencies]
base32 = "0.3.1"
clap = "^2.29.0"
ctrlc = { version = "3.0", features = ["termination"] }
keyring = "0.5.1"
keyring = "0.6.0"
oath = "0.10.2"
rand = "0.4.1"
rpassword = "2.0.0"
rust-crypto = "0.2.36"
serde = "1.0.24"
serde_derive = "1.0.24"
serde_json = "1.0.8"
[dependencies.ctrlc]
features = ["termination"]
version = "3.0"
[profile.release]
debug = false
lto = true

21
TODO

@ -0,0 +1,21 @@
# Change approach for saving and loading data
## On load
1. Read encrypted data into memory
2. Invoke decrypt function, which takes IV from the beginning of the data
3. Retrieve secret
4. Decrypt data
5. Unserialize data
## On save
1. Serialize data
2. Generate IV
3. Retrieve secret
4. Encrypt data
5. Concatenate IV + encrypted data
6. Save data to file
# Implement secret retrieval from OS's keyring

@ -22,12 +22,19 @@ struct Cli {
impl Cli {
fn new() -> Self {
let db = JsonDatabase::new(Self::get_database_path());
let secret = Self::get_secret();
let db = JsonDatabase::new(Self::get_database_path(), &secret);
Self {
app: RusTOTPony::new(db),
}
}
fn get_secret() -> String {
return rpassword::prompt_password_stdout("Enter your database pass: ").unwrap();
}
// fn get_secret_from_storage() -> String { }
fn run(&mut self) {
match self.get_cli_api_matches().subcommand() {
("dash", Some(_)) => {

@ -1,4 +1,5 @@
extern crate base32;
extern crate crypto;
extern crate oath;
extern crate rand;
extern crate serde_json;
@ -6,6 +7,11 @@ extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use crypto::{aes, blockmodes, buffer, symmetriccipher};
use crypto::buffer::{BufferResult, ReadBuffer, WriteBuffer};
use rand::{OsRng, Rng};
use std::collections::HashMap;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::ErrorKind;
@ -121,11 +127,15 @@ struct DatabaseContentSchema {
pub struct JsonDatabase {
file_path: PathBuf,
secret: String,
}
impl JsonDatabase {
pub fn new(path: PathBuf) -> JsonDatabase {
JsonDatabase { file_path: path }
pub fn new(path: PathBuf, secret: &str) -> JsonDatabase {
JsonDatabase {
file_path: path,
secret: String::from(secret),
}
}
fn read_database_file(&self) -> JsonDatabaseSchema {
@ -147,6 +157,105 @@ impl JsonDatabase {
serde_json::to_writer(file, &content).expect("Couldn't write JSON data to database file");
}
// Encrypt a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
fn encrypt(
data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
// Create an encryptor instance of the best performing
// type available for the platform.
let mut encryptor =
aes::cbc_encryptor(aes::KeySize::KeySize256, key, iv, blockmodes::PkcsPadding);
// Each encryption operation encrypts some data from
// an input buffer into an output buffer. Those buffers
// must be instances of RefReaderBuffer and RefWriteBuffer
// (respectively) which keep track of how much data has been
// read from or written to them.
let mut final_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(data);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
// Each encryption operation will "make progress". "Making progress"
// is a bit loosely defined, but basically, at the end of each operation
// either BufferUnderflow or BufferOverflow will be returned (unless
// there was an error). If the return value is BufferUnderflow, it means
// that the operation ended while wanting more input data. If the return
// value is BufferOverflow, it means that the operation ended because it
// needed more space to output data. As long as the next call to the encryption
// operation provides the space that was requested (either more input data
// or more output space), the operation is guaranteed to get closer to
// completing the full operation - ie: "make progress".
//
// Here, we pass the data to encrypt to the enryptor along with a fixed-size
// output buffer. The 'true' flag indicates that the end of the data that
// is to be encrypted is included in the input buffer (which is true, since
// the input data includes all the data to encrypt). After each call, we copy
// any output data to our result Vec. If we get a BufferOverflow, we keep
// going in the loop since it means that there is more work to do. We can
// complete as soon as we get a BufferUnderflow since the encryptor is telling
// us that it stopped processing data due to not having any more data in the
// input buffer.
loop {
let result = try!(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true));
// "write_buffer.take_read_buffer().take_remaining()" means:
// from the writable buffer, create a new readable buffer which
// contains all data that has been written, and then access all
// of that data as a slice.
final_result.extend(
write_buffer
.take_read_buffer()
.take_remaining()
.iter()
.map(|&i| i),
);
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
Ok(final_result)
}
// Decrypts a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
fn decrypt(
encrypted_data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let mut decryptor =
aes::cbc_decryptor(aes::KeySize::KeySize256, key, iv, blockmodes::PkcsPadding);
let mut final_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
final_result.extend(
write_buffer
.take_read_buffer()
.take_remaining()
.iter()
.map(|&i| i),
);
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
Ok(final_result)
}
fn create_database_file(&self) -> Result<File, std::io::Error> {
let dir = std::env::home_dir().unwrap_or(PathBuf::from("."));
if let Some(parent_dir) = Path::new(&self.file_path).parent() {

Loading…
Cancel
Save