2626//! assert!(firebase_scrypt.verify_password(password, salt, password_hash).unwrap())
2727//! ```
2828
29- use aes:: { Aes256 } ;
30- use aes:: cipher:: { KeyIvInit , StreamCipher } ;
29+ use crate :: errors:: { DerivedKeyError , EncryptError , GenerateHashError } ;
30+ use aes:: {
31+ cipher:: { KeyIvInit , StreamCipher } ,
32+ Aes256 ,
33+ } ;
3134use constant_time_eq:: constant_time_eq;
32- use ctr:: { Ctr128BE } ;
35+ use ctr:: Ctr128BE ;
3336use scrypt:: Params ;
34- use crate :: errors:: { DerivedKeyError , EncryptError , GenerateHashError } ;
3537
3638pub mod errors;
3739#[ cfg( feature = "simple" ) ]
@@ -42,6 +44,10 @@ pub use simple::FirebaseScrypt;
4244
4345const IV : [ u8 ; 16 ] = * b"\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 " ;
4446
47+ fn clean ( a : & str ) -> String {
48+ a. replace ( "-" , "+" ) . replace ( "_" , "/" )
49+ }
50+
4551fn generate_derived_key < ' a > (
4652 password : & ' a str ,
4753 salt : & ' a str ,
@@ -61,12 +67,7 @@ fn generate_derived_key<'a>(
6167 let params = Params :: new ( log2_n as u8 , rounds, p) ?;
6268
6369 let mut result = [ 0u8 ; 64 ] ;
64- scrypt:: scrypt (
65- password,
66- salt. as_slice ( ) ,
67- & params,
68- & mut result
69- ) ?;
70+ scrypt:: scrypt ( password, salt. as_slice ( ) , & params, & mut result) ?;
7071
7172 Ok ( result)
7273}
@@ -75,8 +76,7 @@ fn encrypt(signer_key: &[u8], key: [u8; 32]) -> Result<Vec<u8>, EncryptError> {
7576 let mut cipher = Ctr128BE :: < Aes256 > :: new ( & key. into ( ) , & IV . into ( ) ) ;
7677
7778 let mut buffer = vec ! [ 0u8 ; signer_key. len( ) ] ;
78- cipher
79- . apply_keystream_b2b ( signer_key, & mut buffer) ?;
79+ cipher. apply_keystream_b2b ( signer_key, & mut buffer) ?;
8080
8181 Ok ( buffer)
8282}
@@ -120,9 +120,13 @@ pub fn verify_password(
120120 rounds : u32 ,
121121 mem_cost : u32 ,
122122) -> Result < bool , GenerateHashError > {
123- let password_hash = generate_raw_hash ( password, salt, salt_separator, signer_key, rounds, mem_cost) ?;
123+ let password_hash =
124+ generate_raw_hash ( password, salt, salt_separator, signer_key, rounds, mem_cost) ?;
124125
125- Ok ( constant_time_eq ( password_hash. as_slice ( ) , base64:: decode ( known_hash) ?. as_slice ( ) ) )
126+ Ok ( constant_time_eq (
127+ password_hash. as_slice ( ) ,
128+ base64:: decode ( clean ( known_hash) ) ?. as_slice ( ) ,
129+ ) )
126130}
127131
128132/// Generates a hash in the form of a [`Vec<u8>`]
@@ -164,7 +168,8 @@ pub fn generate_raw_hash(
164168 rounds : u32 ,
165169 mem_cost : u32 ,
166170) -> Result < Vec < u8 > , GenerateHashError > {
167- let derived_key = generate_derived_key ( password, salt, salt_separator, rounds, mem_cost) ?;
171+ let derived_key =
172+ generate_derived_key ( password, & clean ( salt) , salt_separator, rounds, mem_cost) ?;
168173 let signer_key = base64:: decode ( signer_key) ?;
169174
170175 let result = encrypt ( signer_key. as_slice ( ) , derived_key[ ..32 ] . try_into ( ) . unwrap ( ) ) ?;
@@ -174,13 +179,15 @@ pub fn generate_raw_hash(
174179#[ cfg( test) ]
175180mod tests {
176181 const SALT_SEPARATOR : & str = "Bw==" ;
177- const SIGNER_KEY : & str = "jxspr8Ki0RYycVU8zykbdLGjFQ3McFUH0uiiTvC8pVMXAn210wjLNmdZJzxUECKbm0QsEmYUSDzZvpjeJ9WmXA==" ;
182+ const SIGNER_KEY : & str =
183+ "jxspr8Ki0RYycVU8zykbdLGjFQ3McFUH0uiiTvC8pVMXAn210wjLNmdZJzxUECKbm0QsEmYUSDzZvpjeJ9WmXA==" ;
178184 const ROUNDS : u32 = 8 ;
179185 const MEM_COST : u32 = 14 ;
180186
181187 const PASSWORD : & str = "user1password" ;
182188 const SALT : & str = "42xEC+ixf3L2lw==" ;
183- const PASSWORD_HASH : & str ="lSrfV15cpx95/sZS2W9c9Kp6i/LVgQNDNC/qzrCnh1SAyZvqmZqAjTdn3aoItz+VHjoZilo78198JAdRuid5lQ==" ;
189+ const PASSWORD_HASH : & str =
190+ "lSrfV15cpx95/sZS2W9c9Kp6i/LVgQNDNC/qzrCnh1SAyZvqmZqAjTdn3aoItz+VHjoZilo78198JAdRuid5lQ==" ;
184191
185192 use super :: * ;
186193
@@ -194,27 +201,30 @@ mod tests {
194201 SIGNER_KEY ,
195202 ROUNDS ,
196203 MEM_COST
197- ) . unwrap( ) )
204+ )
205+ . unwrap( ) )
198206 }
199207
200208 #[ test]
201209 fn generate_hash_works ( ) {
202- assert_eq ! ( base64:: encode( generate_raw_hash(
203- PASSWORD ,
204- SALT ,
205- SALT_SEPARATOR ,
206- SIGNER_KEY ,
207- ROUNDS ,
208- MEM_COST ,
209- ) . unwrap( ) ) , PASSWORD_HASH )
210+ assert_eq ! (
211+ base64:: encode(
212+ generate_raw_hash( PASSWORD , SALT , SALT_SEPARATOR , SIGNER_KEY , ROUNDS , MEM_COST , )
213+ . unwrap( )
214+ ) ,
215+ PASSWORD_HASH
216+ )
210217 }
211218
212219 #[ test]
213220 fn encrypt_works ( ) {
214221 let param_1 = b"randomrandomrandomrandomrandomrandomrandom" ;
215222 let param_2 = b"12345678901234567890123456789012" ;
216223
217- assert_eq ! ( hex:: encode( encrypt( param_1, * param_2) . unwrap( ) ) , "09f509fa3d09cde568f80709416681e4ed5d9677ca8b4807a932869ba3fd057be3606c2940877850ed96" ) ;
224+ assert_eq ! (
225+ hex:: encode( encrypt( param_1, * param_2) . unwrap( ) ) ,
226+ "09f509fa3d09cde568f80709416681e4ed5d9677ca8b4807a932869ba3fd057be3606c2940877850ed96"
227+ ) ;
218228 }
219229
220230 #[ test]
0 commit comments