Skip to content

Commit 2f7d4ad

Browse files
authored
Merge pull request #46 from Cryptographic-API-Services/#44-password-hasher-threading
#44 password hasher threading
2 parents e3910d9 + cdfdbea commit 2f7d4ad

File tree

3 files changed

+213
-13
lines changed

3 files changed

+213
-13
lines changed

src/argon2.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
2-
ffi::{c_char, CStr, CString},
3-
slice, thread,
2+
ffi::{c_char, CStr, CString}, slice, sync::mpsc, thread
43
};
54

65
extern crate rayon;
@@ -75,6 +74,48 @@ fn argon2_verify_fail_test() {
7574
assert_eq!(false, is_valid);
7675
}
7776

77+
#[no_mangle]
78+
pub extern "C" fn argon2_verify_threadpool(hashed_pass: *const c_char, password: *const c_char) -> bool {
79+
let hashed_pass_string = unsafe {
80+
assert!(!hashed_pass.is_null());
81+
CStr::from_ptr(hashed_pass)
82+
}
83+
.to_str()
84+
.unwrap();
85+
86+
let password_string = unsafe {
87+
assert!(!password.is_null());
88+
CStr::from_ptr(password)
89+
}
90+
.to_str()
91+
.unwrap()
92+
.as_bytes();
93+
let (sender, receiver) = mpsc::channel();
94+
rayon::spawn(move || {
95+
let parsed_hash = PasswordHash::new(&hashed_pass_string).unwrap();
96+
let thread_result = Argon2::default()
97+
.verify_password(password_string, &parsed_hash)
98+
.is_ok();
99+
sender.send(thread_result);
100+
});
101+
let result = receiver.recv().unwrap();
102+
result
103+
}
104+
105+
#[test]
106+
fn argon2_verify_threadpool_test() {
107+
let password = "PasswordToVerify";
108+
let password_cstr = CString::new(password).unwrap();
109+
let password_bytes = password_cstr.as_bytes_with_nul();
110+
let password_ptr = password_bytes.as_ptr() as *const i8;
111+
let hashed_password = argon2_hash_threadpool(password_ptr);
112+
let hashed_password_ctr = unsafe { CString::from_raw(hashed_password) };
113+
let hashed_password_bytes = hashed_password_ctr.as_bytes_with_nul();
114+
let hashed_password_ptr = hashed_password_bytes.as_ptr() as *const i8;
115+
let is_valid = argon2_verify_threadpool(hashed_password_ptr, password_ptr);
116+
assert_eq!(true, is_valid);
117+
}
118+
78119
#[no_mangle]
79120
pub extern "C" fn argon2_verify_thread(
80121
hashed_pass: *const c_char,
@@ -148,6 +189,38 @@ fn argon2_hash_test() {
148189
assert_ne!(password, hashed_password_str);
149190
}
150191

192+
#[no_mangle]
193+
pub extern "C" fn argon2_hash_threadpool(pass_to_hash: *const c_char) -> *mut c_char {
194+
let pass_bytes = unsafe {
195+
assert!(!pass_to_hash.is_null());
196+
CStr::from_ptr(pass_to_hash)
197+
}
198+
.to_str()
199+
.unwrap()
200+
.as_bytes();
201+
let (sender, receiver) = mpsc::channel();
202+
rayon::spawn(move || {
203+
let salt = SaltString::generate(&mut OsRng);
204+
let argon2 = Argon2::default();
205+
let password_hash = argon2.hash_password(pass_bytes, &salt).unwrap().to_string();
206+
sender.send(password_hash);
207+
});
208+
let result = CString::new(receiver.recv().unwrap()).unwrap().into_raw();
209+
result
210+
}
211+
212+
#[test]
213+
fn argon2_hash_threadpool_test() {
214+
let password = "DontUseThisPassword";
215+
let password_cstr = CString::new(password).unwrap();
216+
let password_bytes = password_cstr.as_bytes_with_nul();
217+
let password_ptr = password_bytes.as_ptr() as *const i8;
218+
let hashed_password_ptr = argon2_hash_threadpool(password_ptr);
219+
let hashed_password_ctr = unsafe { CString::from_raw(hashed_password_ptr) };
220+
let hashed_password_str = hashed_password_ctr.to_str().unwrap();
221+
assert_ne!(password, hashed_password_str);
222+
}
223+
151224
#[no_mangle]
152225
pub extern "C" fn argon2_hash_thread(
153226
passwords_to_hash: *const *const c_char,

src/bcrypt.rs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
2-
ffi::{c_char, CStr, CString},
3-
thread,
2+
ffi::{c_char, CStr, CString}, sync::mpsc, thread
43
};
54

65
use bcrypt::{hash, verify, DEFAULT_COST};
@@ -31,6 +30,36 @@ fn bcrypt_hash_test() {
3130
assert_ne!(hashed_password_str, password);
3231
}
3332

33+
#[no_mangle]
34+
pub extern "C" fn bcrypt_hash_threadpool(pass_to_hash: *const c_char) -> *mut c_char {
35+
let string_pass = unsafe {
36+
assert!(!pass_to_hash.is_null());
37+
38+
CStr::from_ptr(pass_to_hash)
39+
}
40+
.to_str()
41+
.unwrap();
42+
let (sender, receiver) = mpsc::channel();
43+
rayon::spawn(move || {
44+
let hashed_password = hash(string_pass, DEFAULT_COST).unwrap();
45+
sender.send(hashed_password);
46+
});
47+
let result = CString::new(receiver.recv().unwrap()).unwrap().into_raw();
48+
result
49+
}
50+
51+
#[test]
52+
fn bcrypt_hash_threadpool_test() {
53+
let password = "PasswordToHash";
54+
let password_cstr = CString::new(password).unwrap();
55+
let password_bytes = password_cstr.as_bytes_with_nul();
56+
let passsword_ptr = password_bytes.as_ptr() as *const i8;
57+
let hashed_password = bcrypt_hash_threadpool(passsword_ptr);
58+
let hashed_password_ctr = unsafe { CString::from_raw(hashed_password) };
59+
let hashed_password_str = hashed_password_ctr.to_str().unwrap();
60+
assert_ne!(hashed_password_str, password);
61+
}
62+
3463
#[no_mangle]
3564
pub extern "C" fn bcrypt_verify(pass: *const c_char, hash: *const c_char) -> bool {
3665
let string_pass = unsafe {
@@ -51,8 +80,22 @@ pub extern "C" fn bcrypt_verify(pass: *const c_char, hash: *const c_char) -> boo
5180
return verify(string_pass, string_hash).unwrap();
5281
}
5382

83+
#[test]
84+
fn bcrypt_verify_test() {
85+
let password = "PasswordToHash";
86+
let password_cstr = CString::new(password).unwrap();
87+
let password_bytes = password_cstr.as_bytes_with_nul();
88+
let password_ptr = password_bytes.as_ptr() as *const i8;
89+
let hashed_password = bcrypt_hash(password_ptr);
90+
let hashed_password_ctr = unsafe { CString::from_raw(hashed_password) };
91+
let hashed_password_bytes = hashed_password_ctr.as_bytes_with_nul();
92+
let hashed_password_ptr = hashed_password_bytes.as_ptr() as *const i8;
93+
let is_valid = bcrypt_verify(password_ptr, hashed_password_ptr);
94+
assert_eq!(true, is_valid);
95+
}
96+
5497
#[no_mangle]
55-
pub extern "C" fn bcrypt_verify_thread(pass: *const c_char, hash: *const c_char) -> bool {
98+
pub extern "C" fn bcrypt_verify_threadpool(pass: *const c_char, hash: *const c_char) -> bool {
5699
let string_pass = unsafe {
57100
assert!(!pass.is_null());
58101

@@ -68,21 +111,25 @@ pub extern "C" fn bcrypt_verify_thread(pass: *const c_char, hash: *const c_char)
68111
}
69112
.to_str()
70113
.unwrap();
71-
return thread::spawn(move || return verify(string_pass, string_hash).unwrap())
72-
.join()
73-
.unwrap();
114+
let (sender, receiver) = mpsc::channel();
115+
rayon::spawn(move || {
116+
let thread_result = verify(string_pass, string_hash).unwrap();
117+
sender.send(thread_result);
118+
});
119+
let result = receiver.recv().unwrap();
120+
result
74121
}
75122

76123
#[test]
77-
fn bcrypt_verify_test() {
124+
fn bcrypt_verify_threadpool_test() {
78125
let password = "PasswordToHash";
79126
let password_cstr = CString::new(password).unwrap();
80127
let password_bytes = password_cstr.as_bytes_with_nul();
81128
let password_ptr = password_bytes.as_ptr() as *const i8;
82-
let hashed_password = bcrypt_hash(password_ptr);
129+
let hashed_password = bcrypt_hash_threadpool(password_ptr);
83130
let hashed_password_ctr = unsafe { CString::from_raw(hashed_password) };
84131
let hashed_password_bytes = hashed_password_ctr.as_bytes_with_nul();
85132
let hashed_password_ptr = hashed_password_bytes.as_ptr() as *const i8;
86-
let is_valid = bcrypt_verify(password_ptr, hashed_password_ptr);
133+
let is_valid = bcrypt_verify_threadpool(password_ptr, hashed_password_ptr);
87134
assert_eq!(true, is_valid);
88-
}
135+
}

src/scrypt.rs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::ffi::{c_char, CStr, CString};
1+
use std::{ffi::{c_char, CStr, CString}, sync::mpsc};
22

33
use scrypt::{
44
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
@@ -35,6 +35,40 @@ fn scrypt_hash_test() {
3535
assert_ne!(hashed_str, password);
3636
}
3737

38+
#[no_mangle]
39+
pub extern "C" fn scrypt_hash_threadpool(pass_to_hash: *const c_char) -> *mut c_char {
40+
let string_pass = unsafe {
41+
assert!(!pass_to_hash.is_null());
42+
43+
CStr::from_ptr(pass_to_hash)
44+
}
45+
.to_str()
46+
.unwrap();
47+
let (sender, receiver) = mpsc::channel();
48+
rayon::spawn(move || {
49+
let salt = SaltString::generate(&mut OsRng);
50+
let hashed = Scrypt
51+
.hash_password(string_pass.as_bytes(), &salt)
52+
.unwrap()
53+
.to_string();
54+
sender.send(hashed);
55+
});
56+
let result = CString::new(receiver.recv().unwrap()).unwrap().into_raw();
57+
result
58+
}
59+
60+
#[test]
61+
fn scrypt_hash_threadpool_test() {
62+
let password = "PasswordToTest";
63+
let password_cstr = CString::new(password).unwrap();
64+
let password_bytes = password_cstr.as_bytes_with_nul();
65+
let password_ptr = password_bytes.as_ptr() as *const i8;
66+
let hashed = scrypt_hash_threadpool(password_ptr);
67+
let hashed_ctr = unsafe { CString::from_raw(hashed) };
68+
let hashed_str = hashed_ctr.to_str().unwrap();
69+
assert_ne!(hashed_str, password);
70+
}
71+
3872
#[no_mangle]
3973
pub extern "C" fn scrypt_verify(
4074
pass_to_check: *const c_char,
@@ -75,3 +109,49 @@ fn scrypt_verify_test() {
75109
let is_valid = scrypt_verify(password_ptr, hashed_ptr);
76110
assert_eq!(true, is_valid);
77111
}
112+
113+
#[no_mangle]
114+
pub extern "C" fn scrypt_verify_threadpool(
115+
pass_to_check: *const c_char,
116+
hash_to_check: *const c_char,
117+
) -> bool {
118+
let string_pass = unsafe {
119+
assert!(!pass_to_check.is_null());
120+
121+
CStr::from_ptr(pass_to_check)
122+
}
123+
.to_str()
124+
.unwrap();
125+
126+
let string_hash = unsafe {
127+
assert!(!hash_to_check.is_null());
128+
129+
CStr::from_ptr(hash_to_check)
130+
}
131+
.to_str()
132+
.unwrap();
133+
let (sender, receiver) = mpsc::channel();
134+
rayon::spawn(move || {
135+
let parsed_hash = PasswordHash::new(&string_hash).unwrap();
136+
let thread_result = Scrypt
137+
.verify_password(string_pass.as_bytes(), &parsed_hash)
138+
.is_ok();
139+
sender.send(thread_result);
140+
});
141+
let result = receiver.recv().unwrap();
142+
result
143+
}
144+
145+
#[test]
146+
fn scrypt_verify_threadpool_test() {
147+
let password = "NotThePasswordYouAreLookingFor";
148+
let password_cstr = CString::new(password).unwrap();
149+
let password_bytes = password_cstr.as_bytes_with_nul();
150+
let password_ptr = password_bytes.as_ptr() as *const i8;
151+
let hash = scrypt_hash_threadpool(password_ptr);
152+
let hash_ctr = unsafe { CString::from_raw(hash) };
153+
let hashed_bytes = hash_ctr.as_bytes_with_nul();
154+
let hashed_ptr = hashed_bytes.as_ptr() as *const i8;
155+
let is_valid = scrypt_verify_threadpool(password_ptr, hashed_ptr);
156+
assert_eq!(true, is_valid);
157+
}

0 commit comments

Comments
 (0)