Compare commits

..

No commits in common. "015b4229440aaa384b431d5af860e5ebfa1f185a" and "979c717cc0ecc3f9a0c26ce868dafc2b20c3328c" have entirely different histories.

4 changed files with 487 additions and 553 deletions

1
.gitignore vendored
View File

@ -1,2 +1 @@
/target /target
mutants.out*

652
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,13 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
home = "0.5" home = "0.5.5"
rand = { features = ["std"], default-features = false, version = "0.8" } rand = { features = ["std"], default-features = false, version = "0.8.5" }
aes-gcm = { features = ["alloc", "aes"], default-features = false, version = "0.10" } aes-gcm = { features = ["alloc", "aes"], default-features = false, version = "0.10.1" }
sha2 = { default-features = false, version = "0.10.6" } sha2 = { default-features = false, version = "0.10.6" }
hex = "0.4" hex = "0.4.3"
brotli = { features = ["std"], default-features = false, version = "3.3" } brotli = { features = ["std"], default-features = false, version = "3.3.4" }
reqwest = { features = ["json"], version = "0.11"} reqwest = { features = ["json"], version = "0.11.17"}
serde = { features = ["serde_derive"], version = "1.0"} serde = { features = ["serde_derive"], version = "1.0"}
serde_json="1.0" serde_json="1.0"

View File

@ -1,12 +1,19 @@
use std::io::{Read, Write};
use aes_gcm::{ use aes_gcm::{
aead::{Aead, KeyInit}, aead::{Aead, KeyInit},
Aes256Gcm, Nonce, Aes256Gcm, Nonce
};
use sha2::{Sha256, Digest};
use std::fs::{
File,
read_dir,
read_to_string
};
use rand::{
rngs::OsRng,
RngCore
}; };
use rand::{rngs::OsRng, RngCore};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::fs::{read_dir, read_to_string, File};
use std::io::{Read, Write};
pub fn get_args() -> Vec<String> { pub fn get_args() -> Vec<String> {
//! [0] = file path; [n>0] = argument //! [0] = file path; [n>0] = argument
@ -18,19 +25,16 @@ struct Saved {
success: bool, success: bool,
status: u16, status: u16,
data: Vec<u8>, data: Vec<u8>,
errorcode: u64, errorcode: u64
} }
fn get_token() -> Option<String> { fn get_token() -> Option<String> {
let mut token: String = String::new(); let mut token: String = String::default();
//check if file exists //check if file exists
if !std::path::Path::new(&(get_ipass_folder()+"token.ipasst")).exists() { if !std::path::Path::new(&(get_ipass_folder()+"token.ipasst")).exists() {
return None; return None;
} }
File::open(get_ipass_folder() + "token.ipasst") File::open(get_ipass_folder()+"token.ipasst").unwrap().read_to_string(&mut token).unwrap();
.unwrap()
.read_to_string(&mut token)
.unwrap();
Some(token) Some(token)
} }
@ -39,7 +43,7 @@ struct HashRes {
success: bool, success: bool,
hash: String, hash: String,
status: u16, status: u16,
errorcode: u64, errorcode: u64
} }
fn sha256hexhash(data: Vec<u8>) -> String { fn sha256hexhash(data: Vec<u8>) -> String {
@ -61,8 +65,7 @@ pub async fn isync_compare_hashes() -> bool {
match token { match token {
Some(token) => { Some(token) => {
let client = reqwest::Client::builder().https_only(true).build().unwrap(); let client = reqwest::Client::builder().https_only(true).build().unwrap();
let req = client let req = client.get("https://ipass.ipost.rocks/hash")
.get("https://ipass.ipost.rocks/hash")
.header("ipass-auth-token", token) .header("ipass-auth-token", token)
.timeout(std::time::Duration::from_secs(3)) .timeout(std::time::Duration::from_secs(3))
.build(); .build();
@ -90,7 +93,7 @@ pub async fn isync_compare_hashes() -> bool {
eprintln!("Error: {}", req.err().unwrap()); eprintln!("Error: {}", req.err().unwrap());
true true
} }
} },
None => { None => {
eprintln!("No token found!"); eprintln!("No token found!");
true true
@ -104,8 +107,7 @@ pub async fn isync_get() -> bool {
match token { match token {
Some(token) => { Some(token) => {
let client = reqwest::Client::builder().https_only(true).build().unwrap(); let client = reqwest::Client::builder().https_only(true).build().unwrap();
let req = client let req = client.get("https://ipass.ipost.rocks/saved")
.get("https://ipass.ipost.rocks/saved")
.header("ipass-auth-token", token) .header("ipass-auth-token", token)
.timeout(std::time::Duration::from_secs(3)) .timeout(std::time::Duration::from_secs(3))
.build(); .build();
@ -116,10 +118,7 @@ pub async fn isync_get() -> bool {
if let Ok(body) = body { if let Ok(body) = body {
if body.success { if body.success {
println!("new hash: {}",sha256hexhash(body.data.clone())); println!("new hash: {}",sha256hexhash(body.data.clone()));
File::create(get_ipass_folder() + "temp.ipassx") File::create(get_ipass_folder()+"temp.ipassx").unwrap().write_all(&body.data).unwrap();
.unwrap()
.write_all(&body.data)
.unwrap();
import_file(&(get_ipass_folder()+"temp.ipassx")); import_file(&(get_ipass_folder()+"temp.ipassx"));
std::fs::remove_file(get_ipass_folder()+"temp.ipassx").unwrap(); std::fs::remove_file(get_ipass_folder()+"temp.ipassx").unwrap();
return true; return true;
@ -142,7 +141,7 @@ pub async fn isync_get() -> bool {
eprintln!("Error: {}", req.err().unwrap()); eprintln!("Error: {}", req.err().unwrap());
return false; return false;
} }
} },
None => { None => {
eprintln!("No token found!"); eprintln!("No token found!");
return false; return false;
@ -156,14 +155,14 @@ pub async fn isync_get() -> bool {
struct Save { struct Save {
success: bool, success: bool,
status: u16, status: u16,
errorcode: u64, errorcode: u64
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
struct SavedData { struct SavedData {
data: Vec<u8>, data: Vec<u8>,
amount: i32, amount: i32,
token: String, token: String
} }
pub async fn isync_save() -> bool { pub async fn isync_save() -> bool {
@ -176,14 +175,13 @@ pub async fn isync_save() -> bool {
let saveddata = SavedData { let saveddata = SavedData {
data, data,
amount: read_dir(get_ipass_folder()).unwrap().count() as i32, amount: read_dir(get_ipass_folder()).unwrap().count() as i32,
token, token
}; };
let requestbody = serde_json::to_string(&saveddata).unwrap(); let requestbody = serde_json::to_string(&saveddata).unwrap();
let client = reqwest::Client::builder().https_only(true).build().unwrap(); let client = reqwest::Client::builder().https_only(true).build().unwrap();
let req = client let req = client.post("https://ipass.ipost.rocks/save")
.post("https://ipass.ipost.rocks/save")
.body(requestbody) .body(requestbody)
.header("content-type", "application/json") .header("content-type", "application/json")
.timeout(std::time::Duration::from_secs(5)) .timeout(std::time::Duration::from_secs(5))
@ -200,21 +198,25 @@ pub async fn isync_save() -> bool {
eprintln!("Error: {}", response.errorcode); eprintln!("Error: {}", response.errorcode);
false false
} }
} },
None => false, None => {
false
} }
} }
None => false, },
None => {
false
}
} }
} }
pub fn import_data<R: Read>(mut reader: brotli::Decompressor<R>) { pub fn import_data<R: Read>(mut reader: brotli::Decompressor<R>) {
let mut content: String = String::new(); let mut content: String = String::default();
let mut buf = [0u8; 4096]; let mut buf = [0u8; 4096];
loop { loop {
match reader.read(&mut buf[..]) { match reader.read(&mut buf[..]) {
Err(e) => { Err(e) => {
if let std::io::ErrorKind::Interrupted = e.kind() { if e.kind() == std::io::ErrorKind::Interrupted {
continue; continue;
} }
panic!("{}", e); panic!("{}", e);
@ -230,9 +232,7 @@ pub fn import_data<R: Read>(mut reader: brotli::Decompressor<R>) {
let entries = get_entries().flatten(); let entries = get_entries().flatten();
for entry in entries { for entry in entries {
if entry.file_name().to_str().unwrap().ends_with(".ipasst") if entry.file_name().to_str().unwrap().ends_with(".ipasst") || entry.file_name().to_str().unwrap().ends_with(".ipassx") {
|| entry.file_name().to_str().unwrap().ends_with(".ipassx")
{
continue; continue;
} }
std::fs::remove_file(entry.path()).unwrap(); std::fs::remove_file(entry.path()).unwrap();
@ -255,32 +255,28 @@ pub fn import_data<R: Read>(mut reader: brotli::Decompressor<R>) {
} }
pub fn import_file(file_path:&String) -> bool { pub fn import_file(file_path:&String) -> bool {
if std::path::Path::new(file_path).exists() { let file_exists = std::path::Path::new(file_path).exists();
if file_exists {
let reader = brotli::Decompressor::new( let reader = brotli::Decompressor::new(
File::open(file_path).unwrap(), File::open(file_path).unwrap(),
4096, // buffer size 4096, // buffer size
); );
import_data(reader); import_data(reader);
true
} else {
false
} }
file_exists
} }
pub fn export_data() -> Option<Vec<u8>> { pub fn export_data() -> Option<Vec<u8>> {
let mut collected_data = String::new(); let mut collected_data = String::default();
let paths = std::fs::read_dir(get_ipass_folder()).ok()?; let paths = std::fs::read_dir(get_ipass_folder()).ok()?;
for path in paths.flatten() { for path in paths.flatten() {
if path.file_name().into_string().ok()?.ends_with(".ipasst") if path.file_name().into_string().ok()?.ends_with(".ipasst") || path.file_name().into_string().ok()?.ends_with(".ipassx") {
|| path.file_name().into_string().ok()?.ends_with(".ipassx")
{
continue; continue;
} }
let file_name = path.file_name().into_string().ok()?.replace(".ipass", ""); let file_name = path.file_name().into_string().ok()?.replace(".ipass", "");
let content = let content = std::fs::read_to_string(get_ipass_folder() + &path.file_name().to_string_lossy()).ok()?;
std::fs::read_to_string(get_ipass_folder() + &path.file_name().to_string_lossy())
.ok()?;
collected_data += format!("{}\n{}\n", file_name, content).as_str(); collected_data += format!("{}\n{}\n", file_name, content).as_str();
} }
@ -294,6 +290,8 @@ pub fn export_data() -> Option<Vec<u8>> {
Some(compressed_data) Some(compressed_data)
} }
pub fn export_file(file_path: &String) -> bool { pub fn export_file(file_path: &String) -> bool {
match export_data() { match export_data() {
Some(compressed_data) => { Some(compressed_data) => {
@ -317,7 +315,7 @@ pub fn export_file(file_path: &String) -> bool {
fn vecu8_to_string(vec: Vec<u8>) -> String { fn vecu8_to_string(vec: Vec<u8>) -> String {
let mut do_print_warning = false; let mut do_print_warning = false;
let mut out: String = String::new(); let mut out: String = String::default();
for ind in vec { for ind in vec {
if let Ok(a) = std::str::from_utf8(&[ind]) { if let Ok(a) = std::str::from_utf8(&[ind]) {
out += a; out += a;
@ -335,25 +333,21 @@ fn vecu8_to_string(vec: Vec<u8>) -> String {
out out
} }
fn generate_nonce(nonce_arg: &str) -> String { fn encrypt_pass(nonce_arg:String, pass: String,mpw: String) -> String {
const NONCE_LEN: usize = 12; let mut nonce_argument = String::default();
match nonce_arg.len().cmp(&NONCE_LEN) { if nonce_arg.len() < 12 {
std::cmp::Ordering::Less => { nonce_argument = nonce_arg.clone() + &" ".repeat(12-nonce_arg.len());
nonce_arg.to_string() + &" ".repeat(NONCE_LEN - nonce_arg.len())
} }
std::cmp::Ordering::Greater => nonce_arg[0..NONCE_LEN].to_string(), if nonce_arg.len() > 12 {
std::cmp::Ordering::Equal => nonce_arg.to_string(), nonce_argument = nonce_arg[0..12].to_string();
} }
}
fn encrypt_pass(nonce_arg: &str, pass: &str, mpw: &str) -> String {
let nonce_argument = generate_nonce(nonce_arg);
let mut nonce_hasher = Sha256::new(); let mut nonce_hasher = Sha256::new();
nonce_hasher.update(nonce_argument.as_bytes()); nonce_hasher.update(nonce_argument.as_bytes());
let nonce_final = &nonce_hasher.finalize()[0..12]; let nonce_final = &nonce_hasher.finalize()[0..12];
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hasher.update(mpw.as_bytes()); hasher.update(mpw.as_bytes());
@ -365,8 +359,16 @@ fn encrypt_pass(nonce_arg: &str, pass: &str, mpw: &str) -> String {
hex::encode(ciphertext) hex::encode(ciphertext)
} }
fn decrypt_pass(nonce_arg: &str, pass: Vec<u8>, mpw: &str) -> Result<String, String> {
let nonce_argument = generate_nonce(nonce_arg);
fn decrypt_pass(nonce_arg:String, pass: Vec<u8>,mpw: String) -> Result<String,String> {
let mut nonce_argument = String::default();
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(); let mut nonce_hasher = Sha256::new();
nonce_hasher.update(nonce_argument.as_bytes()); nonce_hasher.update(nonce_argument.as_bytes());
@ -382,22 +384,25 @@ fn decrypt_pass(nonce_arg: &str, pass: Vec<u8>, mpw: &str) -> Result<String, Str
let plaintext = cipher.decrypt(nonce, pass.as_ref()); let plaintext = cipher.decrypt(nonce, pass.as_ref());
match plaintext { match plaintext {
Ok(res) => Ok(vecu8_to_string(res)), Ok(res) => {
Err(_) => Err("[ERROR] Error decrypting data, check your master password".to_string()), Ok(vecu8_to_string(res))
}
Err(_) => {
Err("[ERROR] Error decrypting data, check your master password".to_string())
}
} }
} }
pub fn get_home_folder_str() -> String { pub fn get_home_folder_str() -> String {
const HOME_MESSAGE: &str = "Could not get home folder, set the IPASS_HOME environment variable for the parent-folder of where you want to store your passwords";
match home::home_dir() { match home::home_dir() {
Some(path) => { Some(path) => {
let p = path.to_str(); let p = path.to_str();
match p { match p {
Some(pa) => pa.to_owned(), Some(pa) => pa.to_owned(),
None => panic!("{HOME_MESSAGE}"), None => "".to_owned(),
} }
} },
None => panic!("{HOME_MESSAGE}"), None => "".to_owned(),
} }
} }
@ -407,24 +412,25 @@ pub fn get_ipass_folder() -> String {
path path
} }
pub fn create_entry(name: &str, pw: &str, mpw: &str) -> bool { pub fn create_entry(name: &str, pw: String, mpw: String) -> bool {
let mut entry_name = String::new(); let mut entry_name = String::default();
for c in name.chars() { for c in name.chars() {
match c { match c {
':' | '$' | '<' | '>' | '|' | '?' | '*' | '/' | '\\' => {} ':' | '$' | '<' | '>' | '|' | '?' | '*' | '/' | '\\' => {},
_ => entry_name.push(c), _ => entry_name.push(c),
} }
} }
if std::path::Path::new(&(get_ipass_folder()+entry_name.as_str()+".ipass")).exists() { if std::path::Path::new(&(get_ipass_folder()+entry_name.as_str()+".ipass")).exists() {
return false; return false;
} }
let pw = encrypt_pass(&entry_name, pw, mpw); // println!("{pw}");
let pw = encrypt_pass(entry_name.to_owned(), pw,mpw);
let mut file = File::create(get_ipass_folder()+entry_name.as_str()+".ipass").unwrap(); let mut file = File::create(get_ipass_folder()+entry_name.as_str()+".ipass").unwrap();
file.write_all(pw.as_bytes()).unwrap(); file.write_all(pw.as_bytes()).unwrap();
true true
} }
fn read_entry(name: &str, mpw: &str) -> Result<String, String> { fn read_entry(name:&String,mpw:String) -> Result<String,String> {
let path = get_ipass_folder()+name+".ipass"; let path = get_ipass_folder()+name+".ipass";
//check if entry exists //check if entry exists
@ -433,47 +439,22 @@ fn read_entry(name: &str, mpw: &str) -> Result<String, String> {
} }
let err_msg = format!("Should have been able to read the file {}",path); let err_msg = format!("Should have been able to read the file {}",path);
let content = &mut read_to_string(path).unwrap_or_else(|_| panic!("{}", err_msg)); let content = &mut read_to_string(path).unwrap_or_else(|_| { panic!("{}", err_msg) });
decrypt_pass(name, hex::decode(content).unwrap(), mpw) decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw)
} }
pub fn get_entry(name: &str, mpw: &str) -> Result<String, String> { pub fn get_entry(name:&String, mpw: String) -> Result<String,String> {
read_entry(name,mpw) read_entry(name,mpw)
} }
pub fn edit_password(name: &str, password: &str, mpw: &str) -> bool { pub fn edit_password(name:&String, password:String, mpw: String) -> bool {
let entry_result = read_entry(name, mpw); let entry_result = read_entry(name, mpw.clone());
if let Ok(entry) = entry_result {
let mut parts = entry.split(';');
let username = parts.next().unwrap().to_string();
parts
.next()
.expect("Expected to be able to get old password");
let username_pw_combo = username + ";" + password;
let data = encrypt_pass(name, &username_pw_combo, mpw);
let mut file = File::create(get_ipass_folder() + name + ".ipass").unwrap();
file.write_all(data.as_bytes()).unwrap();
return true;
}
false
}
pub fn edit_username(name: &str, username: &str, mpw: &str) -> bool {
let entry_result = read_entry(name, mpw);
if let Ok(entry) = entry_result { if let Ok(entry) = entry_result {
// println!("entry: {entry}"); // println!("entry: {entry}");
let mut parts = entry.split(';'); let mut parts = entry.split(';');
let username = parts.next().unwrap().to_string();
parts let _old_password = parts.next().unwrap();
.next() let data = encrypt_pass(name.to_owned(), username+";"+password.as_str(),mpw);
.expect("Expected to be able to get old username");
let password = parts.next().unwrap();
let username_pw_combo = username.to_string() + ";" + password;
let data = encrypt_pass(name, &username_pw_combo, mpw);
let mut file = File::create(get_ipass_folder()+name+".ipass").unwrap(); let mut file = File::create(get_ipass_folder()+name+".ipass").unwrap();
file.write_all(data.as_bytes()).unwrap(); file.write_all(data.as_bytes()).unwrap();
return true; return true;
@ -481,32 +462,44 @@ pub fn edit_username(name: &str, username: &str, mpw: &str) -> bool {
false false
} }
pub fn prompt_answer(toprint: &str) -> String { pub fn edit_username(name:&String, username: String, mpw: String) -> bool {
let entry_result = read_entry(name, mpw.clone());
if let Ok(entry) = entry_result {
// 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 = File::create(get_ipass_folder()+name+".ipass").unwrap();
file.write_all(data.as_bytes()).unwrap();
return true;
}
false
}
pub fn prompt_answer(toprint: String) -> String {
prompt_answer_nolower(toprint).to_lowercase() prompt_answer_nolower(toprint).to_lowercase()
} }
pub fn prompt_answer_nolower(toprint: &str) -> String { pub fn prompt_answer_nolower(toprint: String) -> String {
print!("{toprint}"); print!("{toprint}");
std::io::stdout().flush().unwrap(); std::io::stdout().flush().unwrap();
let mut choice = String::new(); let mut choice = String::default();
std::io::stdin() std::io::stdin().read_line(&mut choice).expect("Failed to read choice");
.read_line(&mut choice)
.expect("Failed to read choice");
choice.trim().to_string() return choice.trim().to_string();
} }
pub fn rename(name: &str, new_name: &str, mpw: &str) -> bool { pub fn rename(name: &String, new_name: &String, mpw: String) -> bool {
if !std::path::Path::new(&(get_ipass_folder()+name+".ipass")).exists() { if !std::path::Path::new(&(get_ipass_folder()+name+".ipass")).exists() {
return false; return false;
} }
if std::path::Path::new(&(get_ipass_folder()+new_name+".ipass")).exists() { if std::path::Path::new(&(get_ipass_folder()+new_name+".ipass")).exists() {
return false; return false;
} }
let content = &mut read_to_string(get_ipass_folder() + name + ".ipass") let content = &mut read_to_string(get_ipass_folder()+name+".ipass").expect("Should have been able to read the file");
.expect("Should have been able to read the file"); if let Ok(mut data) = decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw.clone()) {
if let Ok(mut data) = decrypt_pass(name, hex::decode(content).unwrap(), mpw) { data = encrypt_pass(new_name.to_owned(), data,mpw);
data = encrypt_pass(new_name, &data, mpw);
let mut file = File::create(get_ipass_folder()+new_name+".ipass").unwrap(); let mut file = File::create(get_ipass_folder()+new_name+".ipass").unwrap();
file.write_all(data.as_bytes()).unwrap(); file.write_all(data.as_bytes()).unwrap();
return true; return true;
@ -519,94 +512,56 @@ pub fn get_entries() -> std::fs::ReadDir {
} }
pub fn random_password() -> String { pub fn random_password() -> String {
const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!\"$%&/()=?{[]}\\,.-;:_><|+*#'"; let alphabet: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!\"$%&/()=?{[]}\\,.-;:_><|+*#'";
let alph_len: usize = ALPHABET.len(); let alph_len: usize = alphabet.chars().count();
let char_set: Vec<char> = ALPHABET.chars().collect(); let char_set:Vec<char> = alphabet.chars().collect();
let mut chars_index: Vec<u8> = vec![0;20]; let mut chars_index: Vec<u8> = vec![0;20];
OsRng.fill_bytes(&mut chars_index); OsRng.fill_bytes(&mut chars_index);
chars_index let mut chars: String = String::default();
.iter()
.map(|index| char_set[(*index as usize) % alph_len].to_string()) for index in chars_index {
.collect() // println!("{} - {} - {}",index,(index as usize)%(alph_len-1),alph_len);
chars += &char_set[(index as usize)%(alph_len-1)].to_string();
}
chars
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]
fn encrypt_decrypt() { fn encrypt_decrypt() {
const NAME: &str = "test"; let name = "test".to_string();
const PASSWORD: &str = "test"; let password = "test".to_string();
const MASTER_PASSWORD: &str = "test"; let mpw = "test".to_string();
let encrypted = hex::decode(super::encrypt_pass(NAME, PASSWORD, MASTER_PASSWORD)).unwrap(); let encrypted = hex::decode(super::encrypt_pass(name.clone(), password.clone(), mpw.clone())).unwrap();
let decrypted = super::decrypt_pass(NAME, encrypted, MASTER_PASSWORD).unwrap(); let decrypted = super::decrypt_pass(name, encrypted, mpw).unwrap();
assert_eq!(decrypted, PASSWORD); assert_eq!(decrypted, password);
} }
#[test] #[test]
fn encrypt_decrypt_error() { fn encrypt_decrypt_error() {
const NAME: &str = "test"; let name = "test".to_string();
const PASSWORD: &str = "test"; let password = "test".to_string();
const MASTER_PASSWORD: &str = "test"; let mpw = "test".to_string();
let encrypted = hex::decode(super::encrypt_pass(NAME, PASSWORD, MASTER_PASSWORD)).unwrap(); let encrypted = hex::decode(super::encrypt_pass(name.clone(), password.clone(), mpw.clone())).unwrap();
let decrypted = super::decrypt_pass(NAME, encrypted, "test2"); let decrypted = super::decrypt_pass(name, encrypted, "test2".to_string());
assert!(decrypted.is_err()); assert!(decrypted.is_err());
} }
#[test] #[test]
fn create_delete_entry() { fn create_delete_entry() {
const NAME: &str = "test"; let name = "test".to_string();
const PASSWORD: &str = "test"; let password = "test".to_string();
const MASTER_PASSWORD: &str = "test"; let mpw = "test".to_string();
let created = super::create_entry(NAME, PASSWORD, MASTER_PASSWORD); let created = super::create_entry(&name, password.clone(), mpw.clone());
assert!(created); assert!(created);
let entry = super::read_entry(NAME, MASTER_PASSWORD); let entry = super::read_entry(&name, mpw.clone());
assert!(entry.is_ok()); assert!(entry.is_ok());
assert_eq!(entry.unwrap(), PASSWORD); assert_eq!(entry.unwrap(), password);
let deleted = std::fs::remove_file(super::get_ipass_folder() + NAME + ".ipass"); let deleted = std::fs::remove_file(super::get_ipass_folder()+name.as_str()+".ipass");
assert!(deleted.is_ok()); assert!(deleted.is_ok());
let entry = super::read_entry(NAME, MASTER_PASSWORD); let entry = super::read_entry(&name, mpw.clone());
assert!(entry.is_err()); assert!(entry.is_err());
} }
#[test]
fn test_get_ipass_folder() {
let path = super::get_ipass_folder();
let path = std::path::Path::new(&path);
assert!(path.is_dir());
assert!(path.exists());
}
#[test]
fn test_get_home_folder() {
let path = super::get_home_folder_str();
let path = std::path::Path::new(&path);
assert!(path.is_dir());
assert!(path.exists());
}
#[test]
fn test_nonce() {
let nonce = super::generate_nonce("test");
assert_eq!(nonce, "test ");
let nonce = super::generate_nonce("0123456789abcdef");
assert_eq!(nonce, "0123456789ab");
}
#[test]
fn test_random_pw_length() {
for _ in 0..100_000 {
assert_eq!(super::random_password().len(), 20);
}
}
#[test]
fn test_sha256hexhash() {
let to_hash = "test".as_bytes().to_vec();
let hash = super::sha256hexhash(to_hash);
assert_eq!(
hash,
"9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08"
);
}
} }