mirror of
https://github.com/002Hub/IPass.git
synced 2025-04-19 13:51:21 +02:00
move utils to a seperate library
This commit is contained in:
parent
0c9f796658
commit
f3c0b89bdf
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,4 +3,5 @@ comp.bat
|
||||
comp.sh
|
||||
report.json
|
||||
*.ipass
|
||||
*.ipassx
|
||||
*.ipassx
|
||||
library/*
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "library"]
|
||||
path = library
|
||||
url = https://github.com/002Hub/IPass-library
|
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -192,8 +192,8 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipass"
|
||||
version = "0.4.0"
|
||||
name = "ip_lib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"brotli",
|
||||
@ -204,6 +204,14 @@ dependencies = [
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipass"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"ip_lib",
|
||||
"rpassword",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
|
11
Cargo.toml
11
Cargo.toml
@ -1,22 +1,17 @@
|
||||
[package]
|
||||
name = "ipass"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
home = "0.5.4"
|
||||
rpassword = "7.2"
|
||||
rand = { features = ["std"], default-features = false, version = "0.8.5" }
|
||||
aes-gcm = { features = ["alloc", "aes"], default-features = false, version = "0.10.1" }
|
||||
sha2 = { default-features = false, version = "0.10.6" }
|
||||
hex = "0.4.3"
|
||||
brotli = { features = ["std"], default-features = false, version = "3.3.4" }
|
||||
ip_lib = { path = "library/" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = 'z' # Optimize for size
|
||||
lto = true # Enable link-time optimization
|
||||
codegen-units = 1 # Reduce number of codegen units to increase optimizations
|
||||
panic = 'abort' # Abort on panic
|
||||
# strip = true # Strip symbols from binary; remove pdb
|
||||
# strip = true # Strip symbols from binary; remove pdb
|
4
build.rs
4
build.rs
@ -1,3 +1,5 @@
|
||||
fn main() {
|
||||
println!("cargo:rustc-link-arg=.res");
|
||||
if std::env::consts::OS == "windows" {
|
||||
println!("cargo:rustc-link-arg=.res");
|
||||
}
|
||||
}
|
1
library
Submodule
1
library
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 380ae204378be877fffb7ee7f9167748defc2156
|
84
src/main.rs
84
src/main.rs
@ -3,17 +3,16 @@
|
||||
|
||||
//! IPass Password Manager
|
||||
|
||||
extern crate ip_lib;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
mod utils;
|
||||
|
||||
fn main() {
|
||||
let version = option_env!("CARGO_PKG_VERSION").unwrap_or("x.x.x");
|
||||
println!("IPass v{}\n", version);
|
||||
|
||||
let args = utils::get_args();
|
||||
let args = ip_lib::get_args();
|
||||
|
||||
if args.len() < 2 {
|
||||
help_message(&args);
|
||||
@ -22,15 +21,16 @@ fn main() {
|
||||
|
||||
let mode: &str = &args[1].trim().to_lowercase().to_owned();
|
||||
|
||||
let sync_file_loc = utils::get_home_folder_str()+"/.sync.ipass";
|
||||
let sync_file_loc = ip_lib::get_home_folder_str()+"/.sync.ipass";
|
||||
let sync_file_path = std::path::Path::new(&sync_file_loc);
|
||||
|
||||
let sync_enabled = sync_file_path.clone().exists();
|
||||
let sync_loc: String;
|
||||
|
||||
if sync_enabled {
|
||||
// println!("Sync enabled, syncing...");
|
||||
sync_loc = std::fs::read_to_string(sync_file_path).expect("Should have been able to read the sync file");
|
||||
utils::import_file(&sync_loc);
|
||||
ip_lib::import_file(&sync_loc);
|
||||
} else {
|
||||
sync_loc = "".to_string(); //sync is disabled, no location needed
|
||||
}
|
||||
@ -52,7 +52,7 @@ fn main() {
|
||||
_ => help_message(&args),
|
||||
}
|
||||
if sync_enabled {
|
||||
utils::export_file(&sync_loc);
|
||||
ip_lib::export_file(&sync_loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,13 +134,13 @@ fn help_message(args: &Vec<String>) {
|
||||
}
|
||||
|
||||
fn list() {
|
||||
let mut paths: std::fs::ReadDir = std::fs::read_dir(utils::get_ipass_folder()).unwrap();
|
||||
let mut paths = ip_lib::get_entries();
|
||||
|
||||
let mut has_entry:bool = false;
|
||||
|
||||
println!("Total entries: {}\n", paths.count());
|
||||
|
||||
paths = std::fs::read_dir(utils::get_ipass_folder()).unwrap();
|
||||
paths = ip_lib::get_entries();
|
||||
|
||||
for path in paths {
|
||||
has_entry = true;
|
||||
@ -167,17 +167,7 @@ fn add(args: &Vec<String>) {
|
||||
if args.len() > 4 {
|
||||
pw = username+";"+args[4].trim();
|
||||
} else {
|
||||
let alphabet: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!\"$%&/()=?{[]}\\,.-;:_><|+*#'";
|
||||
let alph_len: usize = alphabet.chars().count();
|
||||
let char_set:Vec<char> = alphabet.chars().collect();
|
||||
let mut chars_index: Vec<u8> = vec![0;20];
|
||||
OsRng.fill_bytes(&mut chars_index);
|
||||
let mut chars: String = String::new();
|
||||
|
||||
for index in chars_index {
|
||||
// println!("{} - {} - {}",index,(index as usize)%(alph_len-1),alph_len);
|
||||
chars += &char_set[(index as usize)%(alph_len-1)].to_string();
|
||||
}
|
||||
let chars = ip_lib::random_password();
|
||||
pw = username+";"+chars.as_str();
|
||||
|
||||
println!("Using auto generated password");
|
||||
@ -186,7 +176,7 @@ fn add(args: &Vec<String>) {
|
||||
}
|
||||
|
||||
println!("Adding password for {}",args[2]);
|
||||
let succeeded: bool = utils::create_entry(&args[2], pw);
|
||||
let succeeded: bool = ip_lib::create_entry(&args[2], pw);
|
||||
if !succeeded {
|
||||
println!("You already have an entry with that name! Did you mean to use \"edit\"?");
|
||||
return;
|
||||
@ -201,10 +191,10 @@ fn get(args: &Vec<String>) {
|
||||
return;
|
||||
}
|
||||
let name: &String = &args[2];
|
||||
let filepath = &(utils::get_ipass_folder()+name+".ipass");
|
||||
let filepath = &(ip_lib::get_ipass_folder()+name+".ipass");
|
||||
if std::path::Path::new(filepath).exists() {
|
||||
println!("Getting entry");
|
||||
let entry: String = utils::get_entry(name);
|
||||
let entry: String = ip_lib::get_entry(name);
|
||||
let mut data = entry.split(";");
|
||||
println!("Username: '{}' Password: '{}'",data.next().unwrap(),data.next().unwrap());
|
||||
} else {
|
||||
@ -219,7 +209,7 @@ fn changepw(args: &Vec<String>) {
|
||||
println!("Invalid usage of \"changepw\"");
|
||||
return;
|
||||
}
|
||||
let filepath = &(utils::get_ipass_folder()+&args[2]+".ipass");
|
||||
let filepath = &(ip_lib::get_ipass_folder()+&args[2]+".ipass");
|
||||
if std::path::Path::new(filepath).exists() {
|
||||
let output: String;
|
||||
if args.len() != 4 {
|
||||
@ -228,7 +218,7 @@ fn changepw(args: &Vec<String>) {
|
||||
output = args[3].clone();
|
||||
}
|
||||
|
||||
utils::edit_password(&args[2], output);
|
||||
ip_lib::edit_password(&args[2], output);
|
||||
|
||||
println!("Changed Password of {}!", args[2]);
|
||||
} else {
|
||||
@ -242,16 +232,16 @@ fn changeuser(args: &Vec<String>) {
|
||||
println!("Invalid usage of \"changeuser\"");
|
||||
return;
|
||||
}
|
||||
let filepath = &(utils::get_ipass_folder()+&args[2]+".ipass");
|
||||
let filepath = &(ip_lib::get_ipass_folder()+&args[2]+".ipass");
|
||||
if std::path::Path::new(filepath).exists() {
|
||||
let output: String;
|
||||
if args.len() != 4 {
|
||||
output = utils::prompt_answer("Enter new Username: ".to_string());
|
||||
output = ip_lib::prompt_answer("Enter new Username: ".to_string());
|
||||
} else {
|
||||
output = args[3].clone();
|
||||
}
|
||||
|
||||
utils::edit_username(&args[2], output);
|
||||
ip_lib::edit_username(&args[2], output);
|
||||
|
||||
println!("Changed Username of {}!", args[2]);
|
||||
} else {
|
||||
@ -265,9 +255,9 @@ fn rename(args: &Vec<String>) {
|
||||
println!("Invalid usage of \"rename\"");
|
||||
return;
|
||||
}
|
||||
let filepath = &(utils::get_ipass_folder()+&args[2]+".ipass");
|
||||
let filepath = &(ip_lib::get_ipass_folder()+&args[2]+".ipass");
|
||||
if std::path::Path::new(filepath).exists() {
|
||||
utils::rename(&args[2],&args[3]);
|
||||
ip_lib::rename(&args[2],&args[3]);
|
||||
println!("Renamed {} to {}", args[2], args[3]);
|
||||
} else {
|
||||
println!("No such file");
|
||||
@ -281,9 +271,9 @@ fn remove(args: &Vec<String>) {
|
||||
return;
|
||||
}
|
||||
let name = &args[2];
|
||||
let filepath = &(utils::get_ipass_folder()+name+".ipass");
|
||||
let filepath = &(ip_lib::get_ipass_folder()+name+".ipass");
|
||||
if std::path::Path::new(filepath).exists() {
|
||||
if utils::prompt_answer(format!("Are you sure you want to delete {}? [y/N] ", name)) == "y" {
|
||||
if ip_lib::prompt_answer(format!("Are you sure you want to delete {}? [y/N] ", name)) == "y" {
|
||||
std::fs::remove_file(filepath).unwrap();
|
||||
println!("Removed entry \"{}\"", name);
|
||||
} else {
|
||||
@ -297,16 +287,16 @@ fn remove(args: &Vec<String>) {
|
||||
|
||||
fn import(args: &Vec<String>) {
|
||||
//! arguments: program import {location}
|
||||
let mut location = utils::get_home_folder_str();
|
||||
let mut location = ip_lib::get_home_folder_str();
|
||||
if args.len() == 3 {
|
||||
location = args[2].clone();
|
||||
} else {
|
||||
if utils::prompt_answer(format!("No location specified, defaulting to {} continue? [Y/n] ", location.clone())) == "n" {
|
||||
if ip_lib::prompt_answer(format!("No location specified, defaulting to {} continue? [Y/n] ", location.clone())) == "n" {
|
||||
println!("Operation cancelled");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if utils::import_file(&location) {
|
||||
if ip_lib::import_file(&location) {
|
||||
println!("Imported all entries!");
|
||||
} else {
|
||||
println!("No such file found!");
|
||||
@ -316,16 +306,16 @@ fn import(args: &Vec<String>) {
|
||||
|
||||
fn export(args: &Vec<String>) {
|
||||
//! arguments: program export {location}
|
||||
let mut location = utils::get_home_folder_str();
|
||||
let mut location = ip_lib::get_home_folder_str();
|
||||
if args.len() == 3 {
|
||||
location = args[2].clone();
|
||||
} else {
|
||||
if utils::prompt_answer(format!("No location specified, defaulting to {} continue? [Y/n] ", location.clone())) == "n" {
|
||||
if ip_lib::prompt_answer(format!("No location specified, defaulting to {} continue? [Y/n] ", location.clone())) == "n" {
|
||||
println!("Operation cancelled");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if utils::export_file(&location) {
|
||||
if ip_lib::export_file(&location) {
|
||||
println!("Saved at: '{}/export.ipassx'", location);
|
||||
} else {
|
||||
println!("Failed saving at '{}/export.ipassx' does it exist?",location);
|
||||
@ -333,16 +323,16 @@ fn export(args: &Vec<String>) {
|
||||
}
|
||||
|
||||
fn clear() {
|
||||
if utils::prompt_answer("Are you sure you want to clear everything? [y/N] ".to_string()) != "y" {
|
||||
if ip_lib::prompt_answer("Are you sure you want to clear everything? [y/N] ".to_string()) != "y" {
|
||||
println!("operation cancelled!");
|
||||
return;
|
||||
}
|
||||
|
||||
let paths = std::fs::read_dir(utils::get_ipass_folder()).unwrap();
|
||||
let paths = std::fs::read_dir(ip_lib::get_ipass_folder()).unwrap();
|
||||
|
||||
for path in paths {
|
||||
if let Ok(p) = path {
|
||||
std::fs::remove_file(utils::get_ipass_folder()+"/"+p.file_name().into_string().unwrap().as_str()).unwrap();
|
||||
std::fs::remove_file(ip_lib::get_ipass_folder()+"/"+p.file_name().into_string().unwrap().as_str()).unwrap();
|
||||
}
|
||||
}
|
||||
println!("Cleared all entries!");
|
||||
@ -363,19 +353,19 @@ fn sync(args: &Vec<String>) {
|
||||
let location: String;
|
||||
|
||||
if args.len() < 4 {
|
||||
location = utils::prompt_answer("No location specified, please provide the location of the file you want to sync: ".to_string());
|
||||
location = ip_lib::prompt_answer_nolower("No location specified, please provide the location of the file you want to sync: ".to_string());
|
||||
} else {
|
||||
location = args[3].clone();
|
||||
}
|
||||
|
||||
let mut sync_file = std::fs::File::create(utils::get_home_folder_str()+"/.sync.ipass").expect("could not open sync file");
|
||||
let mut sync_file = std::fs::File::create(ip_lib::get_home_folder_str()+"/.sync.ipass").expect("could not open sync file");
|
||||
sync_file.write(location.as_bytes()).expect("could not write to sync file");
|
||||
|
||||
if !utils::export_file(&location) {
|
||||
if !ip_lib::export_file(&location) {
|
||||
eprintln!("Test sync error, make sure you specified a valid folder!");
|
||||
} else {
|
||||
println!("Sync is now Enabled!");
|
||||
println!("Sync file: {}",location);
|
||||
println!("Sync file: {}\\export.ipassx",location);
|
||||
}
|
||||
|
||||
|
||||
@ -384,14 +374,14 @@ fn sync(args: &Vec<String>) {
|
||||
},
|
||||
"off" => {
|
||||
|
||||
let sync_file_loc = utils::get_home_folder_str()+"/.sync.ipass";
|
||||
let sync_file_loc = ip_lib::get_home_folder_str()+"/.sync.ipass";
|
||||
let sync_file_path = std::path::Path::new(&sync_file_loc);
|
||||
|
||||
let sync_enabled = sync_file_path.clone().exists();
|
||||
|
||||
if sync_enabled {
|
||||
|
||||
std::fs::remove_file(utils::get_home_folder_str()+"/.sync.ipass").expect("could not disable sync, is it already disabled?");
|
||||
std::fs::remove_file(ip_lib::get_home_folder_str()+"/.sync.ipass").expect("could not disable sync, is it already disabled?");
|
||||
|
||||
println!("Sync is now Disabled!");
|
||||
} else {
|
||||
|
257
src/utils.rs
257
src/utils.rs
@ -1,257 +0,0 @@
|
||||
use std::io::{Read, Write};
|
||||
use aes_gcm::{
|
||||
aead::{Aead, KeyInit},
|
||||
Aes256Gcm, Nonce
|
||||
};
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
pub fn get_args() -> Vec<String> {
|
||||
std::env::args().collect() // [0] = file path; [n>0] = argument
|
||||
}
|
||||
|
||||
pub fn import_file(location:&String) -> bool {
|
||||
if std::path::Path::new(&(location.clone()+"/export.ipassx")).exists() {
|
||||
let mut reader = brotli::Decompressor::new(
|
||||
std::fs::File::open(location.clone()+"/export.ipassx").unwrap(),
|
||||
4096, // buffer size
|
||||
);
|
||||
let mut content: String = String::new();
|
||||
let mut buf = [0u8; 4096];
|
||||
loop {
|
||||
match reader.read(&mut buf[..]) {
|
||||
Err(e) => {
|
||||
if let std::io::ErrorKind::Interrupted = e.kind() {
|
||||
continue;
|
||||
}
|
||||
panic!("{}", e);
|
||||
}
|
||||
Ok(size) => {
|
||||
if size == 0 {
|
||||
break;
|
||||
}
|
||||
content += &std::str::from_utf8(&buf[..size]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let lines = content.lines();
|
||||
let mut name = "";
|
||||
for i in lines {
|
||||
if name == "" {
|
||||
name = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut file = std::fs::File::create(format!("{}/{}.ipass",get_ipass_folder(), name)).unwrap();
|
||||
file.write_all(i.as_bytes()).unwrap();
|
||||
name = "";
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn export_file(location:&String) -> bool {
|
||||
let mut collected_data: String = String::new();
|
||||
|
||||
let paths = std::fs::read_dir(get_ipass_folder()).unwrap();
|
||||
|
||||
for p in paths {
|
||||
if let Ok(path) = p {
|
||||
let content = &mut std::fs::read_to_string(get_ipass_folder()+&path.file_name().into_string().unwrap()).expect("Should have been able to read the file");
|
||||
collected_data += format!("{}\n{}\n", path.file_name().into_string().unwrap().replace(".ipass", ""),content).as_str();
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(file) = std::fs::File::create(location.clone()+"/export.ipassx") {
|
||||
let mut writer = brotli::CompressorWriter::new(
|
||||
file,
|
||||
4096,
|
||||
11,
|
||||
22);
|
||||
|
||||
match writer.write_all(collected_data.as_bytes()) {
|
||||
Err(e) => panic!("{}", e),
|
||||
Ok(_) => {},
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fn vecu8_to_string(vec: Vec<u8>) -> String {
|
||||
let mut do_print_warning = false;
|
||||
let mut out: String = String::new();
|
||||
for ind in vec {
|
||||
if let Ok(a) = std::str::from_utf8(&[ind]) {
|
||||
out += a;
|
||||
} else {
|
||||
do_print_warning = true;
|
||||
eprintln!("[WARNING] malformed character {}",ind);
|
||||
let mut temp_vec: Vec<u8> = Vec::new();
|
||||
temp_vec.insert(0,ind%128);
|
||||
out += vecu8_to_string(temp_vec).as_str();
|
||||
}
|
||||
}
|
||||
if do_print_warning {
|
||||
println!("[WARNING] Output may be corrupt");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
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 nonce_hasher = Sha256::new();
|
||||
nonce_hasher.update(nonce_argument.as_bytes());
|
||||
|
||||
let nonce_final = &nonce_hasher.finalize()[0..12];
|
||||
|
||||
|
||||
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_final); // 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<u8>,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 nonce_hasher = Sha256::new();
|
||||
nonce_hasher.update(nonce_argument.as_bytes());
|
||||
|
||||
let nonce_final = &nonce_hasher.finalize()[0..12];
|
||||
|
||||
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_final); // 96-bits; unique per message
|
||||
|
||||
let plaintext = cipher.decrypt(nonce, pass.as_ref());
|
||||
match plaintext {
|
||||
Ok(res) => {
|
||||
return vecu8_to_string(res);
|
||||
}
|
||||
Err(_) => {
|
||||
eprintln!("[ERROR] Error decrypting data, check your master password");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_home_folder_str() -> String {
|
||||
match home::home_dir() {
|
||||
Some(path) => {
|
||||
let p = path.to_str();
|
||||
match p {
|
||||
Some(pa) => return pa.to_owned(),
|
||||
None => return "".to_owned(),
|
||||
}
|
||||
},
|
||||
None => return "".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ipass_folder() -> String {
|
||||
let path = get_home_folder_str()+"/.IPass/";
|
||||
std::fs::create_dir_all(&path).unwrap();
|
||||
return path;
|
||||
}
|
||||
|
||||
pub fn create_entry(name: &String, pw: String) -> bool {
|
||||
if std::path::Path::new(&(get_ipass_folder()+name+".ipass")).exists() {
|
||||
return false;
|
||||
}
|
||||
let mpw = ask_for_pw();
|
||||
// println!("{pw}");
|
||||
let 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();
|
||||
return true;
|
||||
}
|
||||
|
||||
fn read_entry(name:&String,mpw:String) -> String {
|
||||
let content = &mut std::fs::read_to_string(get_ipass_folder()+name+".ipass").expect("Should have been able to read the file");
|
||||
return decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw).to_owned();
|
||||
}
|
||||
|
||||
pub fn get_entry(name:&String) -> String {
|
||||
let mpw = ask_for_pw();
|
||||
return read_entry(name,mpw);
|
||||
}
|
||||
|
||||
pub fn edit_password(name:&String, password:String) {
|
||||
let mpw = ask_for_pw();
|
||||
let entry = read_entry(name, mpw.clone());
|
||||
// println!("entry: {entry}");
|
||||
let mut parts = entry.split(";");
|
||||
let username = parts.next().unwrap().to_string();
|
||||
let _old_password = parts.next().unwrap();
|
||||
let data = encrypt_pass(name.to_owned(), username+";"+password.as_str(),mpw);
|
||||
let mut file = std::fs::File::create(get_ipass_folder()+name+".ipass").unwrap();
|
||||
file.write_all(data.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
pub fn edit_username(name:&String, username: String) {
|
||||
let mpw = ask_for_pw();
|
||||
let entry = read_entry(name, mpw.clone());
|
||||
// println!("entry: {entry}");
|
||||
let mut parts = entry.split(";");
|
||||
let _old_username = parts.next().unwrap();
|
||||
let password = parts.next().unwrap();
|
||||
let data = encrypt_pass(name.to_owned(), username+";"+password,mpw);
|
||||
let mut file = std::fs::File::create(get_ipass_folder()+name+".ipass").unwrap();
|
||||
file.write_all(data.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
fn ask_for_pw() -> String {
|
||||
let output = rpassword::prompt_password("Please enter the master password: ").unwrap();
|
||||
return output.replace("\n", "").replace("\r","");
|
||||
}
|
||||
|
||||
pub fn prompt_answer(toprint: String) -> String {
|
||||
print!("{toprint}");
|
||||
std::io::stdout().flush().unwrap();
|
||||
let mut choice = String::new();
|
||||
std::io::stdin().read_line(&mut choice).expect("Failed to read choice");
|
||||
|
||||
return choice.trim().to_lowercase();
|
||||
}
|
||||
|
||||
pub fn rename(name: &String, new_name: &String) {
|
||||
if !std::path::Path::new(&(get_ipass_folder()+name+".ipass")).exists() {
|
||||
return;
|
||||
}
|
||||
if std::path::Path::new(&(get_ipass_folder()+new_name+".ipass")).exists() {
|
||||
return;
|
||||
}
|
||||
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();
|
||||
let mut pw = decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw.clone()).to_owned();
|
||||
|
||||
pw = encrypt_pass(new_name.to_owned(), pw,mpw);
|
||||
let mut file = std::fs::File::create(get_ipass_folder()+new_name+".ipass").unwrap();
|
||||
file.write_all(pw.as_bytes()).unwrap();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user