33
33
#![ warn( missing_docs, rust_2018_idioms) ]
34
34
35
35
// TODO(tarcieri): heapless support
36
- #[ macro_use ]
36
+ #[ cfg ( feature = "alloc" ) ]
37
37
extern crate alloc;
38
38
39
- #[ cfg( feature = "std" ) ]
40
- extern crate std;
41
-
42
39
mod b64;
43
40
mod defs;
44
41
mod errors;
45
42
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
+ } ;
47
47
48
- use alloc:: string:: String ;
49
48
use md5:: { Digest , Md5 } ;
50
49
50
+ #[ cfg( feature = "subtle" ) ]
51
+ use crate :: errors:: CheckError ;
52
+
51
53
#[ cfg( feature = "simple" ) ]
52
54
use {
53
- crate :: {
54
- defs:: { SALT_MAX_LEN , TAB } ,
55
- errors:: CheckError ,
56
- } ,
57
- alloc:: string:: ToString ,
55
+ crate :: defs:: TAB ,
56
+ alloc:: string:: String ,
58
57
rand:: { distributions:: Distribution , thread_rng, Rng } ,
59
58
} ;
60
59
61
- #[ cfg( feature = "simple" ) ]
62
60
static MD5_SALT_PREFIX : & str = "$1$" ;
63
- #[ cfg( feature = "simple" ) ]
64
61
65
62
/// The MD5 crypt function returned as byte vector
66
63
///
@@ -160,10 +157,9 @@ pub fn md5_crypt(password: &[u8], salt: &[u8]) -> Result<[u8; BLOCK_SIZE], Crypt
160
157
/// # Returns
161
158
/// - `Ok(())` if calculation was successful
162
159
/// - `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 > {
164
161
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) )
167
163
}
168
164
169
165
/// Simple interface for generating a MD5 password hash.
@@ -191,7 +187,7 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
191
187
result. push_str ( MD5_SALT_PREFIX ) ;
192
188
result. push_str ( & salt) ;
193
189
result. push ( '$' ) ;
194
- let s = String :: from_utf8 ( b64:: encode_md5 ( & out) ) ?;
190
+ let s = String :: from_utf8 ( b64:: encode_md5 ( & out) . to_vec ( ) ) ?;
195
191
result. push_str ( & s) ;
196
192
Ok ( result)
197
193
}
@@ -206,40 +202,35 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
206
202
/// # Return
207
203
/// `OK(())` if password matches otherwise Err(CheckError) in case of invalid
208
204
/// format or password mismatch.
209
- #[ cfg( feature = "simple " ) ]
205
+ #[ cfg( feature = "subtle " ) ]
210
206
#[ cfg_attr( docsrs, doc( cfg( feature = "simple" ) ) ) ]
211
207
pub fn md5_check ( password : & str , hashed_value : & str ) -> Result < ( ) , CheckError > {
212
208
let mut iter = hashed_value. split ( '$' ) ;
213
209
214
210
// Check that there are no characters before the first "$"
215
211
if iter. next ( ) != Some ( "" ) {
216
- return Err ( CheckError :: InvalidFormat (
217
- "Should start with '$" . to_string ( ) ,
218
- ) ) ;
212
+ return Err ( CheckError :: InvalidFormat ( "Should start with '$" ) ) ;
219
213
}
220
214
221
215
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
+ ) ) ;
226
219
}
227
220
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
+ ) ) ?;
231
224
232
225
let salt = next;
233
226
234
227
let hash = iter
235
228
. 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" ) ) ?;
237
230
238
231
// Make sure there is no trailing data after the final "$"
239
232
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" ) ) ;
243
234
}
244
235
245
236
let output = md5_crypt ( password. as_bytes ( ) , salt. as_bytes ( ) ) . map_err ( CheckError :: Crypt ) ?;
0 commit comments