add sha*
This commit is contained in:
179
src/main.rs
179
src/main.rs
@@ -1,6 +1,5 @@
|
||||
use rust_util::{
|
||||
XResult,
|
||||
new_box_error,
|
||||
new_box_ioerror,
|
||||
util_msg::{
|
||||
print_message,
|
||||
@@ -9,83 +8,175 @@ use rust_util::{
|
||||
util_io::*,
|
||||
};
|
||||
use std::{
|
||||
env,
|
||||
fs::{self, File},
|
||||
fs::File,
|
||||
io::{Read, ErrorKind},
|
||||
path::Path,
|
||||
process::Command,
|
||||
time::SystemTime,
|
||||
};
|
||||
use crypto::{
|
||||
digest::Digest,
|
||||
md5::Md5,
|
||||
sha1::Sha1,
|
||||
sha2::{Sha256, Sha512},
|
||||
sha2::{
|
||||
Sha224,
|
||||
Sha256,
|
||||
Sha384,
|
||||
Sha512,
|
||||
Sha512Trunc224,
|
||||
Sha512Trunc256,
|
||||
},
|
||||
sha3::Sha3,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
use indicatif::{
|
||||
ProgressBar,
|
||||
ProgressStyle
|
||||
};
|
||||
use argparse::{ArgumentParser, StoreTrue, Store};
|
||||
use libsm::sm3::hash::Sm3Hash;
|
||||
|
||||
const FILE_SIZE_1GB: u64 = 1024 * 1024 * 1024;
|
||||
const BUFF_SIZE: usize = 512 * 1024;
|
||||
const PB_PROGRESS: &str = "#-";
|
||||
const PB_TEMPLATE: &str = "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})";
|
||||
|
||||
fn main() {
|
||||
let h = calc_file_digest(&mut Sha256::new(), "SHA256", "LICENSE");
|
||||
match h {
|
||||
Err(_) => {},
|
||||
Ok(d) => println!("SHA256: {}", d),
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const GIT_HASH: &str = env!("GIT_HASH");
|
||||
|
||||
|
||||
pub struct Options {
|
||||
pub version: bool,
|
||||
pub algorithm: String,
|
||||
pub file_name: String,
|
||||
}
|
||||
|
||||
impl Options {
|
||||
pub fn new() -> Options {
|
||||
Options {
|
||||
version: false,
|
||||
algorithm: "SHA256".to_string(),
|
||||
file_name: String::new(),
|
||||
}
|
||||
}
|
||||
let sm3 = read_file_full("LICENSE");
|
||||
match sm3 {
|
||||
Err(_) => {},
|
||||
Ok(s) => {
|
||||
let mut sm3h = Sm3Hash::new(&s);
|
||||
let hh = sm3h.get_hash();
|
||||
println!("SM3: {}", hex::encode(hh));
|
||||
},
|
||||
|
||||
pub fn parse_args(&mut self) -> XResult<()> {
|
||||
{
|
||||
let mut ap = ArgumentParser::new();
|
||||
ap.set_description("digest - command line digest tool.");
|
||||
ap.refer(&mut self.algorithm).add_option(&["-a", "--algorithm"], Store, "Algorithm, e.g. SHA256, SM3");
|
||||
ap.refer(&mut self.version).add_option(&["-v", "--version"], StoreTrue, "Print version");
|
||||
ap.refer(&mut self.file_name).add_argument("FILE NAME", Store, "Search text");
|
||||
ap.parse_args_or_exit();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new_and_parse_args() -> XResult<Options> {
|
||||
let mut options = Options::new();
|
||||
options.parse_args()?;
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_file_full(file_name: &str) -> XResult<Vec<u8>> {
|
||||
fn main() -> XResult<()> {
|
||||
let options = Options::new_and_parse_args()?;
|
||||
|
||||
if options.version {
|
||||
print_version();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if options.file_name == "" {
|
||||
println!("NO FILE NAME!");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let the_fn = options.file_name.as_str();
|
||||
let the_algo = options.algorithm.to_uppercase();
|
||||
|
||||
match the_algo.as_str() {
|
||||
"MD5" => println!("{}: {}", the_algo, calc_file_digest(&mut Md5::new(), the_fn)?),
|
||||
"SHA1" | "SHA-1" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha1::new(), the_fn)?),
|
||||
"SHA224" | "SHA-224" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha224::new(), the_fn)?),
|
||||
"SHA256" | "SHA-256" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha256::new(), the_fn)?),
|
||||
"SHA384" | "SHA-384" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha384::new(), the_fn)?),
|
||||
"SHA512" | "SHA-512" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha512::new(), the_fn)?),
|
||||
"SHA512-224" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha512Trunc224::new(), the_fn)?),
|
||||
"SHA512-256" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha512Trunc256::new(), the_fn)?),
|
||||
"SHA3-224" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::sha3_224(), the_fn)?),
|
||||
"SHA3-256" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::sha3_256(), the_fn)?),
|
||||
"SHA3-384" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::sha3_384(), the_fn)?),
|
||||
"SHA3-512" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::sha3_512(), the_fn)?),
|
||||
"SHAKE-128" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::shake_128(), the_fn)?),
|
||||
"SHAKE-256" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::shake_256(), the_fn)?),
|
||||
"KECCAK-224" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::keccak224(), the_fn)?),
|
||||
"KECCAK-256" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::keccak256(), the_fn)?),
|
||||
"KECCAK-384" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::keccak384(), the_fn)?),
|
||||
"KECCAK-512" => println!("{}: {}", the_algo, calc_file_digest(&mut Sha3::keccak512(), the_fn)?),
|
||||
"SM3" => println!("{}: {}", the_algo, hex::encode(Sm3Hash::new(&read_file_full(the_fn)?).get_hash())),
|
||||
_ => print_message(MessageType::ERROR, &format!("Unknown algorithm: {}", options.algorithm)),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_version() {
|
||||
print!(r#"digest {} - {}
|
||||
Copyright (C) 2019 Hatter Jiang.
|
||||
License MIT <https://opensource.org/licenses/MIT>
|
||||
|
||||
Written by Hatter Jiang
|
||||
|
||||
Supported algorithms:
|
||||
MD5, SHA1, SHA224, SHA256, SHA512, SHA512-224, SHA512-256,
|
||||
SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE-128, SHAKE-256,
|
||||
KECCAK-224, KECCAK-256, KECCAK-384, KECCAK-512, SM3
|
||||
"#, VERSION, &GIT_HASH[0..7]);
|
||||
}
|
||||
|
||||
fn read_file_full(file_name: &str) -> XResult<Vec<u8>> {
|
||||
let mut buf: [u8; DEFAULT_BUF_SIZE] = [0u8; DEFAULT_BUF_SIZE];
|
||||
let mut f = File::open(file_name)?;
|
||||
let file_len = match f.metadata() {
|
||||
Err(_) => -1i64,
|
||||
Ok(meta_data) => meta_data.len() as i64,
|
||||
};
|
||||
let file_len = f.metadata()?.len();
|
||||
let mut ret: Vec<u8> = Vec::new();
|
||||
let start = SystemTime::now();
|
||||
let mut written = 0i64;
|
||||
let mut read = 0_u64;
|
||||
|
||||
if file_len > FILE_SIZE_1GB {
|
||||
return Err(new_box_ioerror("File too large!"));
|
||||
}
|
||||
|
||||
let pb = ProgressBar::new(file_len);
|
||||
pb.set_style(ProgressStyle::default_bar().template(PB_TEMPLATE).progress_chars(PB_PROGRESS));
|
||||
|
||||
loop {
|
||||
let len = match f.read(&mut buf) {
|
||||
Ok(0) => { println!(); return Ok(ret); },
|
||||
Ok(0) => { pb.finish_and_clear(); return Ok(ret); },
|
||||
Ok(len) => len,
|
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
|
||||
Err(e) => return Err(Box::new(e)),
|
||||
};
|
||||
ret.append(&mut buf[..len].to_vec());
|
||||
written += len as i64;
|
||||
let cost = SystemTime::now().duration_since(start.clone()).unwrap();
|
||||
print_status_last_line(&format!("Calc {}", "digest_alg"), file_len, written, cost);
|
||||
read += len as u64;
|
||||
pb.set_position(read);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calc_file_digest(digest: &mut dyn Digest, digest_alg: &str, file_name: &str) -> XResult<String> {
|
||||
let mut buf: [u8; DEFAULT_BUF_SIZE] = [0u8; DEFAULT_BUF_SIZE];
|
||||
fn calc_file_digest(digest: &mut dyn Digest, file_name: &str) -> XResult<String> {
|
||||
let mut buf: [u8; BUFF_SIZE] = [0u8; BUFF_SIZE];
|
||||
let mut f = File::open(file_name)?;
|
||||
let file_len = match f.metadata() {
|
||||
Err(_) => -1i64,
|
||||
Ok(meta_data) => meta_data.len() as i64,
|
||||
};
|
||||
let start = SystemTime::now();
|
||||
let mut written = 0i64;
|
||||
let file_len = f.metadata()?.len();
|
||||
let mut processed = 0_u64;
|
||||
|
||||
let pb = ProgressBar::new(file_len);
|
||||
pb.set_style(ProgressStyle::default_bar().template(PB_TEMPLATE).progress_chars(PB_PROGRESS));
|
||||
|
||||
loop {
|
||||
let len = match f.read(&mut buf) {
|
||||
Ok(0) => { println!(); return Ok(digest.result_str()); },
|
||||
Ok(0) => { pb.finish_and_clear(); return Ok(digest.result_str()); },
|
||||
Ok(len) => len,
|
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
|
||||
Err(e) => return Err(Box::new(e)),
|
||||
};
|
||||
digest.input(&buf[..len]);
|
||||
written += len as i64;
|
||||
let cost = SystemTime::now().duration_since(start.clone()).unwrap();
|
||||
print_status_last_line(&format!("Calc {}", digest_alg), file_len, written, cost);
|
||||
processed += len as u64;
|
||||
pb.set_position(processed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user