#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
#[macro_use]
extern crate alloc;
use pbkdf2::pbkdf2_hmac;
use sha2::Sha256;
pub mod errors;
mod params;
mod romix;
#[cfg(feature = "simple")]
mod simple;
pub use crate::params::Params;
#[cfg(feature = "simple")]
pub use password_hash;
#[cfg(feature = "simple")]
pub use crate::simple::{ALG_ID, Scrypt};
pub fn scrypt(
password: &[u8],
salt: &[u8],
params: &Params,
output: &mut [u8],
) -> Result<(), errors::InvalidOutputLen> {
if output.is_empty() || output.len() / 32 > 0xffff_ffff {
return Err(errors::InvalidOutputLen);
}
let n = 1 << params.log_n;
let r128 = (params.r as usize) * 128;
let pr128 = (params.p as usize) * r128;
let nr128 = n * r128;
let mut b = vec![0u8; pr128];
pbkdf2_hmac::<Sha256>(password, salt, 1, &mut b);
#[cfg(not(feature = "rayon"))]
romix_sequential(nr128, r128, n, &mut b);
#[cfg(feature = "rayon")]
romix_parallel(nr128, r128, n, &mut b);
pbkdf2_hmac::<Sha256>(password, &b, 1, output);
Ok(())
}
#[cfg(not(feature = "rayon"))]
fn romix_sequential(nr128: usize, r128: usize, n: usize, b: &mut [u8]) {
let mut v = vec![0u8; nr128];
let mut t = vec![0u8; r128];
b.chunks_mut(r128).for_each(|chunk| {
romix::scrypt_ro_mix(chunk, &mut v, &mut t, n);
});
}
#[cfg(feature = "rayon")]
fn romix_parallel(nr128: usize, r128: usize, n: usize, b: &mut [u8]) {
use rayon::{iter::ParallelIterator as _, slice::ParallelSliceMut as _};
b.par_chunks_mut(r128).for_each(|chunk| {
let mut v = vec![0u8; nr128];
let mut t = vec![0u8; r128];
romix::scrypt_ro_mix(chunk, &mut v, &mut t, n);
});
}