164 lines
5.0 KiB
Rust
164 lines
5.0 KiB
Rust
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>) -> 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<Path>) -> 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<Path>) -> 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<Path>) -> 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<u8>, Vec<u8>) {
|
|
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<u8> {
|
|
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<Vec<u8>> {
|
|
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<Vec<u8>> {
|
|
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");
|
|
}
|
|
|