mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #5749 from DitherWither/main
cksum: Add --length argument for the blake2b algorithm
This commit is contained in:
commit
8fe1b2619c
6 changed files with 136 additions and 5 deletions
|
@ -4,7 +4,7 @@
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) fname, algo
|
// spell-checker:ignore (ToDO) fname, algo
|
||||||
use clap::{crate_version, Arg, ArgAction, Command};
|
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
||||||
use hex::encode;
|
use hex::encode;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -36,7 +36,10 @@ const ALGORITHM_OPTIONS_SHA512: &str = "sha512";
|
||||||
const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b";
|
const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b";
|
||||||
const ALGORITHM_OPTIONS_SM3: &str = "sm3";
|
const ALGORITHM_OPTIONS_SM3: &str = "sm3";
|
||||||
|
|
||||||
fn detect_algo(program: &str) -> (&'static str, Box<dyn Digest + 'static>, usize) {
|
fn detect_algo(
|
||||||
|
program: &str,
|
||||||
|
length: Option<usize>,
|
||||||
|
) -> (&'static str, Box<dyn Digest + 'static>, usize) {
|
||||||
match program {
|
match program {
|
||||||
ALGORITHM_OPTIONS_SYSV => (
|
ALGORITHM_OPTIONS_SYSV => (
|
||||||
ALGORITHM_OPTIONS_SYSV,
|
ALGORITHM_OPTIONS_SYSV,
|
||||||
|
@ -85,7 +88,11 @@ fn detect_algo(program: &str) -> (&'static str, Box<dyn Digest + 'static>, usize
|
||||||
),
|
),
|
||||||
ALGORITHM_OPTIONS_BLAKE2B => (
|
ALGORITHM_OPTIONS_BLAKE2B => (
|
||||||
ALGORITHM_OPTIONS_BLAKE2B,
|
ALGORITHM_OPTIONS_BLAKE2B,
|
||||||
Box::new(Blake2b::new()) as Box<dyn Digest>,
|
Box::new(if let Some(length) = length {
|
||||||
|
Blake2b::with_output_bytes(length)
|
||||||
|
} else {
|
||||||
|
Blake2b::new()
|
||||||
|
}) as Box<dyn Digest>,
|
||||||
512,
|
512,
|
||||||
),
|
),
|
||||||
ALGORITHM_OPTIONS_SM3 => (
|
ALGORITHM_OPTIONS_SM3 => (
|
||||||
|
@ -102,6 +109,7 @@ struct Options {
|
||||||
digest: Box<dyn Digest + 'static>,
|
digest: Box<dyn Digest + 'static>,
|
||||||
output_bits: usize,
|
output_bits: usize,
|
||||||
untagged: bool,
|
untagged: bool,
|
||||||
|
length: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate checksum
|
/// Calculate checksum
|
||||||
|
@ -161,8 +169,13 @@ where
|
||||||
(ALGORITHM_OPTIONS_CRC, true) => println!("{sum} {sz}"),
|
(ALGORITHM_OPTIONS_CRC, true) => println!("{sum} {sz}"),
|
||||||
(ALGORITHM_OPTIONS_CRC, false) => println!("{sum} {sz} {}", filename.display()),
|
(ALGORITHM_OPTIONS_CRC, false) => println!("{sum} {sz} {}", filename.display()),
|
||||||
(ALGORITHM_OPTIONS_BLAKE2B, _) if !options.untagged => {
|
(ALGORITHM_OPTIONS_BLAKE2B, _) if !options.untagged => {
|
||||||
|
if let Some(length) = options.length {
|
||||||
|
// Multiply by 8 here, as we want to print the length in bits.
|
||||||
|
println!("BLAKE2b-{} ({}) = {sum}", length * 8, filename.display());
|
||||||
|
} else {
|
||||||
println!("BLAKE2b ({}) = {sum}", filename.display());
|
println!("BLAKE2b ({}) = {sum}", filename.display());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if options.untagged {
|
if options.untagged {
|
||||||
println!("{sum} {}", filename.display());
|
println!("{sum} {}", filename.display());
|
||||||
|
@ -217,6 +230,7 @@ mod options {
|
||||||
pub const ALGORITHM: &str = "algorithm";
|
pub const ALGORITHM: &str = "algorithm";
|
||||||
pub const FILE: &str = "file";
|
pub const FILE: &str = "file";
|
||||||
pub const UNTAGGED: &str = "untagged";
|
pub const UNTAGGED: &str = "untagged";
|
||||||
|
pub const LENGTH: &str = "length";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
|
@ -228,11 +242,54 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
None => ALGORITHM_OPTIONS_CRC,
|
None => ALGORITHM_OPTIONS_CRC,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (name, algo, bits) = detect_algo(algo_name);
|
let input_length = matches.get_one::<usize>(options::LENGTH);
|
||||||
|
let length = if let Some(length) = input_length {
|
||||||
|
match length.to_owned() {
|
||||||
|
0 => None,
|
||||||
|
n if n % 8 != 0 => {
|
||||||
|
// GNU's implementation seem to use these quotation marks
|
||||||
|
// in their error messages, so we do the same.
|
||||||
|
uucore::show_error!("invalid length: \u{2018}{length}\u{2019}");
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"length is not a multiple of 8",
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
n if n > 512 => {
|
||||||
|
uucore::show_error!("invalid length: \u{2018}{length}\u{2019}");
|
||||||
|
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"maximum digest length for \u{2018}BLAKE2b\u{2019} is 512 bits",
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
n => {
|
||||||
|
if algo_name != ALGORITHM_OPTIONS_BLAKE2B {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"--length is only supported with --algorithm=blake2b",
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide by 8, as our blake2b implementation expects bytes
|
||||||
|
// instead of bits.
|
||||||
|
Some(n / 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (name, algo, bits) = detect_algo(algo_name, length);
|
||||||
|
|
||||||
let opts = Options {
|
let opts = Options {
|
||||||
algo_name: name,
|
algo_name: name,
|
||||||
digest: algo,
|
digest: algo,
|
||||||
output_bits: bits,
|
output_bits: bits,
|
||||||
|
length,
|
||||||
untagged: matches.get_flag(options::UNTAGGED),
|
untagged: matches.get_flag(options::UNTAGGED),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -282,5 +339,13 @@ pub fn uu_app() -> Command {
|
||||||
.help("create a reversed style checksum, without digest type")
|
.help("create a reversed style checksum, without digest type")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::LENGTH)
|
||||||
|
.long(options::LENGTH)
|
||||||
|
.value_parser(value_parser!(usize))
|
||||||
|
.short('l')
|
||||||
|
.help("digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8")
|
||||||
|
.action(ArgAction::Set),
|
||||||
|
)
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,3 +228,61 @@ fn test_untagged_algorithm_stdin() {
|
||||||
.stdout_is_fixture(format!("untagged/{algo}_stdin.expected"));
|
.stdout_is_fixture(format!("untagged/{algo}_stdin.expected"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_length_with_wrong_algorithm() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--length=16")
|
||||||
|
.arg("--algorithm=md5")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.fails()
|
||||||
|
.no_stdout()
|
||||||
|
.stderr_contains("cksum: --length is only supported with --algorithm=blake2b")
|
||||||
|
.code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_length_not_supported() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--length=15")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.fails()
|
||||||
|
.no_stdout()
|
||||||
|
.stderr_is_fixture("unsupported_length.expected")
|
||||||
|
.code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_length() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--length=16")
|
||||||
|
.arg("--algorithm=blake2b")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg("alice_in_wonderland.txt")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_fixture("supported_length.expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_length_greater_than_512() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--length=1024")
|
||||||
|
.arg("--algorithm=blake2b")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg("alice_in_wonderland.txt")
|
||||||
|
.fails()
|
||||||
|
.no_stdout()
|
||||||
|
.stderr_is_fixture("length_larger_than_512.expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_length_is_zero() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--length=0")
|
||||||
|
.arg("--algorithm=blake2b")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg("alice_in_wonderland.txt")
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.stdout_is_fixture("length_is_zero.expected");
|
||||||
|
}
|
||||||
|
|
2
tests/fixtures/cksum/length_is_zero.expected
vendored
Normal file
2
tests/fixtures/cksum/length_is_zero.expected
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
BLAKE2b (lorem_ipsum.txt) = 0e97a09189e560c3789c0bff1f020166861ef857d1fbfe4574de1842e3c06cabb9575e4af6309a166158c2b408d3c038c1b49d828b35158142cdc0396d1195c3
|
||||||
|
BLAKE2b (alice_in_wonderland.txt) = 91b8b0f0868e905ad18b8ac35e4a1dacd289857b19258ab5d1e071761af758b0134ec152d4f011fe1825ca889c80c2e072ca70eb50548c25fc49a98937515af4
|
2
tests/fixtures/cksum/length_larger_than_512.expected
vendored
Normal file
2
tests/fixtures/cksum/length_larger_than_512.expected
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
cksum: invalid length: ‘1024’
|
||||||
|
cksum: maximum digest length for ‘BLAKE2b’ is 512 bits
|
2
tests/fixtures/cksum/supported_length.expected
vendored
Normal file
2
tests/fixtures/cksum/supported_length.expected
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
BLAKE2b-16 (lorem_ipsum.txt) = 7e2f
|
||||||
|
BLAKE2b-16 (alice_in_wonderland.txt) = a546
|
2
tests/fixtures/cksum/unsupported_length.expected
vendored
Normal file
2
tests/fixtures/cksum/unsupported_length.expected
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
cksum: invalid length: ‘15’
|
||||||
|
cksum: length is not a multiple of 8
|
Loading…
Add table
Add a link
Reference in a new issue