1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Add checksum algorithm abstractions

This commit is contained in:
Yang Hau 2023-02-21 16:23:18 +08:00
parent 109553436d
commit 9322580967
6 changed files with 77 additions and 102 deletions

14
Cargo.lock generated
View file

@ -2399,14 +2399,8 @@ dependencies = [
name = "uu_cksum"
version = "0.0.17"
dependencies = [
"blake2b_simd",
"blake3",
"clap",
"hex",
"md-5",
"sha1",
"sha2",
"sm3",
"uucore",
]
@ -2611,18 +2605,10 @@ dependencies = [
name = "uu_hashsum"
version = "0.0.17"
dependencies = [
"blake2b_simd",
"blake3",
"clap",
"digest",
"hex",
"md-5",
"memchr",
"regex",
"sha1",
"sha2",
"sha3",
"sm3",
"uucore",
]

View file

@ -16,14 +16,8 @@ path = "src/cksum.rs"
[dependencies]
clap = { workspace=true }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["sum"] }
uucore = { workspace=true, features=["sum"] }
hex = { workspace=true }
md-5 = { workspace=true }
sha1 = { workspace=true }
sha2 = { workspace=true }
blake2b_simd = { workspace=true }
blake3 = { workspace=true }
sm3 = { workspace=true }
[[bin]]
name = "cksum"

View file

@ -8,9 +8,6 @@
// spell-checker:ignore (ToDO) fname, algo
use clap::{crate_version, Arg, Command};
use hex::encode;
use md5::Md5;
use sha1::Sha1;
use sha2::{Sha224, Sha256, Sha384, Sha512};
use std::ffi::OsStr;
use std::fs::File;
use std::io::{self, stdin, BufReader, Read};
@ -19,7 +16,10 @@ use std::path::Path;
use uucore::{
error::{FromIo, UResult},
format_usage,
sum::{div_ceil, Digest, DigestWriter, BSD, CRC, SYSV},
sum::{
div_ceil, Blake2b, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Sm3,
BSD, CRC, SYSV,
},
};
const USAGE: &str = "{} [OPTIONS] [FILE]...";
@ -36,12 +36,8 @@ fn detect_algo(program: &str) -> (&'static str, Box<dyn Digest + 'static>, usize
"sha256" => ("SHA256", Box::new(Sha256::new()) as Box<dyn Digest>, 256),
"sha384" => ("SHA384", Box::new(Sha384::new()) as Box<dyn Digest>, 384),
"sha512" => ("SHA512", Box::new(Sha512::new()) as Box<dyn Digest>, 512),
"blake2b" => (
"BLAKE2",
Box::new(blake2b_simd::State::new()) as Box<dyn Digest>,
512,
),
"sm3" => ("SM3", Box::new(sm3::Sm3::new()) as Box<dyn Digest>, 512),
"blake2b" => ("BLAKE2", Box::new(Blake2b::new()) as Box<dyn Digest>, 512),
"sm3" => ("SM3", Box::new(Sm3::new()) as Box<dyn Digest>, 512),
_ => panic!("unknown algorithm"),
}
}
@ -81,8 +77,7 @@ where
let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits)
.map_err_context(|| "failed to read input".to_string())?;
// Refer to GNU sum.c implementation. The BSD checksum output is 5 digit integer
// https://github.com/coreutils/coreutils/blob/master/src/sum.c
// The BSD checksum output is 5 digit integer
let bsd_width = 5;
match (options.algo_name, not_file) {
("SYSV", true) => println!(

View file

@ -20,14 +20,6 @@ uucore = { workspace=true }
memchr = { workspace=true }
regex = { workspace=true }
hex = { workspace=true }
md-5 = { workspace=true }
sha1 = { workspace=true }
sha2 = { workspace=true }
sha3 = { workspace=true }
blake2b_simd = { workspace=true }
blake3 = { workspace=true }
sm3 = { workspace=true }
digest = { workspace=true }
[[bin]]
name = "hashsum"

View file

@ -14,11 +14,7 @@ use clap::crate_version;
use clap::ArgAction;
use clap::{Arg, ArgMatches, Command};
use hex::encode;
use md5::Md5;
use regex::Regex;
use sha1::Sha1;
use sha2::{Sha224, Sha256, Sha384, Sha512};
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
use std::cmp::Ordering;
use std::error::Error;
use std::ffi::{OsStr, OsString};
@ -27,11 +23,12 @@ use std::io::{self, stdin, BufRead, BufReader, Read};
use std::iter;
use std::num::ParseIntError;
use std::path::Path;
use uucore::crash;
use uucore::display::Quotable;
use uucore::error::{FromIo, UError, UResult};
use uucore::show_warning;
use uucore::sum::{Digest, DigestWriter};
use uucore::sum::{
Blake2b, Blake3, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha3_224, Sha3_256,
Sha3_384, Sha3_512, Sha512, Shake128, Shake256,
};
use uucore::{crash, display::Quotable, show_warning};
const NAME: &str = "hashsum";
@ -64,16 +61,8 @@ fn detect_algo(
"sha256sum" => ("SHA256", Box::new(Sha256::new()) as Box<dyn Digest>, 256),
"sha384sum" => ("SHA384", Box::new(Sha384::new()) as Box<dyn Digest>, 384),
"sha512sum" => ("SHA512", Box::new(Sha512::new()) as Box<dyn Digest>, 512),
"b2sum" => (
"BLAKE2",
Box::new(blake2b_simd::State::new()) as Box<dyn Digest>,
512,
),
"b3sum" => (
"BLAKE3",
Box::new(blake3::Hasher::new()) as Box<dyn Digest>,
256,
),
"b2sum" => ("BLAKE2", Box::new(Blake2b::new()) as Box<dyn Digest>, 512),
"b3sum" => ("BLAKE3", Box::new(Blake3::new()) as Box<dyn Digest>, 256),
"sha3sum" => match matches.get_one::<usize>("bits") {
Some(224) => (
"SHA3-224",
@ -166,10 +155,10 @@ fn detect_algo(
set_or_crash("SHA512", Box::new(Sha512::new()), 512);
}
if matches.get_flag("b2sum") {
set_or_crash("BLAKE2", Box::new(blake2b_simd::State::new()), 512);
set_or_crash("BLAKE2", Box::new(Blake2b::new()), 512);
}
if matches.get_flag("b3sum") {
set_or_crash("BLAKE3", Box::new(blake3::Hasher::new()), 256);
set_or_crash("BLAKE3", Box::new(Blake3::new()), 256);
}
if matches.get_flag("sha3") {
match matches.get_one::<usize>("bits") {

View file

@ -1,4 +1,12 @@
// spell-checker:ignore memmem
// This file is part of the uutils coreutils package.
//
// (c) Yuan YangHao <yuanyanghau@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
// spell-checker:ignore memmem algo
//! Implementations of digest functions, like md5 and sha1.
//!
//! The [`Digest`] trait represents the interface for providing inputs
@ -30,17 +38,18 @@ pub trait Digest {
}
}
impl Digest for blake2b_simd::State {
pub struct Blake2b(blake2b_simd::State);
impl Digest for Blake2b {
fn new() -> Self {
Self::new()
Self(blake2b_simd::State::new())
}
fn hash_update(&mut self, input: &[u8]) {
self.update(input);
self.0.update(input);
}
fn hash_finalize(&mut self, out: &mut [u8]) {
let hash_result = &self.finalize();
let hash_result = &self.0.finalize();
out.copy_from_slice(hash_result.as_bytes());
}
@ -53,17 +62,18 @@ impl Digest for blake2b_simd::State {
}
}
impl Digest for blake3::Hasher {
pub struct Blake3(blake3::Hasher);
impl Digest for Blake3 {
fn new() -> Self {
Self::new()
Self(blake3::Hasher::new())
}
fn hash_update(&mut self, input: &[u8]) {
self.update(input);
self.0.update(input);
}
fn hash_finalize(&mut self, out: &mut [u8]) {
let hash_result = &self.finalize();
let hash_result = &self.0.finalize();
out.copy_from_slice(hash_result.as_bytes());
}
@ -76,23 +86,22 @@ impl Digest for blake3::Hasher {
}
}
use sm3::{Digest as SM3_D, Sm3};
pub struct Sm3(sm3::Sm3);
impl Digest for Sm3 {
fn new() -> Self {
<Self as sm3::Digest>::new()
Self(<sm3::Sm3 as sm3::Digest>::new())
}
fn hash_update(&mut self, input: &[u8]) {
self.update(input);
<sm3::Sm3 as sm3::Digest>::update(&mut self.0, input);
}
fn hash_finalize(&mut self, out: &mut [u8]) {
out.copy_from_slice(&self.clone().finalize());
out.copy_from_slice(&<sm3::Sm3 as sm3::Digest>::finalize(self.0.clone()));
}
fn reset(&mut self) {
*self = <Self as sm3::Digest>::new();
*self = Self::new();
}
fn output_bits(&self) -> usize {
@ -108,7 +117,6 @@ pub struct CRC {
size: usize,
crc_table: [u32; CRC_TABLE_LEN],
}
impl CRC {
fn generate_crc_table() -> [u32; CRC_TABLE_LEN] {
let mut table = [0; CRC_TABLE_LEN];
@ -196,7 +204,6 @@ pub fn div_ceil(a: usize, b: usize) -> usize {
pub struct BSD {
state: u16,
}
impl Digest for BSD {
fn new() -> Self {
Self { state: 0 }
@ -231,7 +238,6 @@ impl Digest for BSD {
pub struct SYSV {
state: u32,
}
impl Digest for SYSV {
fn new() -> Self {
Self { state: 0 }
@ -266,22 +272,22 @@ impl Digest for SYSV {
// Implements the Digest trait for sha2 / sha3 algorithms with fixed output
macro_rules! impl_digest_common {
($type: ty, $size: expr) => {
impl Digest for $type {
($algo_type: ty, $size: expr) => {
impl Digest for $algo_type {
fn new() -> Self {
Self::default()
Self(Default::default())
}
fn hash_update(&mut self, input: &[u8]) {
digest::Digest::update(self, input);
digest::Digest::update(&mut self.0, input);
}
fn hash_finalize(&mut self, out: &mut [u8]) {
digest::Digest::finalize_into_reset(self, out.into());
digest::Digest::finalize_into_reset(&mut self.0, out.into());
}
fn reset(&mut self) {
*self = <Self as Digest>::new();
*self = Self::new();
}
fn output_bits(&self) -> usize {
@ -293,18 +299,18 @@ macro_rules! impl_digest_common {
// Implements the Digest trait for sha2 / sha3 algorithms with variable output
macro_rules! impl_digest_shake {
($type: ty) => {
impl Digest for $type {
($algo_type: ty) => {
impl Digest for $algo_type {
fn new() -> Self {
Self::default()
Self(Default::default())
}
fn hash_update(&mut self, input: &[u8]) {
digest::Update::update(self, input);
digest::Update::update(&mut self.0, input);
}
fn hash_finalize(&mut self, out: &mut [u8]) {
digest::ExtendableOutputReset::finalize_xof_reset_into(self, out);
digest::ExtendableOutputReset::finalize_xof_reset_into(&mut self.0, out);
}
fn reset(&mut self) {
@ -318,19 +324,32 @@ macro_rules! impl_digest_shake {
};
}
impl_digest_common!(md5::Md5, 128);
impl_digest_common!(sha1::Sha1, 160);
impl_digest_common!(sha2::Sha224, 224);
impl_digest_common!(sha2::Sha256, 256);
impl_digest_common!(sha2::Sha384, 384);
impl_digest_common!(sha2::Sha512, 512);
pub struct Md5(md5::Md5);
pub struct Sha1(sha1::Sha1);
pub struct Sha224(sha2::Sha224);
pub struct Sha256(sha2::Sha256);
pub struct Sha384(sha2::Sha384);
pub struct Sha512(sha2::Sha512);
impl_digest_common!(Md5, 128);
impl_digest_common!(Sha1, 160);
impl_digest_common!(Sha224, 224);
impl_digest_common!(Sha256, 256);
impl_digest_common!(Sha384, 384);
impl_digest_common!(Sha512, 512);
impl_digest_common!(sha3::Sha3_224, 224);
impl_digest_common!(sha3::Sha3_256, 256);
impl_digest_common!(sha3::Sha3_384, 384);
impl_digest_common!(sha3::Sha3_512, 512);
impl_digest_shake!(sha3::Shake128);
impl_digest_shake!(sha3::Shake256);
pub struct Sha3_224(sha3::Sha3_224);
pub struct Sha3_256(sha3::Sha3_256);
pub struct Sha3_384(sha3::Sha3_384);
pub struct Sha3_512(sha3::Sha3_512);
impl_digest_common!(Sha3_224, 224);
impl_digest_common!(Sha3_256, 256);
impl_digest_common!(Sha3_384, 384);
impl_digest_common!(Sha3_512, 512);
pub struct Shake128(sha3::Shake128);
pub struct Shake256(sha3::Shake256);
impl_digest_shake!(Shake128);
impl_digest_shake!(Shake256);
/// A struct that writes to a digest.
///