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