Added in the list function

master
Tom Alexander 5 years ago
parent 49e5919afa
commit b8f407c2b9

@ -1,11 +1,21 @@
use super::db;
use crypto::aes::{self, KeySize};
use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::scrypt::{self, ScryptParams};
use crypto::sha2::Sha256;
use rand::rngs::OsRng;
use rand::Rng;
use rustc_serialize::base64;
use rustc_serialize::base64::{FromBase64, ToBase64};
use std::io;
pub struct EncryptedValue {
pub ciphertext: Vec<u8>,
pub iv: [u8; 32],
pub mac: MacResult,
}
pub fn get_master_key(db_conn: &db::DbHandle, master_password: &str) -> io::Result<[u8; 32]> {
let scrypt_params: ScryptParams = ScryptParams::new(12, 16, 2);
let salt: Vec<u8> = get_salt(db_conn)?;
@ -37,3 +47,16 @@ fn get_salt(db_conn: &db::DbHandle) -> io::Result<Vec<u8>> {
}
}
}
pub fn decrypt_value(value: Vec<u8>, master_key: [u8; 32], iv: [u8; 32], mac: [u8; 32]) -> Vec<u8> {
let mut hmac = Hmac::new(Sha256::new(), &master_key);
hmac.input(&value[..]);
if hmac.result() != MacResult::new(&mac) {
panic!("Mac did not match, corrupted data");
}
let mut cipher = aes::ctr(KeySize::KeySize256, &master_key, &iv);
let mut output: Vec<u8> = vec![0; value.len() as usize];
cipher.process(&value, output.as_mut_slice());
output
}

@ -1,4 +1,5 @@
use rusqlite::Connection;
use super::crypt;
use rusqlite::{Connection, NO_PARAMS};
use rustc_serialize::base64;
use rustc_serialize::base64::{FromBase64, ToBase64};
use std::error::Error;
@ -16,6 +17,14 @@ struct DbProperty {
value: Option<String>,
}
#[derive(Debug)]
pub struct Account {
pub id: i64,
pub host: String,
pub user: String,
pub password: String,
}
impl DbHandle {
pub fn new(db_path: &Option<String>) -> DbHandle {
let path: PathBuf = db_path
@ -25,7 +34,7 @@ impl DbHandle {
let mut conn: Connection = Connection::open(path).unwrap();
let tx = conn.transaction().unwrap();
tx.execute_batch(DB_INIT_QUERY).unwrap();
tx.commit();
tx.commit().unwrap();
DbHandle { conn: conn }
}
@ -65,4 +74,65 @@ impl DbHandle {
let b64value: String = value.to_base64(base64::STANDARD);
self.set_db_property(name, &b64value);
}
pub fn list_accounts(&mut self, master_key: [u8; 32]) -> Vec<Account> {
let mut stmt = self.conn
.prepare("SELECT h.iv, h.ciphertext, h.mac, u.iv, u.ciphertext, u.mac, p.iv, p.ciphertext, p.mac, a.id FROM accounts a \
LEFT JOIN encrypted_values h ON a.server=h.id \
LEFT JOIN encrypted_values u ON a.user=u.id \
LEFT JOIN encrypted_values p ON a.password=p.id")
.unwrap();
let result: Vec<Account> = {
let props = stmt
.query_map(NO_PARAMS, |row| {
let host: String = String::from_utf8(decrypt_base64(
row.get(0).unwrap(),
row.get(1).unwrap(),
row.get(2).unwrap(),
master_key,
))
.unwrap();
let user: String = String::from_utf8(decrypt_base64(
row.get(3).unwrap(),
row.get(4).unwrap(),
row.get(5).unwrap(),
master_key,
))
.unwrap();
let password: String = String::from_utf8(decrypt_base64(
row.get(6).unwrap(),
row.get(7).unwrap(),
row.get(8).unwrap(),
master_key,
))
.unwrap();
Ok(Account {
id: row.get(9).unwrap(),
host: host,
user: user,
password: password,
})
})
.unwrap();
props.map(move |x| x.unwrap()).collect()
};
result
}
}
fn decrypt_base64(iv: String, ciphertext: String, mac: String, master_key: [u8; 32]) -> Vec<u8> {
let mut iv_bytes: [u8; 32] = [0; 32];
let mut mac_bytes: [u8; 32] = [0; 32];
iv_bytes.clone_from_slice(&iv.from_base64().unwrap());
mac_bytes.clone_from_slice(&mac.from_base64().unwrap());
let decrypted: Vec<u8> = crypt::decrypt_value(
ciphertext.from_base64().unwrap(),
master_key,
iv_bytes,
mac_bytes,
);
decrypted
}

@ -90,6 +90,16 @@ fn get_master_key(db_conn: &mut db::DbHandle) -> [u8; 32] {
master_key
}
fn list(mut db_conn: db::DbHandle, master_key: [u8; 32]) {
for host in db_conn
.list_accounts(master_key)
.into_iter()
.map(|account: db::Account| account.host)
{
println!("{}", host);
}
}
fn main() -> Result<(), Box<dyn Error>> {
pretty_env_logger::init();
let args: Args = Docopt::new(USAGE)
@ -106,5 +116,9 @@ fn main() -> Result<(), Box<dyn Error>> {
let master_key: [u8; 32] = get_master_key(&mut db_conn);
if args.cmd_list {
list(db_conn, master_key);
}
Ok(())
}

Loading…
Cancel
Save