bcrypt_wasm/
bcrypt.rs

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    // OrpheanBeholderScryDoubt
24    #[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}