Skip to content

Commit 75ba99d

Browse files
committed
feat(argon2): add hashRaw and sync api
1 parent 1ccf475 commit 75ba99d

File tree

3 files changed

+127
-2
lines changed

3 files changed

+127
-2
lines changed

packages/argon2/index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,21 @@ export function hash(
7070
options?: Options | undefined | null,
7171
abortSignal?: AbortSignal | undefined | null,
7272
): Promise<string>
73+
export function hashSync(password: string | Buffer, options?: Options | undefined | null): string
74+
export function hashRaw(
75+
password: string | Buffer,
76+
options?: Options | undefined | null,
77+
abortSignal?: AbortSignal | undefined | null,
78+
): Promise<Buffer>
79+
export function hashRawSync(password: string | Buffer, options?: Options | undefined | null): Buffer
7380
export function verify(
7481
hashed: string | Buffer,
7582
password: string | Buffer,
7683
options?: Options | undefined | null,
7784
abortSignal?: AbortSignal | undefined | null,
7885
): Promise<boolean>
86+
export function verifySync(
87+
hashed: string | Buffer,
88+
password: string | Buffer,
89+
options?: Options | undefined | null,
90+
): boolean

packages/argon2/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,13 @@ if (!nativeBinding) {
218218
throw new Error(`Failed to load native binding`)
219219
}
220220

221-
const { Algorithm, Version, hash, verify } = nativeBinding
221+
const { Algorithm, Version, hash, hashSync, hashRaw, hashRawSync, verify, verifySync } = nativeBinding
222222

223223
module.exports.Algorithm = Algorithm
224224
module.exports.Version = Version
225225
module.exports.hash = hash
226+
module.exports.hashSync = hashSync
227+
module.exports.hashRaw = hashRaw
228+
module.exports.hashRawSync = hashRawSync
226229
module.exports.verify = verify
230+
module.exports.verifySync = verifySync

packages/argon2/src/lib.rs

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use napi_derive::napi;
88

99
use argon2::{
1010
password_hash::{rand_core::OsRng, PasswordHasher, PasswordVerifier, SaltString},
11-
Argon2,
11+
Argon2, Params,
1212
};
1313

1414
#[napi]
@@ -153,6 +153,91 @@ pub fn hash(
153153
)
154154
}
155155

156+
#[napi]
157+
pub fn hash_sync(
158+
env: Env,
159+
password: Either<String, Buffer>,
160+
options: Option<Options>,
161+
) -> Result<String> {
162+
let mut hash_task = HashTask {
163+
password: match password {
164+
Either::A(s) => s.as_bytes().to_vec(),
165+
Either::B(b) => b.to_vec(),
166+
},
167+
options: options.unwrap_or_default(),
168+
};
169+
let output = hash_task.compute()?;
170+
hash_task.resolve(env, output)
171+
}
172+
173+
pub struct RawHashTask {
174+
password: Vec<u8>,
175+
options: Options,
176+
}
177+
178+
#[napi]
179+
impl Task for RawHashTask {
180+
type Output = Vec<u8>;
181+
type JsValue = Buffer;
182+
183+
fn compute(&mut self) -> Result<Self::Output> {
184+
let salt = SaltString::generate(&mut OsRng);
185+
let hasher = self
186+
.options
187+
.to_argon()
188+
.map_err(|err| Error::new(Status::InvalidArg, format!("{}", err)))?;
189+
let output_len = hasher
190+
.params()
191+
.output_len()
192+
.unwrap_or(Params::DEFAULT_OUTPUT_LEN);
193+
let mut output = vec![0; output_len];
194+
195+
hasher
196+
.hash_password_into(self.password.as_slice(), salt.as_bytes(), &mut output)
197+
.map_err(|err| Error::new(Status::GenericFailure, format!("{}", err)))
198+
.map(|_| output)
199+
}
200+
201+
fn resolve(&mut self, _env: Env, output: Self::Output) -> Result<Self::JsValue> {
202+
Ok(output.into())
203+
}
204+
}
205+
206+
#[napi]
207+
pub fn hash_raw(
208+
password: Either<String, Buffer>,
209+
options: Option<Options>,
210+
abort_signal: Option<AbortSignal>,
211+
) -> AsyncTask<RawHashTask> {
212+
AsyncTask::with_optional_signal(
213+
RawHashTask {
214+
password: match password {
215+
Either::A(s) => s.as_bytes().to_vec(),
216+
Either::B(b) => b.to_vec(),
217+
},
218+
options: options.unwrap_or_default(),
219+
},
220+
abort_signal,
221+
)
222+
}
223+
224+
#[napi]
225+
pub fn hash_raw_sync(
226+
env: Env,
227+
password: Either<String, Buffer>,
228+
options: Option<Options>,
229+
) -> Result<Buffer> {
230+
let mut hash_task = RawHashTask {
231+
password: match password {
232+
Either::A(s) => s.as_bytes().to_vec(),
233+
Either::B(b) => b.to_vec(),
234+
},
235+
options: options.unwrap_or_default(),
236+
};
237+
let output = hash_task.compute()?;
238+
hash_task.resolve(env, output)
239+
}
240+
156241
pub struct VerifyTask {
157242
password: String,
158243
hashed: String,
@@ -205,3 +290,27 @@ pub fn verify(
205290
abort_signal,
206291
))
207292
}
293+
294+
#[napi]
295+
pub fn verify_sync(
296+
env: Env,
297+
hashed: Either<String, Buffer>,
298+
password: Either<String, Buffer>,
299+
options: Option<Options>,
300+
) -> Result<bool> {
301+
let mut verify_task = VerifyTask {
302+
password: match password {
303+
Either::A(s) => s,
304+
Either::B(b) => String::from_utf8(b.to_vec())
305+
.map_err(|err| Error::new(Status::InvalidArg, format!("{}", err)))?,
306+
},
307+
hashed: match hashed {
308+
Either::A(s) => s,
309+
Either::B(b) => String::from_utf8(b.to_vec())
310+
.map_err(|err| Error::new(Status::InvalidArg, format!("{}", err)))?,
311+
},
312+
options: options.unwrap_or_default(),
313+
};
314+
let output = verify_task.compute()?;
315+
verify_task.resolve(env, output)
316+
}

0 commit comments

Comments
 (0)