1use blowfish::Blowfish;
2use byteorder::{ByteOrder, BE};
3
4fn setup(cost: u32, salt: &[u8], key: &[u8]) -> Blowfish {
5 assert!(cost < 32);
6 let mut state = Blowfish::bc_init_state();
7
8 state.salted_expand_key(salt, key);
9 for _ in 0..1u32 << cost {
10 state.bc_expand_key(key);
11 state.bc_expand_key(salt);
12 }
13
14 state
15}
16
17pub fn bcrypt(cost: u32, salt: &[u8], password: &[u8], output: &mut [u8]) {
18 assert!(salt.len() == 16);
19 assert!(!password.is_empty() && password.len() <= 72);
20 assert!(output.len() == 24);
21
22 let state = setup(cost, salt, password);
23 #[allow(clippy::unreadable_literal)]
25 let mut ctext = [
26 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, 0x6f756274,
27 ];
28 for i in 0..3 {
29 let i: usize = i * 2;
30 for _ in 0..64 {
31 let (l, r) = state.bc_encrypt(ctext[i], ctext[i + 1]);
32 ctext[i] = l;
33 ctext[i + 1] = r;
34 }
35 BE::write_u32(&mut output[i * 4..(i + 1) * 4], ctext[i]);
36 BE::write_u32(&mut output[(i + 1) * 4..(i + 2) * 4], ctext[i + 1]);
37 }
38}