Add `b2sum` applet - switch to `blake2b_simd` crate to get around

limitations of `blake2` crate, which will not accept a non-const
numerical specifier for length
This commit is contained in:
Nathan Fisher 2023-02-04 11:06:24 -05:00
parent 6b30c356dd
commit f0099a2958
4 changed files with 134 additions and 14 deletions

37
Cargo.lock generated
View File

@ -2,6 +2,18 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "arrayvec"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "atty"
version = "0.2.14"
@ -20,12 +32,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "blake2"
version = "0.10.6"
name = "blake2b_simd"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127"
dependencies = [
"digest",
"arrayref",
"arrayvec",
"constant_time_eq",
]
[[package]]
@ -100,6 +114,12 @@ dependencies = [
"roff",
]
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "cpufeatures"
version = "0.2.5"
@ -133,7 +153,6 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@ -293,7 +312,7 @@ name = "shitbox"
version = "0.1.0"
dependencies = [
"atty",
"blake2",
"blake2b_simd",
"clap",
"clap_complete",
"clap_complete_nushell",
@ -322,12 +341,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "termcolor"
version = "1.2.0"

View File

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
atty = "0.2"
blake2 = "0.10"
blake2b_simd = "1.0"
clap = "4.1"
clap_complete = "4.1"
clap_complete_nushell = "0.1"

104
src/cmd/b2sum/mod.rs Normal file
View File

@ -0,0 +1,104 @@
use super::Cmd;
use crate::args;
use blake2b_simd::Params;
use clap::{value_parser, Arg, Command};
use std::{
fs::File,
io::{self, BufRead, BufReader, Read},
process,
};
#[derive(Debug, Default)]
pub struct B2sum;
impl Cmd for B2sum {
fn cli(&self) -> clap::Command {
Command::new("b2sum")
.about("compute and check MD5 message digest")
.author("Nathan Fisher")
.version(env!("CARGO_PKG_VERSION"))
.args([
args::check(),
args::file(),
Arg::new("length")
.help(
"digest length in bits; must not exceed the max for the \
blake2 algorithm and must be a multiple of 8"
)
.short('l')
.long("length")
.default_value("512")
.value_parser(value_parser!(usize)),
])
}
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
if let Some(files) = matches.get_many::<String>("file") {
let mut erred = 0;
let len = matches.get_one("length").unwrap_or(&512);
if *len % 8 != 0 {
let msg = format!("bad hash length: {len}");
return Err(io::Error::new(io::ErrorKind::Other, msg).into());
}
let len = len / 8;
for f in files {
if matches.get_flag("check") {
if f == "-" {
return Err(
io::Error::new(io::ErrorKind::Other, "no file specified").into()
);
}
let fd = File::open(f)?;
let reader = BufReader::new(fd);
for line in reader.lines() {
let line = line?;
let mut split = line.split_whitespace();
let sum = split.next().ok_or::<io::Error>(
io::Error::new(io::ErrorKind::Other, "invalid checksum file").into(),
)?;
let file = split.next().ok_or::<io::Error>(
io::Error::new(io::ErrorKind::Other, "invalid checksum file").into(),
)?;
let mut buf = vec![];
let mut fd = File::open(file)?;
fd.read_to_end(&mut buf)?;
let hash = Params::new()
.hash_length(len)
.to_state()
.update(&buf)
.finalize();
if hash.to_hex().as_str() == sum {
println!("{file}: OK");
} else {
println!("{file}: FAILED");
erred += 1;
}
}
} else {
let mut buf = vec![];
if f == "-" {
let _s = io::stdin().read_to_end(&mut buf)?;
} else {
let mut fd = File::open(f)?;
let _s = fd.read_to_end(&mut buf)?;
}
let hash = Params::new()
.hash_length(len)
.to_state()
.update(&buf)
.finalize();
println!("{} {f}", &hash.to_hex());
}
}
if erred > 0 {
println!("b2sum: WARNING: {erred} computed checksum did NOT match");
process::exit(1);
}
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::UsrBin)
}
}

View File

@ -1,6 +1,7 @@
use clap::ArgMatches;
use std::{error::Error, fmt};
mod b2sum;
pub mod base32;
mod base64;
mod basename;
@ -78,6 +79,7 @@ pub trait Cmd: fmt::Debug + Sync {
#[allow(clippy::box_default)]
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
match name {
"b2sum" => Some(Box::new(b2sum::B2sum::default())),
"base64" => Some(Box::new(base64::Base64::default())),
"base32" => Some(Box::new(base32::Base32::default())),
"basename" => Some(Box::new(basename::Basename::default())),
@ -131,7 +133,8 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
}
}
pub static COMMANDS: [&str; 49] = [
pub static COMMANDS: [&str; 50] = [
"b2sum",
"base32",
"base64",
"basename",