Skip to content

Commit d240fb4

Browse files
committed
Merge pull request #72 from ebfe/bcrypt_pbkdf
Add bcrypt_pbkdf
2 parents 09c7ac3 + b54f223 commit d240fb4

File tree

5 files changed

+322
-23
lines changed

5 files changed

+322
-23
lines changed

src/rust-crypto/bcrypt.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@
66

77
use blowfish::Blowfish;
88
use std::iter::{range, range_step};
9-
use cryptoutil::{read_u32v_be, write_u32_be};
9+
use cryptoutil::{write_u32_be};
1010

1111
fn setup(cost: uint, salt: &[u8], key: &[u8]) -> Blowfish {
1212
let mut state = Blowfish::init_state();
1313

14-
let mut salt_ = [0u32, ..4];
15-
read_u32v_be(salt_.as_mut_slice(), salt.as_slice());
16-
17-
state.salted_expand_key(salt_, key);
14+
state.salted_expand_key(salt, key);
1815
for _ in range(0u, 1u << cost) {
1916
state.expand_key(key);
2017
state.expand_key(salt);
@@ -148,3 +145,19 @@ mod test {
148145
}
149146
}
150147
}
148+
149+
#[cfg(test)]
150+
mod bench {
151+
use test::Bencher;
152+
use bcrypt::bcrypt;
153+
154+
#[bench]
155+
pub fn bcrypt_16_5(bh: & mut Bencher) {
156+
let pass = [0u8, ..16];
157+
let salt = [0u8, ..16];
158+
let mut out = [0u8, ..24];
159+
bh.iter( || {
160+
bcrypt(5, salt, pass, out);
161+
});
162+
}
163+
}

src/rust-crypto/bcrypt_pbkdf.rs

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4+
// option. This file may not be copied, modified, or distributed
5+
// except according to those terms.
6+
7+
use std::iter::range_step;
8+
use blowfish::Blowfish;
9+
use cryptoutil::{read_u32v_be, write_u32_be, write_u32_le};
10+
use sha2::Sha512;
11+
use digest::Digest;
12+
13+
fn bcrypt_hash(hpass: &[u8], hsalt: &[u8], output: &mut [u8, ..32]) {
14+
let mut bf = Blowfish::init_state();
15+
bf.salted_expand_key(hsalt, hpass);
16+
17+
for _ in range(0, 64) {
18+
bf.expand_key(hsalt);
19+
bf.expand_key(hpass);
20+
}
21+
22+
let mut buf = [0u32, ..8];
23+
read_u32v_be(buf, bytes!("OxychromaticBlowfishSwatDynamite"));
24+
25+
for i in range_step(0u, 8, 2) {
26+
for _ in range(0, 64) {
27+
let (l, r) = bf.encrypt(buf[i], buf[i+1]);
28+
buf[i] = l;
29+
buf[i+1] = r;
30+
}
31+
}
32+
33+
for i in range(0u, 8) {
34+
write_u32_le(output.mut_slice(i*4, (i+1)*4), buf[i]);
35+
}
36+
}
37+
38+
pub fn bcrypt_pbkdf(password: &[u8], salt: &[u8], rounds: uint, output: &mut [u8]) {
39+
let mut hpass = [0u8, ..64];
40+
41+
assert!(password.len() > 0);
42+
assert!(salt.len() > 0);
43+
assert!(rounds > 0);
44+
assert!(output.len() > 0);
45+
assert!(output.len() <= 1024);
46+
47+
let nblocks = (output.len() + 31) / 32;
48+
49+
let mut h = Sha512::new();
50+
h.input(password);
51+
h.result(hpass.as_mut_slice());
52+
53+
for block in range(1u, (nblocks+1)) {
54+
let mut count = [0u8, ..4];
55+
let mut hsalt = [0u8, ..64];
56+
let mut out = [0u8, ..32];
57+
write_u32_be(count.as_mut_slice(), block as u32);
58+
59+
h.reset();
60+
h.input(salt);
61+
h.input(count);
62+
h.result(hsalt);
63+
64+
bcrypt_hash(hpass, hsalt, &mut out);
65+
let mut tmp = out;
66+
67+
for _ in range(1, rounds) {
68+
h.reset();
69+
h.input(tmp);
70+
h.result(hsalt);
71+
72+
bcrypt_hash(hpass, hsalt, &mut tmp);
73+
for i in range(0, out.len()) {
74+
out[i] ^= tmp[i];
75+
}
76+
77+
for i in range(0, out.len()) {
78+
let idx = i * nblocks + (block-1);
79+
if idx < output.len() {
80+
output[idx] = out[i];
81+
}
82+
}
83+
}
84+
}
85+
}
86+
87+
#[cfg(test)]
88+
mod test {
89+
use bcrypt_pbkdf::{bcrypt_pbkdf, bcrypt_hash};
90+
91+
#[test]
92+
fn test_bcrypt_hash() {
93+
struct Test {
94+
hpass: [u8, ..64],
95+
hsalt: [u8, ..64],
96+
out: [u8, ..32],
97+
}
98+
99+
let tests = vec!(
100+
Test{
101+
hpass: [
102+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
106+
hsalt: [
107+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
111+
out: [
112+
0x46, 0x02, 0x86, 0xe9, 0x72, 0xfa, 0x83, 0x3f, 0x8b, 0x12, 0x83, 0xad, 0x8f, 0xa9, 0x19, 0xfa,
113+
0x29, 0xbd, 0xe2, 0x0e, 0x23, 0x32, 0x9e, 0x77, 0x4d, 0x84, 0x22, 0xba, 0xc0, 0xa7, 0x92, 0x6c, ],
114+
}, Test{
115+
hpass: [
116+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
117+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
118+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
119+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f ],
120+
hsalt: [
121+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
125+
out: [
126+
0xb0, 0xb2, 0x29, 0xdb, 0xc6, 0xba, 0xde, 0xf0, 0xe1, 0xda, 0x25, 0x27, 0x47, 0x4a, 0x8b, 0x28,
127+
0x88, 0x8f, 0x8b, 0x06, 0x14, 0x76, 0xfe, 0x80, 0xc3, 0x22, 0x56, 0xe1, 0x14, 0x2d, 0xd0, 0x0d ],
128+
}, Test{
129+
hpass: [
130+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
134+
hsalt: [
135+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
136+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
137+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
138+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f ],
139+
out: [
140+
0xb6, 0x2b, 0x4e, 0x36, 0x7d, 0x31, 0x57, 0xf5, 0xc3, 0x1e, 0x4d, 0x2c, 0xba, 0xfb, 0x29, 0x31,
141+
0x49, 0x4d, 0x9d, 0x3b, 0xdd, 0x17, 0x1d, 0x55, 0xcf, 0x79, 0x9f, 0xa4, 0x41, 0x60, 0x42, 0xe2 ],
142+
}, Test{
143+
hpass: [
144+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
145+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
146+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
147+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f ],
148+
hsalt: [
149+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
150+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
151+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
152+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f ],
153+
out: [
154+
0xc6, 0xa9, 0x5f, 0xe6, 0x41, 0x31, 0x15, 0xfb, 0x57, 0xe9, 0x9f, 0x75, 0x74, 0x98, 0xe8, 0x5d,
155+
0xa3, 0xc6, 0xe1, 0xdf, 0x0c, 0x3c, 0x93, 0xaa, 0x97, 0x5c, 0x54, 0x8a, 0x34, 0x43, 0x26, 0xf8 ],
156+
},
157+
);
158+
159+
for t in tests.iter() {
160+
let mut out = [0u8, ..32];
161+
bcrypt_hash(t.hpass, t.hsalt, &mut out);
162+
assert_eq!(out.as_slice(), t.out.as_slice());
163+
}
164+
}
165+
166+
#[test]
167+
fn test_openbsd_vectors() {
168+
struct Test{
169+
password: &'static [u8],
170+
salt: &'static [u8],
171+
rounds: uint,
172+
out: &'static [u8],
173+
}
174+
175+
let tests = vec!(
176+
Test{
177+
password: bytes!("password"),
178+
salt: bytes!("salt"),
179+
rounds: 4,
180+
out: bytes!(
181+
0x5b, 0xbf, 0x0c, 0xc2, 0x93, 0x58, 0x7f, 0x1c, 0x36, 0x35, 0x55, 0x5c, 0x27, 0x79, 0x65, 0x98,
182+
0xd4, 0x7e, 0x57, 0x90, 0x71, 0xbf, 0x42, 0x7e, 0x9d, 0x8f, 0xbe, 0x84, 0x2a, 0xba, 0x34, 0xd9),
183+
}, Test{
184+
password: bytes!("password"),
185+
salt: bytes!{0},
186+
rounds: 4,
187+
out: bytes!(0xc1, 0x2b, 0x56, 0x62, 0x35, 0xee, 0xe0, 0x4c, 0x21, 0x25, 0x98, 0x97, 0x0a, 0x57, 0x9a, 0x67),
188+
}, Test{
189+
password: bytes!{0},
190+
salt: bytes!("salt"),
191+
rounds: 4,
192+
out: bytes!(0x60, 0x51, 0xbe, 0x18, 0xc2, 0xf4, 0xf8, 0x2c, 0xbf, 0x0e, 0xfe, 0xe5, 0x47, 0x1b, 0x4b, 0xb9),
193+
}, Test{
194+
password: bytes!("password\x00"),
195+
salt: bytes!("salt\x00"),
196+
rounds: 4,
197+
out: bytes!(
198+
0x74, 0x10, 0xe4, 0x4c, 0xf4, 0xfa, 0x07, 0xbf, 0xaa, 0xc8, 0xa9, 0x28, 0xb1, 0x72, 0x7f, 0xac,
199+
0x00, 0x13, 0x75, 0xe7, 0xbf, 0x73, 0x84, 0x37, 0x0f, 0x48, 0xef, 0xd1, 0x21, 0x74, 0x30, 0x50),
200+
}, Test{
201+
password: bytes!("pass\x00wor"),
202+
salt: bytes!("sa\x00l"),
203+
rounds: 4,
204+
out: bytes!(0xc2, 0xbf, 0xfd, 0x9d, 0xb3, 0x8f, 0x65, 0x69, 0xef, 0xef, 0x43, 0x72, 0xf4, 0xde, 0x83, 0xc0),
205+
}, Test{
206+
password: bytes!("pass\x00word"),
207+
salt: bytes!("sa\x00lt"),
208+
rounds: 4,
209+
out: bytes!(0x4b, 0xa4, 0xac, 0x39, 0x25, 0xc0, 0xe8, 0xd7, 0xf0, 0xcd, 0xb6, 0xbb, 0x16, 0x84, 0xa5, 0x6f),
210+
}, Test{
211+
password: bytes!("password"),
212+
salt: bytes!("salt"),
213+
rounds: 8,
214+
out: bytes!(
215+
0xe1, 0x36, 0x7e, 0xc5, 0x15, 0x1a, 0x33, 0xfa, 0xac, 0x4c, 0xc1, 0xc1, 0x44, 0xcd, 0x23, 0xfa,
216+
0x15, 0xd5, 0x54, 0x84, 0x93, 0xec, 0xc9, 0x9b, 0x9b, 0x5d, 0x9c, 0x0d, 0x3b, 0x27, 0xbe, 0xc7,
217+
0x62, 0x27, 0xea, 0x66, 0x08, 0x8b, 0x84, 0x9b, 0x20, 0xab, 0x7a, 0xa4, 0x78, 0x01, 0x02, 0x46,
218+
0xe7, 0x4b, 0xba, 0x51, 0x72, 0x3f, 0xef, 0xa9, 0xf9, 0x47, 0x4d, 0x65, 0x08, 0x84, 0x5e, 0x8d),
219+
}, Test{
220+
password: bytes!("password"),
221+
salt: bytes!("salt"),
222+
rounds: 42,
223+
out: bytes!(0x83, 0x3c, 0xf0, 0xdc, 0xf5, 0x6d, 0xb6, 0x56, 0x08, 0xe8, 0xf0, 0xdc, 0x0c, 0xe8, 0x82, 0xbd),
224+
}, Test{
225+
password: bytes!("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."),
226+
salt: bytes!("salis\x00"),
227+
rounds: 8,
228+
out: bytes!(0x10, 0x97, 0x8b, 0x07, 0x25, 0x3d, 0xf5, 0x7f, 0x71, 0xa1, 0x62, 0xeb, 0x0e, 0x8a, 0xd3, 0x0a),
229+
}, Test{
230+
password: bytes!(0x0d, 0xb3, 0xac, 0x94, 0xb3, 0xee, 0x53, 0x28, 0x4f, 0x4a, 0x22, 0x89, 0x3b, 0x3c, 0x24, 0xae),
231+
salt: bytes!(0x3a, 0x62, 0xf0, 0xf0, 0xdb, 0xce, 0xf8, 0x23, 0xcf, 0xcc, 0x85, 0x48, 0x56, 0xea, 0x10, 0x28),
232+
rounds: 8,
233+
out: bytes!(0x20, 0x44, 0x38, 0x17, 0x5e, 0xee, 0x7c, 0xe1, 0x36, 0xc9, 0x1b, 0x49, 0xa6, 0x79, 0x23, 0xff),
234+
}, Test{
235+
password: bytes!(0x0d, 0xb3, 0xac, 0x94, 0xb3, 0xee, 0x53, 0x28, 0x4f, 0x4a, 0x22, 0x89, 0x3b, 0x3c, 0x24, 0xae),
236+
salt: bytes!(0x3a, 0x62, 0xf0, 0xf0, 0xdb, 0xce, 0xf8, 0x23, 0xcf, 0xcc, 0x85, 0x48, 0x56, 0xea, 0x10, 0x28),
237+
rounds: 8,
238+
out: bytes!(
239+
0x20, 0x54, 0xb9, 0xff, 0xf3, 0x4e, 0x37, 0x21, 0x44, 0x03, 0x34, 0x74, 0x68, 0x28, 0xe9, 0xed,
240+
0x38, 0xde, 0x4b, 0x72, 0xe0, 0xa6, 0x9a, 0xdc, 0x17, 0x0a, 0x13, 0xb5, 0xe8, 0xd6, 0x46, 0x38,
241+
0x5e, 0xa4, 0x03, 0x4a, 0xe6, 0xd2, 0x66, 0x00, 0xee, 0x23, 0x32, 0xc5, 0xed, 0x40, 0xad, 0x55,
242+
0x7c, 0x86, 0xe3, 0x40, 0x3f, 0xbb, 0x30, 0xe4, 0xe1, 0xdc, 0x1a, 0xe0, 0x6b, 0x99, 0xa0, 0x71,
243+
0x36, 0x8f, 0x51, 0x8d, 0x2c, 0x42, 0x66, 0x51, 0xc9, 0xe7, 0xe4, 0x37, 0xfd, 0x6c, 0x91, 0x5b,
244+
0x1b, 0xbf, 0xc3, 0xa4, 0xce, 0xa7, 0x14, 0x91, 0x49, 0x0e, 0xa7, 0xaf, 0xb7, 0xdd, 0x02, 0x90,
245+
0xa6, 0x78, 0xa4, 0xf4, 0x41, 0x12, 0x8d, 0xb1, 0x79, 0x2e, 0xab, 0x27, 0x76, 0xb2, 0x1e, 0xb4,
246+
0x23, 0x8e, 0x07, 0x15, 0xad, 0xd4, 0x12, 0x7d, 0xff, 0x44, 0xe4, 0xb3, 0xe4, 0xcc, 0x4c, 0x4f,
247+
0x99, 0x70, 0x08, 0x3f, 0x3f, 0x74, 0xbd, 0x69, 0x88, 0x73, 0xfd, 0xf6, 0x48, 0x84, 0x4f, 0x75,
248+
0xc9, 0xbf, 0x7f, 0x9e, 0x0c, 0x4d, 0x9e, 0x5d, 0x89, 0xa7, 0x78, 0x39, 0x97, 0x49, 0x29, 0x66,
249+
0x61, 0x67, 0x07, 0x61, 0x1c, 0xb9, 0x01, 0xde, 0x31, 0xa1, 0x97, 0x26, 0xb6, 0xe0, 0x8c, 0x3a,
250+
0x80, 0x01, 0x66, 0x1f, 0x2d, 0x5c, 0x9d, 0xcc, 0x33, 0xb4, 0xaa, 0x07, 0x2f, 0x90, 0xdd, 0x0b,
251+
0x3f, 0x54, 0x8d, 0x5e, 0xeb, 0xa4, 0x21, 0x13, 0x97, 0xe2, 0xfb, 0x06, 0x2e, 0x52, 0x6e, 0x1d,
252+
0x68, 0xf4, 0x6a, 0x4c, 0xe2, 0x56, 0x18, 0x5b, 0x4b, 0xad, 0xc2, 0x68, 0x5f, 0xbe, 0x78, 0xe1,
253+
0xc7, 0x65, 0x7b, 0x59, 0xf8, 0x3a, 0xb9, 0xab, 0x80, 0xcf, 0x93, 0x18, 0xd6, 0xad, 0xd1, 0xf5,
254+
0x93, 0x3f, 0x12, 0xd6, 0xf3, 0x61, 0x82, 0xc8, 0xe8, 0x11, 0x5f, 0x68, 0x03, 0x0a, 0x12, 0x44),
255+
},
256+
);
257+
258+
for t in tests.iter() {
259+
let mut out = Vec::from_elem(t.out.len(), 0u8);
260+
bcrypt_pbkdf(t.password, t.salt, t.rounds, out.as_mut_slice());
261+
assert_eq!(out.as_slice(), t.out.as_slice());
262+
}
263+
}
264+
}
265+
266+
#[cfg(test)]
267+
mod bench {
268+
use test::Bencher;
269+
use bcrypt_pbkdf::bcrypt_pbkdf;
270+
271+
#[bench]
272+
fn bench_bcrypt_pbkdf_5_32(b: &mut Bencher) {
273+
let pass = [0u8, ..16];
274+
let salt = [0u8, ..16];
275+
let mut out = [0u8, ..32];
276+
277+
b.iter(|| {
278+
bcrypt_pbkdf(pass, salt, 5, out.as_mut_slice());
279+
});
280+
}
281+
}

src/rust-crypto/blowfish.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ pub struct Blowfish {
1313
p: [u32, ..18]
1414
}
1515

16+
fn next_u32_wrap(buf: &[u8], offset: &mut uint) -> u32 {
17+
let mut v = 0;
18+
for _ in range(0u, 4) {
19+
if *offset >= buf.len() {
20+
*offset = 0;
21+
}
22+
v = (v << 8) | buf[*offset] as u32;
23+
*offset += 1;
24+
}
25+
v
26+
}
27+
1628
impl Blowfish {
1729
pub fn new(key: &[u8]) -> Blowfish {
1830
assert!(4 <= key.len() && key.len() <= 56);
@@ -204,14 +216,9 @@ impl Blowfish {
204216

205217
// For bcrypt. Use Blowfish::new instead.
206218
pub fn expand_key(&mut self, key: &[u8]) {
207-
let mut last_key_byte = 0u;
219+
let mut key_pos = 0u;
208220
for i in range(0u, 18u) {
209-
let mut key_slice = 0u32;
210-
for _ in range(0u, 4u) {
211-
key_slice = (key_slice << 8u) | (key[last_key_byte] as u32);
212-
last_key_byte = (last_key_byte+1) % key.len();
213-
}
214-
self.p[i] ^= key_slice;
221+
self.p[i] ^= next_u32_wrap(key, &mut key_pos);
215222
}
216223
let mut l = 0u32;
217224
let mut r = 0u32;
@@ -234,34 +241,30 @@ impl Blowfish {
234241
}
235242

236243
// Bcrypt key schedule.
237-
pub fn salted_expand_key(&mut self, salt: [u32, ..4], key: &[u8]) {
238-
let mut last_key_byte = 0u;
244+
pub fn salted_expand_key(&mut self, salt: &[u8], key: &[u8]) {
245+
let mut key_pos = 0u;
239246
for i in range(0u, 18u) {
240-
let mut key_slice = 0u32;
241-
for _ in range(0u, 4u) {
242-
key_slice = (key_slice << 8u) | (key[last_key_byte] as u32);
243-
last_key_byte = (last_key_byte+1) % key.len();
244-
}
245-
self.p[i] ^= key_slice;
247+
self.p[i] ^= next_u32_wrap(key, &mut key_pos);
246248
}
247249
let mut l = 0u32;
248250
let mut r = 0u32;
251+
let mut salt_pos = 0u;
249252
for i in range_step(0u, 18u, 2) {
250-
let (new_l, new_r) = self.encrypt(l ^ salt[i & 2], r ^ salt[(i&2)+1]);
253+
let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
251254
l = new_l;
252255
r = new_r;
253256
self.p[i] = l;
254257
self.p[i+1] = r;
255258
}
256259
for i in range(0u, 4u) {
257260
for j in range_step(0u, 256u, 4) {
258-
let (new_l, new_r) = self.encrypt(l ^ salt[2], r ^ salt[3]);
261+
let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
259262
l = new_l;
260263
r = new_r;
261264
self.s[i][j] = l;
262265
self.s[i][j+1] = r;
263266

264-
let (new_l, new_r) = self.encrypt(l ^ salt[0], r ^ salt[1]);
267+
let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
265268
l = new_l;
266269
r = new_r;
267270
self.s[i][j+2] = l;

0 commit comments

Comments
 (0)