@@ -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 {
@@ -266,15 +306,15 @@ pub enum SizedAlgoKind {
266306 Sha2 ( ShaLength ) ,
267307 Sha3 ( ShaLength ) ,
268308 // Note: we store Blake*'s length as BYTES.
269- Blake2b ( usize ) ,
270- Blake3 ( usize ) ,
309+ Blake2b ( HashLength ) ,
310+ Blake3 ( HashLength ) ,
271311 // Shake* length are stored in bits.
272- Shake128 ( Option < usize > ) ,
273- Shake256 ( Option < usize > ) ,
312+ Shake128 ( Option < HashLength > ) ,
313+ Shake256 ( Option < HashLength > ) ,
274314}
275315
276316impl SizedAlgoKind {
277- pub fn from_unsized ( kind : AlgoKind , output_length : Option < usize > ) -> UResult < Self > {
317+ pub fn from_unsized ( kind : AlgoKind , output_length : Option < HashLength > ) -> UResult < Self > {
278318 use AlgoKind as ak;
279319 match ( kind, output_length) {
280320 (
@@ -300,12 +340,16 @@ impl SizedAlgoKind {
300340 ( ak:: Sm3 , _) => Ok ( Self :: Sm3 ) ,
301341 ( ak:: Sha1 , _) => Ok ( Self :: Sha1 ) ,
302342
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 ) ) ) ,
343+ ( ak:: Blake2b , l) => Ok ( Self :: Blake2b (
344+ l. unwrap_or ( HashLength :: from_bits ( Blake2b :: DEFAULT_BIT_SIZE ) ) ,
345+ ) ) ,
346+ ( ak:: Blake3 , l) => Ok ( Self :: Blake3 (
347+ l. unwrap_or ( HashLength :: from_bits ( Blake3 :: DEFAULT_BIT_SIZE ) ) ,
348+ ) ) ,
305349 ( ak:: Shake128 , l) => Ok ( Self :: Shake128 ( l) ) ,
306350 ( 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) ?) ) ,
351+ ( ak:: Sha2 , Some ( l) ) => Ok ( Self :: Sha2 ( ShaLength :: try_from ( l. as_bits ( ) ) ?) ) ,
352+ ( ak:: Sha3 , Some ( l) ) => Ok ( Self :: Sha3 ( ShaLength :: try_from ( l. as_bits ( ) ) ?) ) ,
309353 ( algo @ ( ak:: Sha2 | ak:: Sha3 ) , None ) => {
310354 Err ( ChecksumError :: LengthRequiredForSha ( algo. to_lowercase ( ) . into ( ) ) . into ( ) )
311355 }
@@ -323,16 +367,16 @@ impl SizedAlgoKind {
323367 Self :: Sha1 => "SHA1" . into ( ) ,
324368 Self :: Sha2 ( len) => format ! ( "SHA{}" , len. as_usize( ) ) ,
325369 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 ! (
370+ Self :: Blake2b ( len ) if len . as_bits ( ) == Blake2b :: DEFAULT_BIT_SIZE => "BLAKE2b" . into ( ) ,
371+ Self :: Blake2b ( len ) => format ! ( "BLAKE2b-{}" , len . as_bits ( ) ) ,
372+ Self :: Blake3 ( len ) => format ! ( "BLAKE3-{}" , len . as_bits ( ) ) ,
373+ Self :: Shake128 ( opt_len ) => format ! (
330374 "SHAKE128-{}" ,
331- opt_bit_len . unwrap_or ( Shake128 :: DEFAULT_BIT_SIZE )
375+ opt_len . map_or ( Shake128 :: DEFAULT_BIT_SIZE , HashLength :: as_bits )
332376 ) ,
333- Self :: Shake256 ( opt_bit_len ) => format ! (
377+ Self :: Shake256 ( opt_len ) => format ! (
334378 "SHAKE256-{}" ,
335- opt_bit_len . unwrap_or ( Shake256 :: DEFAULT_BIT_SIZE )
379+ opt_len . map_or ( Shake256 :: DEFAULT_BIT_SIZE , HashLength :: as_bits )
336380 ) ,
337381 Self :: Sysv | Self :: Bsd | Self :: Crc | Self :: Crc32b => {
338382 panic ! ( "Should not be used for tagging" )
@@ -358,14 +402,20 @@ impl SizedAlgoKind {
358402 Self :: Sha3 ( Len256 ) => Box :: new ( Sha3_256 :: default ( ) ) ,
359403 Self :: Sha3 ( Len384 ) => Box :: new ( Sha3_384 :: default ( ) ) ,
360404 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- }
405+ Self :: Blake2b ( len) => Box :: new ( Blake2b :: with_output_bytes ( len. as_bytes ( ) ) ) ,
406+ Self :: Blake3 ( len) => Box :: new ( Blake3 :: with_output_bytes ( len. as_bytes ( ) ) ) ,
407+ Self :: Shake128 ( len_opt) => Box :: new (
408+ len_opt
409+ . map ( HashLength :: as_bits)
410+ . map ( Shake128 :: with_output_bits)
411+ . unwrap_or_default ( ) ,
412+ ) ,
413+ Self :: Shake256 ( len_opt) => Box :: new (
414+ len_opt
415+ . map ( HashLength :: as_bits)
416+ . map ( Shake256 :: with_output_bits)
417+ . unwrap_or_default ( ) ,
418+ ) ,
369419 }
370420 }
371421
@@ -380,10 +430,10 @@ impl SizedAlgoKind {
380430 Self :: Sha1 => 160 ,
381431 Self :: Sha2 ( len) => len. as_usize ( ) ,
382432 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 ) ,
433+ Self :: Blake2b ( len) => len. as_bits ( ) ,
434+ Self :: Blake3 ( len) => len. as_bits ( ) ,
435+ Self :: Shake128 ( len) => len. map_or ( Shake128 :: DEFAULT_BIT_SIZE , HashLength :: as_bits ) ,
436+ Self :: Shake256 ( len) => len. map_or ( Shake256 :: DEFAULT_BIT_SIZE , HashLength :: as_bits ) ,
387437 }
388438 }
389439 pub fn is_legacy ( & self ) -> bool {
@@ -506,7 +556,7 @@ pub enum BlakeLength<'s> {
506556/// Note: when the input is a string, validation may print error messages.
507557/// Note: when the algo is Blake2b, values that are above 512
508558/// (Blake2b::DEFAULT_BIT_SIZE) are errors.
509- pub fn parse_blake_length ( algo : AlgoKind , bit_length : BlakeLength < ' _ > ) -> UResult < usize > {
559+ pub fn parse_blake_length ( algo : AlgoKind , bit_length : BlakeLength < ' _ > ) -> UResult < HashLength > {
510560 debug_assert ! ( matches!( algo, AlgoKind :: Blake2b | AlgoKind :: Blake3 ) ) ;
511561
512562 let print_error = || {
@@ -529,8 +579,8 @@ pub fn parse_blake_length(algo: AlgoKind, bit_length: BlakeLength<'_>) -> UResul
529579
530580 if n == 0 {
531581 return Ok ( match algo {
532- AlgoKind :: Blake2b => Blake2b :: DEFAULT_BYTE_SIZE ,
533- AlgoKind :: Blake3 => Blake3 :: DEFAULT_BYTE_SIZE ,
582+ AlgoKind :: Blake2b => HashLength :: from_bits ( Blake2b :: DEFAULT_BIT_SIZE ) ,
583+ AlgoKind :: Blake3 => HashLength :: from_bits ( Blake3 :: DEFAULT_BIT_SIZE ) ,
534584 _ => unreachable ! ( ) ,
535585 } ) ;
536586 }
@@ -545,7 +595,7 @@ pub fn parse_blake_length(algo: AlgoKind, bit_length: BlakeLength<'_>) -> UResul
545595 return Err ( ChecksumError :: LengthNotMultipleOf8 . into ( ) ) ;
546596 }
547597
548- Ok ( n / 8 )
598+ Ok ( HashLength :: from_bits ( n ) )
549599}
550600
551601pub fn validate_sha2_sha3_length ( algo_name : AlgoKind , length : Option < usize > ) -> UResult < ShaLength > {
@@ -562,7 +612,7 @@ pub fn validate_sha2_sha3_length(algo_name: AlgoKind, length: Option<usize>) ->
562612 }
563613}
564614
565- pub fn sanitize_sha2_sha3_length_str ( algo_kind : AlgoKind , length : & str ) -> UResult < usize > {
615+ pub fn sanitize_sha2_sha3_length_str ( algo_kind : AlgoKind , length : & str ) -> UResult < HashLength > {
566616 // There is a difference in the errors sent when the length is not a number
567617 // vs. its an invalid number.
568618 //
@@ -580,7 +630,7 @@ pub fn sanitize_sha2_sha3_length_str(algo_kind: AlgoKind, length: &str) -> UResu
580630 } ;
581631
582632 if [ 224 , 256 , 384 , 512 ] . contains ( & len) {
583- Ok ( len)
633+ Ok ( HashLength :: from_bits ( len) )
584634 } else {
585635 show_error ! ( "{}" , ChecksumError :: InvalidLength ( length. into( ) ) ) ;
586636 Err ( ChecksumError :: InvalidLengthForSha ( algo_kind. to_uppercase ( ) . into ( ) ) . into ( ) )
@@ -664,17 +714,23 @@ mod tests {
664714 #[ test]
665715 fn test_calculate_blake2b_length ( ) {
666716 assert_eq ! (
667- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "0" ) ) . unwrap( ) ,
717+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "0" ) )
718+ . unwrap( )
719+ . as_bytes( ) ,
668720 Blake2b :: DEFAULT_BYTE_SIZE
669721 ) ;
670722 assert ! ( parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "10" ) ) . is_err( ) ) ;
671723 assert ! ( parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "520" ) ) . is_err( ) ) ;
672724 assert_eq ! (
673- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "512" ) ) . unwrap( ) ,
725+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "512" ) )
726+ . unwrap( )
727+ . as_bytes( ) ,
674728 Blake2b :: DEFAULT_BYTE_SIZE
675729 ) ;
676730 assert_eq ! (
677- parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "256" ) ) . unwrap( ) ,
731+ parse_blake_length( AlgoKind :: Blake2b , BlakeLength :: String ( "256" ) )
732+ . unwrap( )
733+ . as_bytes( ) ,
678734 32
679735 ) ;
680736 }
0 commit comments