@@ -204,15 +204,15 @@ impl AlgoKind {
204204 /// When checking untagged format lines, non-XOF non-legacy algorithms
205205 /// should report "improperly formatted lines" if the digest length isn't
206206 /// equivalent to this.
207- pub fn expected_digest_bit_len ( self ) -> Option < usize > {
207+ pub fn expected_digest_bit_len ( self ) -> Option < HashLength > {
208208 match self {
209- Self :: Md5 => Some ( Md5 :: BIT_SIZE ) ,
210- Self :: Sm3 => Some ( Sm3 :: BIT_SIZE ) ,
211- Self :: Sha1 => Some ( Sha1 :: BIT_SIZE ) ,
212- Self :: Sha224 => Some ( Sha224 :: BIT_SIZE ) ,
213- Self :: Sha256 => Some ( Sha256 :: BIT_SIZE ) ,
214- Self :: Sha384 => Some ( Sha384 :: BIT_SIZE ) ,
215- Self :: Sha512 => Some ( Sha512 :: BIT_SIZE ) ,
209+ Self :: Md5 => Some ( HashLength :: from_bits ( Md5 :: BIT_SIZE ) ) ,
210+ Self :: Sm3 => Some ( HashLength :: from_bits ( Sm3 :: BIT_SIZE ) ) ,
211+ Self :: Sha1 => Some ( HashLength :: from_bits ( Sha1 :: BIT_SIZE ) ) ,
212+ Self :: Sha224 => Some ( HashLength :: from_bits ( Sha224 :: BIT_SIZE ) ) ,
213+ Self :: Sha256 => Some ( HashLength :: from_bits ( Sha256 :: BIT_SIZE ) ) ,
214+ Self :: Sha384 => Some ( HashLength :: from_bits ( Sha384 :: BIT_SIZE ) ) ,
215+ Self :: Sha512 => Some ( HashLength :: from_bits ( Sha512 :: BIT_SIZE ) ) ,
216216 _ => None ,
217217 }
218218 }
@@ -253,6 +253,46 @@ impl TryFrom<usize> for ShaLength {
253253 }
254254}
255255
256+ /// Stores a hash length in bits.
257+ #[ derive( Debug , Clone , Copy ) ]
258+ pub struct HashLength {
259+ bit_len : usize ,
260+ }
261+
262+ impl HashLength {
263+ #[ must_use]
264+ #[ inline]
265+ pub ( crate ) fn from_bytes ( n : usize ) -> Self {
266+ Self { bit_len : n * 8 }
267+ }
268+
269+ #[ must_use]
270+ #[ inline]
271+ pub fn from_bits ( n : usize ) -> Self {
272+ Self { bit_len : n }
273+ }
274+
275+ #[ must_use]
276+ #[ inline]
277+ pub ( crate ) fn as_bits ( self ) -> usize {
278+ self . bit_len
279+ }
280+
281+ #[ must_use]
282+ #[ inline]
283+ pub ( crate ) fn as_bytes ( self ) -> usize {
284+ self . bit_len . div_ceil ( 8 )
285+ }
286+ }
287+
288+ impl From < ShaLength > for HashLength {
289+ fn from ( value : ShaLength ) -> Self {
290+ Self {
291+ bit_len : value. as_usize ( ) ,
292+ }
293+ }
294+ }
295+
256296/// Represents an actual determined algorithm.
257297#[ derive( Debug , Clone , Copy ) ]
258298pub enum SizedAlgoKind {
@@ -265,16 +305,14 @@ pub enum SizedAlgoKind {
265305 Sha1 ,
266306 Sha2 ( ShaLength ) ,
267307 Sha3 ( ShaLength ) ,
268- // Note: we store Blake*'s length as BYTES.
269- Blake2b ( usize ) ,
270- Blake3 ( usize ) ,
271- // Shake* length are stored in bits.
272- Shake128 ( Option < usize > ) ,
273- Shake256 ( Option < usize > ) ,
308+ Blake2b ( HashLength ) ,
309+ Blake3 ( HashLength ) ,
310+ Shake128 ( Option < HashLength > ) ,
311+ Shake256 ( Option < HashLength > ) ,
274312}
275313
276314impl SizedAlgoKind {
277- pub fn from_unsized ( kind : AlgoKind , output_length : Option < usize > ) -> UResult < Self > {
315+ pub fn from_unsized ( kind : AlgoKind , output_length : Option < HashLength > ) -> UResult < Self > {
278316 use AlgoKind as ak;
279317 match ( kind, output_length) {
280318 (
@@ -300,12 +338,16 @@ impl SizedAlgoKind {
300338 ( ak:: Sm3 , _) => Ok ( Self :: Sm3 ) ,
301339 ( ak:: Sha1 , _) => Ok ( Self :: Sha1 ) ,
302340
303- ( ak:: Blake2b , l) => Ok ( Self :: Blake2b ( l. unwrap_or ( Blake2b :: DEFAULT_BYTE_SIZE ) ) ) ,
304- ( ak:: Blake3 , l) => Ok ( Self :: Blake3 ( l. unwrap_or ( Blake3 :: DEFAULT_BYTE_SIZE ) ) ) ,
341+ ( ak:: Blake2b , l) => Ok ( Self :: Blake2b (
342+ l. unwrap_or ( HashLength :: from_bits ( Blake2b :: DEFAULT_BIT_SIZE ) ) ,
343+ ) ) ,
344+ ( ak:: Blake3 , l) => Ok ( Self :: Blake3 (
345+ l. unwrap_or ( HashLength :: from_bits ( Blake3 :: DEFAULT_BIT_SIZE ) ) ,
346+ ) ) ,
305347 ( ak:: Shake128 , l) => Ok ( Self :: Shake128 ( l) ) ,
306348 ( ak:: Shake256 , l) => Ok ( Self :: Shake256 ( l) ) ,
307- ( ak:: Sha2 , Some ( l) ) => Ok ( Self :: Sha2 ( ShaLength :: try_from ( l) ?) ) ,
308- ( ak:: Sha3 , Some ( l) ) => Ok ( Self :: Sha3 ( ShaLength :: try_from ( l) ?) ) ,
349+ ( ak:: Sha2 , Some ( l) ) => Ok ( Self :: Sha2 ( ShaLength :: try_from ( l. as_bits ( ) ) ?) ) ,
350+ ( ak:: Sha3 , Some ( l) ) => Ok ( Self :: Sha3 ( ShaLength :: try_from ( l. as_bits ( ) ) ?) ) ,
309351 ( algo @ ( ak:: Sha2 | ak:: Sha3 ) , None ) => {
310352 Err ( ChecksumError :: LengthRequiredForSha ( algo. to_lowercase ( ) . into ( ) ) . into ( ) )
311353 }
@@ -323,16 +365,16 @@ impl SizedAlgoKind {
323365 Self :: Sha1 => "SHA1" . into ( ) ,
324366 Self :: Sha2 ( len) => format ! ( "SHA{}" , len. as_usize( ) ) ,
325367 Self :: Sha3 ( len) => format ! ( "SHA3-{}" , len. as_usize( ) ) ,
326- Self :: Blake2b ( Blake2b :: DEFAULT_BYTE_SIZE ) => "BLAKE2b" . into ( ) ,
327- Self :: Blake2b ( byte_len ) => format ! ( "BLAKE2b-{}" , byte_len * 8 ) ,
328- Self :: Blake3 ( byte_len ) => format ! ( "BLAKE3-{}" , byte_len * 8 ) ,
329- Self :: Shake128 ( opt_bit_len ) => format ! (
368+ Self :: Blake2b ( len ) if len . as_bits ( ) == Blake2b :: DEFAULT_BIT_SIZE => "BLAKE2b" . into ( ) ,
369+ Self :: Blake2b ( len ) => format ! ( "BLAKE2b-{}" , len . as_bits ( ) ) ,
370+ Self :: Blake3 ( len ) => format ! ( "BLAKE3-{}" , len . as_bits ( ) ) ,
371+ Self :: Shake128 ( opt_len ) => format ! (
330372 "SHAKE128-{}" ,
331- opt_bit_len . unwrap_or ( Shake128 :: DEFAULT_BIT_SIZE )
373+ opt_len . map_or ( Shake128 :: DEFAULT_BIT_SIZE , HashLength :: as_bits )
332374 ) ,
333- Self :: Shake256 ( opt_bit_len ) => format ! (
375+ Self :: Shake256 ( opt_len ) => format ! (
334376 "SHAKE256-{}" ,
335- opt_bit_len . unwrap_or ( Shake256 :: DEFAULT_BIT_SIZE )
377+ opt_len . map_or ( Shake256 :: DEFAULT_BIT_SIZE , HashLength :: as_bits )
336378 ) ,
337379 Self :: Sysv | Self :: Bsd | Self :: Crc | Self :: Crc32b => {
338380 panic ! ( "Should not be used for tagging" )
@@ -358,14 +400,20 @@ impl SizedAlgoKind {
358400 Self :: Sha3 ( Len256 ) => Box :: new ( Sha3_256 :: default ( ) ) ,
359401 Self :: Sha3 ( Len384 ) => Box :: new ( Sha3_384 :: default ( ) ) ,
360402 Self :: Sha3 ( Len512 ) => Box :: new ( Sha3_512 :: default ( ) ) ,
361- Self :: Blake2b ( len) => Box :: new ( Blake2b :: with_output_bytes ( * len) ) ,
362- Self :: Blake3 ( len) => Box :: new ( Blake3 :: with_output_bytes ( * len) ) ,
363- Self :: Shake128 ( len_opt) => {
364- Box :: new ( len_opt. map ( Shake128 :: with_output_bits) . unwrap_or_default ( ) )
365- }
366- Self :: Shake256 ( len_opt) => {
367- Box :: new ( len_opt. map ( Shake256 :: with_output_bits) . unwrap_or_default ( ) )
368- }
403+ Self :: Blake2b ( len) => Box :: new ( Blake2b :: with_output_bytes ( len. as_bytes ( ) ) ) ,
404+ Self :: Blake3 ( len) => Box :: new ( Blake3 :: with_output_bytes ( len. as_bytes ( ) ) ) ,
405+ Self :: Shake128 ( len_opt) => Box :: new (
406+ len_opt
407+ . map ( HashLength :: as_bits)
408+ . map ( Shake128 :: with_output_bits)
409+ . unwrap_or_default ( ) ,
410+ ) ,
411+ Self :: Shake256 ( len_opt) => Box :: new (
412+ len_opt
413+ . map ( HashLength :: as_bits)
414+ . map ( Shake256 :: with_output_bits)
415+ . unwrap_or_default ( ) ,
416+ ) ,
369417 }
370418 }
371419
@@ -380,10 +428,10 @@ impl SizedAlgoKind {
380428 Self :: Sha1 => 160 ,
381429 Self :: Sha2 ( len) => len. as_usize ( ) ,
382430 Self :: Sha3 ( len) => len. as_usize ( ) ,
383- Self :: Blake2b ( len) => len * 8 ,
384- Self :: Blake3 ( len) => len * 8 ,
385- Self :: Shake128 ( len) => len. unwrap_or ( Shake128 :: DEFAULT_BIT_SIZE ) ,
386- Self :: Shake256 ( len) => len. unwrap_or ( Shake256 :: DEFAULT_BIT_SIZE ) ,
431+ Self :: Blake2b ( len) => len. as_bits ( ) ,
432+ Self :: Blake3 ( len) => len. as_bits ( ) ,
433+ Self :: Shake128 ( len) => len. map_or ( Shake128 :: DEFAULT_BIT_SIZE , HashLength :: as_bits ) ,
434+ Self :: Shake256 ( len) => len. map_or ( Shake256 :: DEFAULT_BIT_SIZE , HashLength :: as_bits ) ,
387435 }
388436 }
389437 pub fn is_legacy ( & self ) -> bool {
@@ -506,7 +554,7 @@ pub enum BlakeLength<'s> {
506554/// Note: when the input is a string, validation may print error messages.
507555/// Note: when the algo is Blake2b, values that are above 512
508556/// (Blake2b::DEFAULT_BIT_SIZE) are errors.
509- pub fn parse_blake_length ( algo : AlgoKind , bit_length : BlakeLength < ' _ > ) -> UResult < usize > {
557+ pub fn parse_blake_length ( algo : AlgoKind , bit_length : BlakeLength < ' _ > ) -> UResult < HashLength > {
510558 debug_assert ! ( matches!( algo, AlgoKind :: Blake2b | AlgoKind :: Blake3 ) ) ;
511559
512560 let print_error = || {
@@ -529,8 +577,8 @@ pub fn parse_blake_length(algo: AlgoKind, bit_length: BlakeLength<'_>) -> UResul
529577
530578 if n == 0 {
531579 return Ok ( match algo {
532- AlgoKind :: Blake2b => Blake2b :: DEFAULT_BYTE_SIZE ,
533- AlgoKind :: Blake3 => Blake3 :: DEFAULT_BYTE_SIZE ,
580+ AlgoKind :: Blake2b => HashLength :: from_bits ( Blake2b :: DEFAULT_BIT_SIZE ) ,
581+ AlgoKind :: Blake3 => HashLength :: from_bits ( Blake3 :: DEFAULT_BIT_SIZE ) ,
534582 _ => unreachable ! ( ) ,
535583 } ) ;
536584 }
@@ -545,7 +593,7 @@ pub fn parse_blake_length(algo: AlgoKind, bit_length: BlakeLength<'_>) -> UResul
545593 return Err ( ChecksumError :: LengthNotMultipleOf8 . into ( ) ) ;
546594 }
547595
548- Ok ( n / 8 )
596+ Ok ( HashLength :: from_bits ( n ) )
549597}
550598
551599pub fn validate_sha2_sha3_length ( algo_name : AlgoKind , length : Option < usize > ) -> UResult < ShaLength > {
@@ -562,7 +610,7 @@ pub fn validate_sha2_sha3_length(algo_name: AlgoKind, length: Option<usize>) ->
562610 }
563611}
564612
565- pub fn sanitize_sha2_sha3_length_str ( algo_kind : AlgoKind , length : & str ) -> UResult < usize > {
613+ pub fn sanitize_sha2_sha3_length_str ( algo_kind : AlgoKind , length : & str ) -> UResult < HashLength > {
566614 // There is a difference in the errors sent when the length is not a number
567615 // vs. its an invalid number.
568616 //
@@ -580,7 +628,7 @@ pub fn sanitize_sha2_sha3_length_str(algo_kind: AlgoKind, length: &str) -> UResu
580628 } ;
581629
582630 if [ 224 , 256 , 384 , 512 ] . contains ( & len) {
583- Ok ( len)
631+ Ok ( HashLength :: from_bits ( len) )
584632 } else {
585633 show_error ! ( "{}" , ChecksumError :: InvalidLength ( length. into( ) ) ) ;
586634 Err ( ChecksumError :: InvalidLengthForSha ( algo_kind. to_uppercase ( ) . into ( ) ) . into ( ) )
@@ -664,17 +712,23 @@ mod tests {
664712 #[ test]
665713 fn test_calculate_blake2b_length ( ) {
666714 assert_eq ! (
667- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "0" ) ) . unwrap( ) ,
715+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "0" ) )
716+ . unwrap( )
717+ . as_bytes( ) ,
668718 Blake2b :: DEFAULT_BYTE_SIZE
669719 ) ;
670720 assert ! ( parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "10" ) ) . is_err( ) ) ;
671721 assert ! ( parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "520" ) ) . is_err( ) ) ;
672722 assert_eq ! (
673- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "512" ) ) . unwrap( ) ,
723+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "512" ) )
724+ . unwrap( )
725+ . as_bytes( ) ,
674726 Blake2b :: DEFAULT_BYTE_SIZE
675727 ) ;
676728 assert_eq ! (
677- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "256" ) ) . unwrap( ) ,
729+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "256" ) )
730+ . unwrap( )
731+ . as_bytes( ) ,
678732 32
679733 ) ;
680734 }
0 commit comments