Added in the list function
This commit is contained in:
parent
49e5919afa
commit
b8f407c2b9
23
src/crypt.rs
23
src/crypt.rs
@ -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
|
||||
}
|
||||
|
74
src/db.rs
74
src/db.rs
@ -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
|
||||
}
|
||||
|
14
src/main.rs
14
src/main.rs
@ -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…
x
Reference in New Issue
Block a user