diff --git a/Cargo.toml b/Cargo.toml index 0d6e6db..ddb508c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ sha3 = "0.10.8" x25519-dalek = {version = "2.0.0", features = ["static_secrets"]} rand_07 = { package = "rand", version = "0.7.0" } ascon-aead = "0.4.2" +rayon = "1.10.0" [profile.dev.package.num-bigint-dig] opt-level = 3 diff --git a/index.d.ts b/index.d.ts index 2f7f119..5e867e8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,11 +4,17 @@ /* auto-generated by NAPI-RS */ export function argon2Hash(password: string): string +export function argon2HashThreadPool(password: string): string export function argon2Verify(hashedPassword: string, passwordToVerify: string): boolean +export function argon2VerifyThreadpool(hashedPassword: string, passwordToVerify: string): boolean export function bcryptHash(passwordToHash: string): string +export function bcryptHashThreadpool(passwordToHash: string): string export function bcryptVerify(hashedPassword: string, passwordToVerify: string): boolean +export function bcryptVerifyThreadpool(passwordToHash: string, passwordToVerify: string): boolean export function scryptHash(passwordToHash: string): string export function scryptVerify(hashedPassword: string, passwordToVerify: string): boolean +export function scryptHashThreadpool(passwordToHash: string): string +export function scryptVerifyThreadpool(hashedPassword: string, passwordToVerify: string): boolean export function sha512(dataToHash: Array): Array export function sha512Verify(dataToHash: Array, dataToVerify: Array): boolean export function sha256(dataToHash: Array): Array diff --git a/index.node b/index.node index fb9abb1..903a440 100644 Binary files a/index.node and b/index.node differ diff --git a/package.json b/package.json index 35c0fdd..60b8af3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cas-typescript-sdk", - "version": "1.0.21", + "version": "1.0.22", "description": "", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src-ts/password-hashers/argon2-wrapper.ts b/src-ts/password-hashers/argon2-wrapper.ts index 61a1c37..2795955 100644 --- a/src-ts/password-hashers/argon2-wrapper.ts +++ b/src-ts/password-hashers/argon2-wrapper.ts @@ -1,9 +1,27 @@ -import {argon2Hash, argon2Verify} from "./../../index"; -import { IPasswordHasherBase} from "./password-hasher-base"; +import { argon2Hash, argon2HashThreadPool, argon2Verify, argon2VerifyThreadpool } from "./../../index"; +import { IPasswordHasherBase } from "./password-hasher-base"; export class Argon2Wrapper implements IPasswordHasherBase { + + verifyThreadPool(hashedPassword: string, passwordToCheck: string): boolean { + if (!hashedPassword) { + throw new Error("You must provide a password to verify with Argon2"); + } + if (!passwordToCheck) { + throw new Error("You must provide a password to check to verify with Argon2"); + } + return argon2VerifyThreadpool(hashedPassword, passwordToCheck); + } + + public hashPasswordThreadPool(password: string): string { + if (!password) { + throw new Error("You must provide a password to hash with Argon2"); + } + return argon2HashThreadPool(password); + } + public hashPassword(password: string): string { - if (!password){ + if (!password) { throw new Error("You must provide a password to hash with Argon2"); } return argon2Hash(password); @@ -11,7 +29,9 @@ export class Argon2Wrapper implements IPasswordHasherBase { public verify(hashedPassword: string, passwordToVerify: string): boolean { if (!hashedPassword || !passwordToVerify) { - throw new Error("You must provide a hashed password and a plaintext password to verify with Argon2"); + throw new Error( + "You must provide a hashed password and a plaintext password to verify with Argon2", + ); } return argon2Verify(hashedPassword, passwordToVerify); } diff --git a/src-ts/password-hashers/bcrypt-wrapper.ts b/src-ts/password-hashers/bcrypt-wrapper.ts index 3b94483..2f44195 100644 --- a/src-ts/password-hashers/bcrypt-wrapper.ts +++ b/src-ts/password-hashers/bcrypt-wrapper.ts @@ -1,7 +1,24 @@ import { IPasswordHasherBase } from "./password-hasher-base"; -import { bcryptHash, bcryptVerify } from "./../../index"; +import { bcryptHash, bcryptHashThreadpool, bcryptVerify, bcryptVerifyThreadpool } from "./../../index"; export class BCryptWrapper implements IPasswordHasherBase { + + verifyThreadPool(hashedPassword: string, passwordToCheck: string): boolean { + if (!hashedPassword || !passwordToCheck) { + throw new Error( + "You must provide a hashed password and a plaintext password to verify with Argon2", + ); + } + return bcryptVerifyThreadpool(hashedPassword, passwordToCheck); + } + + public hashPasswordThreadPool(password: string): string { + if (!password) { + throw new Error("You must provide a password to hash with Argon2"); + } + return bcryptHashThreadpool(password); + } + public hashPassword(password: string): string { if (!password) { throw new Error("You must provide a password to hash with Argon2"); diff --git a/src-ts/password-hashers/password-hasher-base.ts b/src-ts/password-hashers/password-hasher-base.ts index 839d56d..1621e1f 100644 --- a/src-ts/password-hashers/password-hasher-base.ts +++ b/src-ts/password-hashers/password-hasher-base.ts @@ -1,4 +1,6 @@ export interface IPasswordHasherBase { hashPassword(password: string): string; verify(hashedPassword: string, passwordToVerify: string): boolean; + hashPasswordThreadPool(password: string): string; + verifyThreadPool(hashedPassword: string, passwordToCheck: string): boolean; } \ No newline at end of file diff --git a/src-ts/password-hashers/scrypt-wrapper.ts b/src-ts/password-hashers/scrypt-wrapper.ts index 17499fb..47bbe84 100644 --- a/src-ts/password-hashers/scrypt-wrapper.ts +++ b/src-ts/password-hashers/scrypt-wrapper.ts @@ -1,20 +1,37 @@ -import { scryptHash, scryptVerify } from "../../index"; +import { scryptHash, scryptHashThreadpool, scryptVerify, scryptVerifyThreadpool } from "../../index"; import { IPasswordHasherBase } from "./password-hasher-base"; export class ScryptWrapper implements IPasswordHasherBase { - public hashPassword(password: string): string { - if (!password){ - throw new Error("You must provide a password to hash with Scrypt"); - } - return scryptHash(password); - } - - public verify(hashedPassword: string, passwordToVerify: string): boolean { - if (!hashedPassword || !passwordToVerify) { - throw new Error("You must provide a hashed password and a plaintext password to verify with Scrypt"); - } - return scryptVerify(hashedPassword, passwordToVerify); - } + verifyThreadPool(hashedPassword: string, passwordToCheck: string): boolean { + if (!hashedPassword || !passwordToCheck) { + throw new Error( + "You must provide a hashed password and a plaintext password to verify with Scrypt", + ); + } + return scryptVerifyThreadpool(hashedPassword, passwordToCheck); + } -} \ No newline at end of file + hashPasswordThreadPool(password: string): string { + if (!password) { + throw new Error("You must provide a password to hash with Scrypt"); + } + return scryptHashThreadpool(password); + } + + public hashPassword(password: string): string { + if (!password) { + throw new Error("You must provide a password to hash with Scrypt"); + } + return scryptHash(password); + } + + public verify(hashedPassword: string, passwordToVerify: string): boolean { + if (!hashedPassword || !passwordToVerify) { + throw new Error( + "You must provide a hashed password and a plaintext password to verify with Scrypt", + ); + } + return scryptVerify(hashedPassword, passwordToVerify); + } +} diff --git a/src/password_hashers/argon2.rs b/src/password_hashers/argon2.rs index bff7430..670a12f 100644 --- a/src/password_hashers/argon2.rs +++ b/src/password_hashers/argon2.rs @@ -1,4 +1,3 @@ -use std::net::ToSocketAddrs; use napi_derive::napi; @@ -7,6 +6,8 @@ use argon2::{ Argon2, PasswordHash, PasswordHasher, PasswordVerifier, }; +use crate::symmetric::aes::CASAES128; + use super::cas_password_hasher::CASPasswordHasher; pub struct CASArgon; @@ -35,11 +36,49 @@ pub fn argon2_hash(password: String) -> String { return ::hash_password(password); } +#[napi] +pub fn argon2_hash_thread_pool(password: String) -> String { + let (sender, receiver) = std::sync::mpsc::channel(); + rayon::spawn(move || { + let hash_result = ::hash_password(password); + sender.send(hash_result); + }); + let result = receiver.recv().unwrap(); + result +} + #[napi] pub fn argon2_verify(hashed_password: String, password_to_verify: String) -> bool { return ::verify_password(hashed_password, password_to_verify); } +#[napi] +pub fn argon2_verify_threadpool(hashed_password: String, password_to_verify: String) -> bool { + let (sender, receiver) = std::sync::mpsc::channel(); + rayon::spawn(move || { + let verify_result = ::verify_password(hashed_password, password_to_verify); + sender.send(verify_result); + }); + let result = receiver.recv().unwrap(); + result +} + +#[test] +pub fn argon2_hash_threadpool_test() { + let password = "ThisIsNotMyPasswolrd".to_string(); + let hashed = argon2_hash_thread_pool(password.clone()); + assert_ne!(password, hashed); +} + +#[test] +pub fn argon2_verify_threadpool_test() { + let password = "ThisIsNotMyPasswolrd".to_string(); + let passwordToCheck = "ThisIsNotMyPasswolrd".to_string(); + let hashed = argon2_hash_thread_pool(password); + let result = argon2_verify_threadpool(hashed, passwordToCheck); + assert_eq!(result, true); +} + #[test] pub fn argon2_hash_test() { let password = "ThisIsNotMyPasswolrd".to_string(); diff --git a/src/password_hashers/bcrypt.rs b/src/password_hashers/bcrypt.rs index 8e67fd8..c51e6d9 100644 --- a/src/password_hashers/bcrypt.rs +++ b/src/password_hashers/bcrypt.rs @@ -1,3 +1,5 @@ +use std::sync::mpsc; + use bcrypt::{hash, verify, DEFAULT_COST}; use napi_derive::napi; @@ -20,11 +22,33 @@ pub fn bcrypt_hash(password_to_hash: String) -> String { return ::hash_password(password_to_hash); } +#[napi] +pub fn bcrypt_hash_threadpool(password_to_hash: String) -> String { + let (sender, receiver) = mpsc::channel(); + rayon::spawn(move || { + let thread_result = ::hash_password(password_to_hash); + sender.send(thread_result); + }); + let result = receiver.recv().unwrap(); + result +} + #[napi] pub fn bcrypt_verify(hashed_password: String, password_to_verify: String) -> bool { return ::verify_password(hashed_password, password_to_verify); } +#[napi] +pub fn bcrypt_verify_threadpool(password_to_hash: String, password_to_verify: String) -> bool { + let (sender, receiver) = mpsc::channel(); + rayon::spawn(move || { + let thread_result = ::verify_password(password_to_hash, password_to_verify); + sender.send(thread_result); + }); + let result = receiver.recv().unwrap(); + result +} + #[test] pub fn bcrypt_hash_test() { let password = "ThisIsNotMyPasswolrd".to_string(); @@ -32,6 +56,13 @@ pub fn bcrypt_hash_test() { assert_ne!(password, hashed); } +#[test] +pub fn bcrypt_hash_threadpool_test() { + let password = "ThisIsNotMyPasswolrd".to_string(); + let hashed = bcrypt_hash_threadpool(password.clone()); + assert_ne!(password, hashed); +} + #[test] pub fn bcrypt_verify_test() { let password = "ThisIsNotMyPasswolrd".to_string(); @@ -40,6 +71,14 @@ pub fn bcrypt_verify_test() { assert_eq!(true, verified); } +#[test] +pub fn bcrypt_verify_threadpool_test() { + let password = "ThisIsNotMyPasswolrd".to_string(); + let hashed = bcrypt_hash_threadpool(password.clone()); + let verified = bcrypt_verify_threadpool(hashed, password); + assert_eq!(true, verified); +} + #[test] pub fn bcrypt_verify_fail_test() { let password = "ThisIsNotMyPasswolrd".to_string(); diff --git a/src/password_hashers/scrypt.rs b/src/password_hashers/scrypt.rs index 2a33407..72c3314 100644 --- a/src/password_hashers/scrypt.rs +++ b/src/password_hashers/scrypt.rs @@ -1,3 +1,5 @@ +use std::sync::mpsc; + use napi_derive::napi; use scrypt::{ @@ -36,6 +38,43 @@ pub fn scrypt_verify(hashed_password: String, password_to_verify: String) -> boo return ::verify_password(hashed_password, password_to_verify); } +#[napi] +pub fn scrypt_hash_threadpool(password_to_hash: String) -> String { + let (sender, receiver) = mpsc::channel(); + rayon::spawn(move || { + let thread_result = ::hash_password(password_to_hash); + sender.send(thread_result); + }); + let result = receiver.recv().unwrap(); + result +} + +#[napi] +pub fn scrypt_verify_threadpool(hashed_password: String, password_to_verify: String) -> bool { + let (sender, receiver) = mpsc::channel(); + rayon::spawn(move || { + let thread_result = ::verify_password(hashed_password, password_to_verify); + sender.send(thread_result); + }); + let result = receiver.recv().unwrap(); + result +} + +#[test] +pub fn scrypt_hash_threadpool_test() { + let password = "BadPassword".to_string(); + let hashed_password = scrypt_hash_threadpool(password.clone()); + assert_ne!(password, hashed_password); +} + +#[test] +pub fn scrypt_verify_threadpool_test() { + let password = "BadPassword".to_string(); + let hashed_password = scrypt_hash_threadpool(password.clone()); + let verified = scrypt_verify_threadpool(hashed_password, password); + assert_eq!(true, verified); +} + #[test] pub fn scrypt_hash_test() { let password = "BadPassword".to_string(); diff --git a/test-ts/password-hasher.test.spec.ts b/test-ts/password-hasher.test.spec.ts index 843fa20..3949e6f 100644 --- a/test-ts/password-hasher.test.spec.ts +++ b/test-ts/password-hasher.test.spec.ts @@ -1,5 +1,5 @@ import { assert, expect } from "chai"; -import { BCryptWrapper } from "../src-ts/password-hashers/index"; +import { Argon2Wrapper, BCryptWrapper } from "../src-ts/password-hashers/index"; import { ScryptWrapper } from "../src-ts/password-hashers/index"; import { PasswordHasherFactory, @@ -7,6 +7,22 @@ import { } from "../src-ts/password-hashers"; describe("Bcrypt Tests", () => { + + it("hash threadpool", () => { + const hasher: BCryptWrapper = new BCryptWrapper(); + const password: string = "ThisOneBadPassword!@"; + const hashedPassword: string = hasher.hashPasswordThreadPool(password); + assert.notEqual(hashedPassword, password); + }); + + it("verify threadpool", () => { + const hasher: BCryptWrapper = new BCryptWrapper(); + const password: string = "NotThisPassword!@"; + const hashedPassword: string = hasher.hashPassword(password); + const isValid: boolean = hasher.verifyThreadPool(hashedPassword, password); + expect(isValid).to.equal(true); + }); + it("hash", () => { const hasher: BCryptWrapper = new BCryptWrapper(); const password: string = "ThisOneBadPassword!@"; @@ -35,6 +51,25 @@ describe("Bcrypt Tests", () => { }); describe("Scrypt Tests", () => { + it("hash with threadpool", () => { + const hasher: ScryptWrapper = PasswordHasherFactory.getHasher( + PasswordHasherType.Scrypt, + ); + const password: string = "ScryptRocks"; + const hashed: string = hasher.hashPasswordThreadPool(password); + assert.notEqual(password, hashed); + }); + + it("verify pass with threadpool", () => { + const hasher: ScryptWrapper = PasswordHasherFactory.getHasher( + PasswordHasherType.Scrypt, + ); + const password: string = "ScryptRocks1231231"; + const hashed: string = hasher.hashPasswordThreadPool(password); + const verified: boolean = hasher.verifyThreadPool(hashed, password); + assert.isTrue(verified); + }); + it("hash with factory", () => { const hasher: ScryptWrapper = PasswordHasherFactory.getHasher( PasswordHasherType.Scrypt, @@ -69,8 +104,23 @@ describe("Scrypt Tests", () => { }); describe("Argon2 Tests", () => { + it("hash with threadpool", () => { + const argon2: Argon2Wrapper = PasswordHasherFactory.getHasher(PasswordHasherType.Argon2); + const password = "Argon2OverBCrypt"; + const hashed = argon2.hashPasswordThreadPool(password); + assert.notEqual(password, hashed); + }) + + it("verify with threadpool", () => { + const argon2: Argon2Wrapper = PasswordHasherFactory.getHasher(PasswordHasherType.Argon2); + const password = "Argon2OverBCrypt"; + const hashed = argon2.hashPasswordThreadPool(password); + const result = argon2.verifyThreadPool(hashed, password); + assert.equal(result, true); + }); + it("hash with factory", () => { - const hasher: ScryptWrapper = PasswordHasherFactory.getHasher( + const hasher: Argon2Wrapper = PasswordHasherFactory.getHasher( PasswordHasherType.Argon2, ); const password: string = "ScryptRocks"; @@ -79,7 +129,7 @@ describe("Argon2 Tests", () => { }); it("verify pass with factory", () => { - const hasher: ScryptWrapper = PasswordHasherFactory.getHasher( + const hasher: Argon2Wrapper = PasswordHasherFactory.getHasher( PasswordHasherType.Argon2, ); const password: string = "ScryptRocks1231231";