1010pub use mcf:: { PasswordHash , PasswordHashRef } ;
1111
1212use crate :: { Algorithm , Params , Pbkdf2 , pbkdf2_hmac} ;
13- use alloc:: { string:: String , vec:: Vec } ;
1413use mcf:: Base64 ;
1514use password_hash:: {
1615 CustomizedPasswordHasher , Error , PasswordHasher , PasswordVerifier , Result , Version ,
@@ -55,19 +54,11 @@ impl CustomizedPasswordHasher<PasswordHash> for Pbkdf2 {
5554 f ( password, salt, params. rounds ( ) , out) ;
5655
5756 let mut mcf_hash = PasswordHash :: from_id ( algorithm. to_str ( ) ) . expect ( "should have valid ID" ) ;
58-
5957 mcf_hash
6058 . push_displayable ( params)
6159 . map_err ( |_| Error :: EncodingInvalid ) ?;
62-
63- mcf_hash
64- . push_str ( & base64_encode ( salt) )
65- . map_err ( |_| Error :: EncodingInvalid ) ?;
66-
67- mcf_hash
68- . push_str ( & base64_encode ( out) )
69- . map_err ( |_| Error :: EncodingInvalid ) ?;
70-
60+ mcf_hash. push_base64 ( salt, Base64 :: Pbkdf2 ) ;
61+ mcf_hash. push_base64 ( out, Base64 :: Pbkdf2 ) ;
7162 Ok ( mcf_hash)
7263 }
7364}
@@ -97,13 +88,17 @@ impl PasswordVerifier<PasswordHashRef> for Pbkdf2 {
9788 next = fields. next ( ) . ok_or ( Error :: EncodingInvalid ) ?;
9889 }
9990
100- let salt = base64_decode ( next. as_str ( ) ) ?;
91+ // decode salt
92+ let salt = next
93+ . decode_base64 ( Base64 :: Pbkdf2 )
94+ . map_err ( |_| Error :: EncodingInvalid ) ?;
10195
10296 // decode expected password hash
10397 let expected = fields
10498 . next ( )
105- . ok_or ( Error :: EncodingInvalid )
106- . and_then ( |field| base64_decode ( field. as_str ( ) ) ) ?;
99+ . ok_or ( Error :: EncodingInvalid ) ?
100+ . decode_base64 ( Base64 :: Pbkdf2 )
101+ . map_err ( |_| Error :: EncodingInvalid ) ?;
107102
108103 // should be the last field
109104 if fields. next ( ) . is_some ( ) {
@@ -136,25 +131,12 @@ impl PasswordVerifier<PasswordHashRef> for Pbkdf2 {
136131 }
137132}
138133
139- // Base64 support: PBKDF2 uses a variant of standard unpadded Base64 which substitutes the `+`
140- // character for `.` and this is a distinct encoding from the bcrypt and crypt Base64 variants.
141-
142- fn base64_decode ( base64 : & str ) -> Result < Vec < u8 > > {
143- Base64 :: B64
144- . decode_vec ( & base64. replace ( '.' , "+" ) )
145- . map_err ( |_| Error :: EncodingInvalid )
146- }
147-
148- fn base64_encode ( bytes : & [ u8 ] ) -> String {
149- Base64 :: B64 . encode_string ( bytes) . replace ( '+' , "." )
150- }
151-
152- // TODO(tarcieri): tests for SHA-1 and SHA-512
134+ // TODO(tarcieri): tests for SHA-1
153135#[ cfg( test) ]
154136mod tests {
155- use super :: { Error , base64_decode } ;
137+ use super :: Error ;
156138 use crate :: { Params , Pbkdf2 } ;
157- use mcf:: PasswordHash ;
139+ use mcf:: { Base64 , PasswordHash } ;
158140 use password_hash:: { CustomizedPasswordHasher , PasswordVerifier } ;
159141
160142 // Example adapted from:
@@ -167,7 +149,7 @@ mod tests {
167149 const EXAMPLE_HASH : & str =
168150 "$pbkdf2-sha256$8000$XAuBMIYQQogxRg$tRRlz8hYn63B9LYiCd6PRo6FMiunY9ozmMMI3srxeRE" ;
169151
170- let salt = base64_decode ( EXAMPLE_SALT ) . unwrap ( ) ;
152+ let salt = Base64 :: Pbkdf2 . decode_vec ( EXAMPLE_SALT ) . unwrap ( ) ;
171153 let params = Params :: new ( EXAMPLE_ROUNDS ) . unwrap ( ) ;
172154
173155 let actual_hash: PasswordHash = Pbkdf2 :: SHA256
@@ -197,7 +179,7 @@ mod tests {
197179 const EXAMPLE_SALT : & str = "O4fwPmdMyRmDUIrx/h9jTA" ;
198180 const EXAMPLE_HASH : & str = "$pbkdf2-sha512$25000$O4fwPmdMyRmDUIrx/h9jTA$Xlp267ZwEbG4aOpN3Bve/ATo3rFA7WH8iMdS16Xbe9rc6P5welk1yiXEMPy7.BFp0qsncipHumaW1trCWVvq/A" ;
199181
200- let salt = base64_decode ( EXAMPLE_SALT ) . unwrap ( ) ;
182+ let salt = Base64 :: Pbkdf2 . decode_vec ( EXAMPLE_SALT ) . unwrap ( ) ;
201183 let params = Params :: new_with_output_len ( EXAMPLE_ROUNDS , 64 ) . unwrap ( ) ;
202184
203185 let actual_hash: PasswordHash = Pbkdf2 :: SHA512
0 commit comments