Skip to content

Commit a4066c0

Browse files
committed
cksum: Add support for blake3
1 parent 0f38c81 commit a4066c0

3 files changed

Lines changed: 64 additions & 30 deletions

File tree

src/uu/cksum/src/cksum.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,14 @@ fn maybe_sanitize_length(
6161
// validation is performed on this length, any value is valid. If the
6262
// given length is not a multiple of 8, the last byte of the output
6363
// will have its extra bits set to zero.
64-
(Some(AlgoKind::Shake128 | AlgoKind::Shake256), Some(len)) => match len.parse::<usize>() {
65-
Ok(0) => Ok(None),
66-
Ok(l) => Ok(Some(l)),
67-
Err(_) => Err(ChecksumError::InvalidLength(len.into()).into()),
68-
},
64+
// For BLAKE3, the length is interpreted as a byte length.
65+
(Some(AlgoKind::Shake128 | AlgoKind::Shake256 | AlgoKind::Blake3), Some(len)) => {
66+
match len.parse::<usize>() {
67+
Ok(0) => Ok(None),
68+
Ok(l) => Ok(Some(l)),
69+
Err(_) => Err(ChecksumError::InvalidLength(len.into()).into()),
70+
}
71+
}
6972

7073
// For BLAKE2b, if a length is provided, validate it.
7174
(Some(AlgoKind::Blake2b), Some(len)) => calculate_blake2b_length_str(len),

src/uucore/src/lib/features/checksum/mod.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ impl AlgoKind {
115115
ALGORITHM_OPTIONS_SHA384 => Sha384,
116116
ALGORITHM_OPTIONS_SHA512 => Sha512,
117117

118+
// Extensions not in GNU as of version 9.10
119+
ALGORITHM_OPTIONS_BLAKE3 => Blake3,
118120
ALGORITHM_OPTIONS_SHAKE128 => Shake128,
119121
ALGORITHM_OPTIONS_SHAKE256 => Shake256,
120122
_ => return Err(ChecksumError::UnknownAlgorithm(algo.as_ref().to_string()).into()),
@@ -245,11 +247,12 @@ pub enum SizedAlgoKind {
245247
Md5,
246248
Sm3,
247249
Sha1,
248-
Blake3,
249250
Sha2(ShaLength),
250251
Sha3(ShaLength),
251252
// Note: we store Blake2b's length as BYTES.
252253
Blake2b(Option<usize>),
254+
// Note: we store Blake3's length as BYTES.
255+
Blake3(Option<usize>),
253256
Shake128(Option<usize>),
254257
Shake256(Option<usize>),
255258
}
@@ -266,7 +269,6 @@ impl SizedAlgoKind {
266269
| ak::Md5
267270
| ak::Sm3
268271
| ak::Sha1
269-
| ak::Blake3
270272
| ak::Sha224
271273
| ak::Sha256
272274
| ak::Sha384
@@ -281,8 +283,8 @@ impl SizedAlgoKind {
281283
(ak::Md5, _) => Ok(Self::Md5),
282284
(ak::Sm3, _) => Ok(Self::Sm3),
283285
(ak::Sha1, _) => Ok(Self::Sha1),
284-
(ak::Blake3, _) => Ok(Self::Blake3),
285286

287+
(ak::Blake3, l) => Ok(Self::Blake3(l)),
286288
(ak::Shake128, l) => Ok(Self::Shake128(l)),
287289
(ak::Shake256, l) => Ok(Self::Shake256(l)),
288290
(ak::Sha2, Some(l)) => Ok(Self::Sha2(ShaLength::try_from(l)?)),
@@ -305,19 +307,22 @@ impl SizedAlgoKind {
305307
}
306308

307309
pub fn to_tag(self) -> String {
308-
use SizedAlgoKind::*;
309310
match self {
310-
Md5 => "MD5".into(),
311-
Sm3 => "SM3".into(),
312-
Sha1 => "SHA1".into(),
313-
Blake3 => "BLAKE3".into(),
314-
Sha2(len) => format!("SHA{}", len.as_usize()),
315-
Sha3(len) => format!("SHA3-{}", len.as_usize()),
316-
Blake2b(Some(byte_len)) => format!("BLAKE2b-{}", byte_len * 8),
317-
Blake2b(None) => "BLAKE2b".into(),
318-
Shake128(_) => "SHAKE128".into(),
319-
Shake256(_) => "SHAKE256".into(),
320-
Sysv | Bsd | Crc | Crc32b => panic!("Should not be used for tagging"),
311+
Self::Md5 => "MD5".into(),
312+
Self::Sm3 => "SM3".into(),
313+
Self::Sha1 => "SHA1".into(),
314+
Self::Sha2(len) => format!("SHA{}", len.as_usize()),
315+
Self::Sha3(len) => format!("SHA3-{}", len.as_usize()),
316+
Self::Blake2b(Some(byte_len)) => format!("BLAKE2b-{}", byte_len * 8),
317+
Self::Blake2b(None) => "BLAKE2b".into(),
318+
Self::Blake3(byte_len) => {
319+
format!("BLAKE3-{}", byte_len.unwrap_or(Blake3::DEFAULT_BYTE_SIZE))
320+
}
321+
Self::Shake128(_) => "SHAKE128".into(),
322+
Self::Shake256(_) => "SHAKE256".into(),
323+
Self::Sysv | Self::Bsd | Self::Crc | Self::Crc32b => {
324+
panic!("Should not be used for tagging")
325+
}
321326
}
322327
}
323328

@@ -331,7 +336,6 @@ impl SizedAlgoKind {
331336
Self::Md5 => Box::new(Md5::default()),
332337
Self::Sm3 => Box::new(Sm3::default()),
333338
Self::Sha1 => Box::new(Sha1::default()),
334-
Self::Blake3 => Box::new(Blake3::default()),
335339
Self::Sha2(Len224) => Box::new(Sha224::default()),
336340
Self::Sha2(Len256) => Box::new(Sha256::default()),
337341
Self::Sha2(Len384) => Box::new(Sha384::default()),
@@ -343,6 +347,9 @@ impl SizedAlgoKind {
343347
Self::Blake2b(len_opt) => {
344348
Box::new(len_opt.map(Blake2b::with_output_bytes).unwrap_or_default())
345349
}
350+
Self::Blake3(len_opt) => {
351+
Box::new(len_opt.map(Blake3::with_output_bytes).unwrap_or_default())
352+
}
346353
Self::Shake128(len_opt) => {
347354
Box::new(len_opt.map(Shake128::with_output_bits).unwrap_or_default())
348355
}
@@ -361,7 +368,7 @@ impl SizedAlgoKind {
361368
Self::Md5 => 128,
362369
Self::Sm3 => 512,
363370
Self::Sha1 => 160,
364-
Self::Blake3 => 256,
371+
Self::Blake3(len) => len.unwrap_or(Blake3::DEFAULT_BYTE_SIZE) * 8,
365372
Self::Sha2(len) => len.as_usize(),
366373
Self::Sha3(len) => len.as_usize(),
367374
Self::Blake2b(len) => len.unwrap_or(Blake2b::DEFAULT_BYTE_SIZE * 8),

src/uucore/src/lib/features/sum.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ pub trait Digest {
6868
}
6969

7070
fn result(&mut self) -> DigestOutput {
71-
let mut buf: Vec<u8> = vec![0; self.output_bytes()];
71+
let out_bytes: usize = self.output_bytes();
72+
let mut buf: Vec<u8> = vec![0; out_bytes];
7273
self.hash_finalize(&mut buf);
7374
DigestOutput::Vec(buf)
7475
}
@@ -122,25 +123,48 @@ impl Digest for Blake2b {
122123
}
123124
}
124125

125-
#[derive(Default)]
126-
pub struct Blake3(blake3::Hasher);
126+
pub struct Blake3 {
127+
digest: blake3::Hasher,
128+
byte_size: usize,
129+
}
130+
131+
impl Blake3 {
132+
/// Default length for the BLAKE3 digest in bytes.
133+
pub const DEFAULT_BYTE_SIZE: usize = 32;
134+
135+
pub fn with_output_bytes(output_bytes: usize) -> Self {
136+
Self {
137+
digest: blake3::Hasher::new(),
138+
byte_size: output_bytes,
139+
}
140+
}
141+
}
142+
143+
impl Default for Blake3 {
144+
fn default() -> Self {
145+
Self {
146+
digest: Default::default(),
147+
byte_size: Self::DEFAULT_BYTE_SIZE,
148+
}
149+
}
150+
}
127151

128152
impl Digest for Blake3 {
129153
fn hash_update(&mut self, input: &[u8]) {
130-
self.0.update(input);
154+
self.digest.update(input);
131155
}
132156

133157
fn hash_finalize(&mut self, out: &mut [u8]) {
134-
let hash_result = &self.0.finalize();
135-
out.copy_from_slice(hash_result.as_bytes());
158+
let hash_result = &self.digest.finalize();
159+
out.copy_from_slice(&hash_result.as_bytes()[..self.byte_size]);
136160
}
137161

138162
fn reset(&mut self) {
139-
*self = Self::default();
163+
*self = Self::with_output_bytes(self.output_bytes());
140164
}
141165

142166
fn output_bits(&self) -> usize {
143-
256
167+
self.byte_size * 8
144168
}
145169
}
146170

0 commit comments

Comments
 (0)