3333#![ warn( missing_docs,  rust_2018_idioms) ]  
3434
3535// TODO(tarcieri): heapless support 
36- #[ macro_use ]  
36+ #[ cfg ( feature =  "alloc" ) ]  
3737extern  crate  alloc; 
3838
39- #[ cfg( feature = "std" ) ]  
40- extern  crate  std; 
41- 
4239mod  b64; 
4340mod  defs; 
4441mod  errors; 
4542
46- pub  use  crate :: { defs:: BLOCK_SIZE ,  errors:: CryptError } ; 
43+ pub  use  crate :: { 
44+     defs:: { BLOCK_SIZE ,  PW_SIZE_MD5 ,  SALT_MAX_LEN } , 
45+     errors:: CryptError , 
46+ } ; 
4747
48- use  alloc:: string:: String ; 
4948use  md5:: { Digest ,  Md5 } ; 
5049
50+ #[ cfg( feature = "subtle" ) ]  
51+ use  crate :: errors:: CheckError ; 
52+ 
5153#[ cfg( feature = "simple" ) ]  
5254use  { 
53-     crate :: { 
54-         defs:: { SALT_MAX_LEN ,  TAB } , 
55-         errors:: CheckError , 
56-     } , 
57-     alloc:: string:: ToString , 
55+     crate :: defs:: TAB , 
56+     alloc:: string:: String , 
5857    rand:: { distributions:: Distribution ,  thread_rng,  Rng } , 
5958} ; 
6059
61- #[ cfg( feature = "simple" ) ]  
6260static  MD5_SALT_PREFIX :  & str  = "$1$" ; 
63- #[ cfg( feature = "simple" ) ]  
6461
6562/// The MD5 crypt function returned as byte vector 
6663/// 
@@ -160,10 +157,9 @@ pub fn md5_crypt(password: &[u8], salt: &[u8]) -> Result<[u8; BLOCK_SIZE], Crypt
160157/// # Returns 
161158/// - `Ok(())` if calculation was successful 
162159/// - `Err(errors::CryptError)` otherwise 
163- pub  fn  md5_crypt_b64 ( password :  & [ u8 ] ,  salt :  & [ u8 ] )  -> Result < String ,  CryptError >  { 
160+ pub  fn  md5_crypt_b64 ( password :  & [ u8 ] ,  salt :  & [ u8 ] )  -> Result < [ u8 ;   PW_SIZE_MD5 ] ,  CryptError >  { 
164161    let  output = md5_crypt ( password,  salt) ?; 
165-     let  r = String :: from_utf8 ( b64:: encode_md5 ( & output) ) ?; 
166-     Ok ( r) 
162+     Ok ( b64:: encode_md5 ( & output) ) 
167163} 
168164
169165/// Simple interface for generating a MD5 password hash. 
@@ -191,7 +187,7 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
191187    result. push_str ( MD5_SALT_PREFIX ) ; 
192188    result. push_str ( & salt) ; 
193189    result. push ( '$' ) ; 
194-     let  s = String :: from_utf8 ( b64:: encode_md5 ( & out) ) ?; 
190+     let  s = String :: from_utf8 ( b64:: encode_md5 ( & out) . to_vec ( ) ) ?; 
195191    result. push_str ( & s) ; 
196192    Ok ( result) 
197193} 
@@ -206,40 +202,35 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
206202/// # Return 
207203/// `OK(())` if password matches otherwise Err(CheckError) in case of invalid 
208204/// format or password mismatch. 
209- #[ cfg( feature = "simple " ) ]  
205+ #[ cfg( feature = "subtle " ) ]  
210206#[ cfg_attr( docsrs,  doc( cfg( feature = "simple" ) ) ) ]  
211207pub  fn  md5_check ( password :  & str ,  hashed_value :  & str )  -> Result < ( ) ,  CheckError >  { 
212208    let  mut  iter = hashed_value. split ( '$' ) ; 
213209
214210    // Check that there are no characters before the first "$" 
215211    if  iter. next ( )  != Some ( "" )  { 
216-         return  Err ( CheckError :: InvalidFormat ( 
217-             "Should start with '$" . to_string ( ) , 
218-         ) ) ; 
212+         return  Err ( CheckError :: InvalidFormat ( "Should start with '$" ) ) ; 
219213    } 
220214
221215    if  iter. next ( )  != Some ( "1" )  { 
222-         return  Err ( CheckError :: InvalidFormat ( format ! ( 
223-             "does not contain MD5 identifier: '{}'" , 
224-             MD5_SALT_PREFIX 
225-         ) ) ) ; 
216+         return  Err ( CheckError :: InvalidFormat ( 
217+             "does not contain MD5 identifier: '$1$'" , 
218+         ) ) ; 
226219    } 
227220
228-     let  next = iter. next ( ) . ok_or_else ( ||  { 
229-         CheckError :: InvalidFormat ( "Does not contain a salt or hash string" . to_string ( ) ) 
230-     } ) ?; 
221+     let  next = iter. next ( ) . ok_or ( CheckError :: InvalidFormat ( 
222+         "Does not contain a salt or hash string" , 
223+     ) ) ?; 
231224
232225    let  salt = next; 
233226
234227    let  hash = iter
235228        . next ( ) 
236-         . ok_or_else ( ||  CheckError :: InvalidFormat ( "Does not contain a hash string" . to_string ( ) ) ) ?; 
229+         . ok_or ( CheckError :: InvalidFormat ( "Does not contain a hash string" ) ) ?; 
237230
238231    // Make sure there is no trailing data after the final "$" 
239232    if  iter. next ( ) . is_some ( )  { 
240-         return  Err ( CheckError :: InvalidFormat ( 
241-             "Trailing characters present" . to_string ( ) , 
242-         ) ) ; 
233+         return  Err ( CheckError :: InvalidFormat ( "Trailing characters present" ) ) ; 
243234    } 
244235
245236    let  output = md5_crypt ( password. as_bytes ( ) ,  salt. as_bytes ( ) ) . map_err ( CheckError :: Crypt ) ?; 
0 commit comments