33use crate :: { Error , Result } ;
44
55use blake2:: {
6- Blake2b512 , Blake2bVar ,
7- digest:: { self , Digest } ,
6+ Blake2b512 , Blake2bVarCore ,
7+ digest:: {
8+ Digest ,
9+ block_api:: { UpdateCore , VariableOutputCore } ,
10+ block_buffer:: LazyBuffer ,
11+ } ,
812} ;
913
10- use core:: convert:: TryFrom ;
11-
1214pub fn blake2b_long ( inputs : & [ & [ u8 ] ] , out : & mut [ u8 ] ) -> Result < ( ) > {
1315 if out. is_empty ( ) {
1416 return Err ( Error :: OutputTooShort ) ;
@@ -19,19 +21,17 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
1921 . map_err ( |_| Error :: OutputTooLong ) ?;
2022
2123 // Use blake2b directly if the output is small enough.
22- if out. len ( ) <= Blake2b512 :: output_size ( ) {
23- let mut digest = Blake2bVar :: new ( out. len ( ) ) . map_err ( |_| Error :: OutputTooLong ) ?;
24-
25- // Conflicting method name from `Digest` and `Update` traits
26- digest:: Update :: update ( & mut digest, & len_bytes) ;
24+ if let Ok ( mut hasher) = Blake2bVarCore :: new ( out. len ( ) ) {
25+ let mut buf = LazyBuffer :: new ( & len_bytes) ;
2726
2827 for input in inputs {
29- digest :: Update :: update ( & mut digest , input ) ;
28+ buf . digest_blocks ( input , |blocks| hasher . update_blocks ( blocks ) ) ;
3029 }
3130
32- digest
33- . finalize_variable ( out)
34- . map_err ( |_| Error :: OutputTooLong ) ?;
31+ let mut full_out = Default :: default ( ) ;
32+ hasher. finalize_variable_core ( & mut buf, & mut full_out) ;
33+ let out_src = & full_out[ ..out. len ( ) ] ;
34+ out. copy_from_slice ( out_src) ;
3535
3636 return Ok ( ( ) ) ;
3737 }
@@ -47,33 +47,28 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
4747 let mut last_output = digest. finalize ( ) ;
4848
4949 // Then we write the first 32 bytes of this hash to the output
50- out[ ..half_hash_len] . copy_from_slice ( & last_output[ ..half_hash_len] ) ;
50+ let ( first_chunk, mut out) = out. split_at_mut ( half_hash_len) ;
51+ first_chunk. copy_from_slice ( & last_output[ ..half_hash_len] ) ;
5152
5253 // Next, we write a number of 32 byte blocks to the output.
5354 // Each block is the first 32 bytes of the hash of the last block.
5455 // The very last block of the output is excluded, and has a variable
5556 // length in range [1, 32].
56- let mut counter = 0 ;
57- let out_len = out. len ( ) ;
58- for chunk in out[ half_hash_len..]
59- . chunks_exact_mut ( half_hash_len)
60- . take_while ( |_| {
61- counter += half_hash_len;
62- out_len - counter > 64
63- } )
64- {
57+ while out. len ( ) > 64 {
58+ let ( chunk, tail) = out. split_at_mut ( half_hash_len) ;
59+ out = tail;
6560 last_output = Blake2b512 :: digest ( last_output) ;
6661 chunk. copy_from_slice ( & last_output[ ..half_hash_len] ) ;
6762 }
6863
6964 // Calculate the last block with VarBlake2b.
70- let last_block_size = out. len ( ) - counter ;
71- let mut digest = Blake2bVar :: new ( last_block_size ) . map_err ( |_| Error :: OutputTooLong ) ? ;
72-
73- digest :: Update :: update ( & mut digest , & last_output ) ;
74- digest
75- . finalize_variable ( & mut out [ counter.. ] )
76- . expect ( "invalid Blake2bVar out length" ) ;
65+ let mut hasher = Blake2bVarCore :: new ( out. len ( ) )
66+ . expect ( "`out.len()` is guaranteed to be smaller or equal to 64" ) ;
67+ let mut buf = LazyBuffer :: new ( & last_output ) ;
68+ let mut full_out = Default :: default ( ) ;
69+ hasher . finalize_variable_core ( & mut buf , & mut full_out ) ;
70+ let out_src = & full_out [ ..out . len ( ) ] ;
71+ out . copy_from_slice ( out_src ) ;
7772
7873 Ok ( ( ) )
7974}
0 commit comments