use std::{fs, io}; use std::io::Write; use std::path::{Path, PathBuf}; use base64::Engine; use base64::engine::general_purpose; use rand::random; use rust_util::{information, simple_error, util_term, warning, XResult}; use zeroize::Zeroize; use crate::consts::TINY_ENC_FILE_EXT; pub fn read_pin(pin: &Option) -> String { match pin { Some(pin) => pin.to_string(), None => if util_term::read_yes_no("Use default PIN 123456, please confirm") { "123456".into() } else { rpassword::prompt_password("Please input PIN: ").expect("Read PIN failed") } } } pub fn remove_file_with_msg(path: &PathBuf) { match fs::remove_file(path) { Err(e) => warning!("Remove file: {} failed: {}", path.display(), e), Ok(_) => information!("Remove file: {} succeed", path.display()), } } pub fn get_file_name(path: &Path) -> String { let path_display = format!("{}", path.display()); if path_display.contains('/') { if let Some(p) = path_display.split('/').last() { return p.to_string(); } } path_display } pub fn require_tiny_enc_file_and_exists(path: impl AsRef) -> XResult<()> { let path = path.as_ref(); let path_display = format!("{}", path.display()); if !path_display.ends_with(TINY_ENC_FILE_EXT) { return simple_error!("File is not tiny encrypt file: {}", &path_display); } require_file_exists(path)?; Ok(()) } pub fn require_file_exists(path: impl AsRef) -> XResult<()> { let path = path.as_ref(); let metadata = match fs::metadata(path) { Ok(metadata) => metadata, Err(_) => return simple_error!("File: {} not exists", path.display()), }; if !metadata.is_file() { return simple_error!("Path: {} is not a file", path.display()); } Ok(()) } pub fn require_file_not_exists(path: impl AsRef) -> XResult<()> { let path = path.as_ref(); match fs::metadata(path) { Ok(_) => simple_error!("File: {} exists", path.display()), Err(_) => Ok(()), } } pub fn make_key256_and_nonce() -> (Vec, Vec) { let key: [u8; 32] = random(); let nonce: [u8; 12] = random(); let result = (key.into(), nonce.into()); let (mut key, mut nonce) = (key, nonce); key.zeroize(); nonce.zeroize(); result } pub fn simple_kdf(input: &[u8]) -> Vec { let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); let input = hex::decode(sha256::digest(input)).unwrap(); hex::decode(sha256::digest(input)).unwrap() } pub fn decode_base64(input: &str) -> XResult> { Ok(general_purpose::STANDARD.decode(input)?) } pub fn encode_base64(input: &[u8]) -> String { general_purpose::STANDARD.encode(input) } pub fn encode_base64_url_no_pad(input: &[u8]) -> String { general_purpose::URL_SAFE_NO_PAD.encode(input) } pub fn decode_base64_url_no_pad(input: &str) -> XResult> { Ok(general_purpose::URL_SAFE_NO_PAD.decode(input)?) } pub fn read_number(hint: &str, from: usize, to: usize) -> usize { loop { print!("{} ({}-{}): ", hint, from, to); io::stdout().flush().ok(); let mut buff = String::new(); let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin"); let buff = buff.trim(); match buff.parse() { Err(_) => warning!("Input number error!"), Ok(number) => if number < from || number > to { warning!("Input number is not in range."); } else { return number; }, } } } pub fn get_user_agent() -> String { format!("TinyEncrypt-rs v{}@{}", env!("CARGO_PKG_VERSION"), if cfg!(target_os = "macos") { "MacOS" } else if cfg!(target_os = "ios") { "iOS" } else if cfg!(target_os = "android") { "Android" } else if cfg!(target_os = "windows") { "Windows" } else if cfg!(target_os = "linux") { "Linux" } else if cfg!(target_os = "freebsd") { "FreeBSD" } else if cfg!(target_os = "dragonfly") { "Dragonfly" } else if cfg!(target_os = "openbsd") { "OpenBSD" } else if cfg!(target_os = "netbsd") { "NetBSD" } else { panic!("Unsupported OS!"); } ) } pub fn zeroize(object: impl Zeroize) { let mut object = object; object.zeroize(); } pub fn read_line(ln: &str) { print!("{}", ln); io::stdout().flush().ok(); let mut buff = String::new(); let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin"); }