From d40f297e1991aea905127804e34055703ac5f8c5 Mon Sep 17 00:00:00 2001 From: Mystikfluu Date: Wed, 28 Dec 2022 01:19:10 +0100 Subject: [PATCH] added encryption --- .gitignore | 2 + Cargo.lock | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +- src/main.rs | 10 +-- src/utils.rs | 68 ++++++++++++++++--- 5 files changed, 256 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..9e50c14 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +comp.bat +comp.sh \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e09b1ce..1abae61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,115 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -19,6 +122,22 @@ dependencies = [ "wasi", ] +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "home" version = "0.5.4" @@ -28,13 +147,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipass" version = "0.1.0" dependencies = [ + "aes-gcm", + "hex", "home", "rand", "rpassword", + "sha2", ] [[package]] @@ -43,6 +174,24 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "polyval" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -100,6 +249,45 @@ dependencies = [ "winapi", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index fccfb07..bd90d8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,7 @@ edition = "2021" [dependencies] home = "0.5.4" rpassword = "7.2" -rand = "0.8.5" \ No newline at end of file +rand = "0.8.5" +aes-gcm = "0.10.1" +sha2 = "0.10.6" +hex = "0.4.3" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a336f14..8a92b8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::io::Write; mod utils; fn main() { - let version = "0.1.2"; + let version = "0.2.0"; println!("IPass v{}\n", version); let args = utils::get_args(); @@ -117,10 +117,10 @@ fn add(args: &Vec) { return; } - let mut pw: String; + let pw: String; if args.len() > 3 { - pw = args[3].to_owned(); + pw = args[3].trim().to_owned(); } else { let alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!\"§$%&/()=?´`²³{[]}\\,.-;:_><|+*#'"; let char_set:Vec = alphabet.clone().chars().collect(); @@ -137,7 +137,7 @@ fn add(args: &Vec) { } println!("Adding password for {}",args[2]); - let succeeded = utils::create_entry(&args[2],&mut pw); + let succeeded = utils::create_entry(&args[2], pw); if !succeeded { println!("You already have an entry with that name! Did you mean to use \"edit\"?"); return; @@ -154,7 +154,7 @@ fn get(args: &Vec) { let filepath = &(utils::get_ipass_folder()+name+".ipass"); if std::path::Path::new(filepath).exists() { println!("Getting entry"); - println!("{}",utils::get_entry(filepath)); + println!("{}",utils::get_entry(name)); } else { println!("No such entry!"); return; diff --git a/src/utils.rs b/src/utils.rs index 2adc9ce..8fcd9db 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,16 +1,62 @@ use std::io::Write; - +use aes_gcm::{ + aead::{Aead, KeyInit}, + Aes256Gcm, Nonce +}; +use sha2::{Sha256, Digest}; pub fn get_args() -> Vec { std::env::args().collect() // [0] = file path; [n>0] = argument } -fn encrypt_pass(pass: &mut String,_mpw: String) -> &mut String { - return pass; +fn vecu8_to_string(vec: Vec) -> String { + let mut out: String = String::new(); + for ind in vec { + if let Ok(a) = std::str::from_utf8(&[ind]) { + out += a; + } else { + panic!("malformed character"); + } + } + return out } -fn decrypt_pass(pass: &mut String, _mpw: String) -> &mut String { - return pass; +fn encrypt_pass(nonce_arg:String, pass: String,mpw: String) -> String { + let mut nonce_argument = String::new(); + if nonce_arg.len() < 12 { + nonce_argument = nonce_arg.clone() + &" ".repeat(12-nonce_arg.len()); + } + if nonce_arg.len() > 12 { + nonce_argument = nonce_arg[0..12].to_string(); + } + let mut hasher = Sha256::new(); + hasher.update(mpw.as_bytes()); + + let master_pw = &hasher.finalize(); + + let cipher = Aes256Gcm::new(master_pw); + let nonce = Nonce::from_slice(nonce_argument.as_bytes()); // 96-bits; unique per message + let ciphertext = cipher.encrypt(nonce, pass.as_ref()).unwrap(); + return hex::encode(ciphertext); +} + +fn decrypt_pass(nonce_arg:String, pass: Vec,mpw: String) -> String { + let mut nonce_argument = String::new(); + if nonce_arg.len() < 12 { + nonce_argument = nonce_arg.clone() + &" ".repeat(12-nonce_arg.len()); + } + if nonce_arg.len() > 12 { + nonce_argument = nonce_arg[0..12].to_string(); + } + let mut hasher = Sha256::new(); + hasher.update(mpw.as_bytes()); + + let master_pw = &hasher.finalize(); + let cipher = Aes256Gcm::new(master_pw); + let nonce = Nonce::from_slice(nonce_argument.as_bytes()); // 96-bits; unique per message + + let plaintext = cipher.decrypt(nonce, pass.as_ref()).unwrap(); + return vecu8_to_string(plaintext); } pub fn get_home_folder_str() -> String { @@ -32,7 +78,7 @@ pub fn get_ipass_folder() -> String { return path; } -pub fn create_entry(name:&String, pw:&mut String) -> bool { +pub fn create_entry(name: &String, pw: String) -> bool { if std::path::Path::new(&(get_ipass_folder()+name+".ipass")).exists() { return false; } @@ -40,15 +86,15 @@ pub fn create_entry(name:&String, pw:&mut String) -> bool { return true; } -pub fn get_entry(filepath:&String) -> String { - let content = &mut std::fs::read_to_string(filepath).expect("Should have been able to read the file"); +pub fn get_entry(name:&String) -> String { + let content = &mut std::fs::read_to_string(get_ipass_folder()+name+".ipass").expect("Should have been able to read the file"); let mpw = ask_for_pw(); - return decrypt_pass(content,mpw).to_owned(); + return decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw).to_owned(); } -pub fn edit_entry(name:&String,mut pw:&mut String) { +pub fn edit_entry(name:&String,mut pw:String) { let mpw = ask_for_pw(); - pw = encrypt_pass(pw,mpw); + pw = encrypt_pass(name.to_owned(), pw,mpw); let mut file = std::fs::File::create(get_ipass_folder()+name+".ipass").unwrap(); file.write_all(pw.as_bytes()).unwrap(); }