1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
//! This crate implements the Scrypt key derivation function as specified //! in \[1\]. //! //! If you are only using the low-level [`scrypt`] function instead of the //! higher-level [`Scrypt`] struct to produce/verify hash strings, //! it's recommended to disable default features in your `Cargo.toml`: //! //! ```toml //! [dependencies] //! scrypt = { version = "0.2", default-features = false } //! ``` //! //! # Usage (simple with default params) //! //! ``` //! # #[cfg(feature = "password-hash")] //! # { //! use scrypt::{ //! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, //! Scrypt //! }; //! use rand_core::OsRng; //! //! let password = b"hunter42"; // Bad password; don't actually use! //! let salt = SaltString::generate(&mut OsRng); //! //! // Hash password to PHC string ($scrypt$...) //! let password_hash = Scrypt.hash_password_simple(password, salt.as_ref()).unwrap().to_string(); //! //! // Verify password against PHC string //! let parsed_hash = PasswordHash::new(&password_hash).unwrap(); //! assert!(Scrypt.verify_password(password, &parsed_hash).is_ok()); //! # } //! ``` //! //! # References //! \[1\] - [C. Percival. Stronger Key Derivation Via Sequential //! Memory-Hard Functions](http://www.tarsnap.com/scrypt/scrypt.pdf) #![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")] #[macro_use] extern crate alloc; #[cfg(feature = "std")] extern crate std; use hmac::Hmac; use pbkdf2::pbkdf2; use sha2::Sha256; /// Errors for `scrypt` operations. pub mod errors; mod params; mod romix; #[cfg(feature = "simple")] mod simple; #[cfg(feature = "simple")] pub use password_hash; pub use crate::params::Params; #[cfg(feature = "simple")] pub use crate::simple::{Scrypt, ALG_ID}; /// The scrypt key derivation function. /// /// # Arguments /// - `password` - The password to process as a byte vector /// - `salt` - The salt value to use as a byte vector /// - `params` - The ScryptParams to use /// - `output` - The resulting derived key is returned in this byte vector. /// **WARNING: Make sure to compare this value in constant time!** /// /// # Return /// `Ok(())` if calculation is succesfull and `Err(InvalidOutputLen)` if /// `output` does not satisfy the following condition: /// `output.len() > 0 && output.len() <= (2^32 - 1) * 32`. pub fn scrypt( password: &[u8], salt: &[u8], params: &Params, output: &mut [u8], ) -> Result<(), errors::InvalidOutputLen> { // This check required by Scrypt: // check output.len() > 0 && output.len() <= (2^32 - 1) * 32 if output.is_empty() || output.len() / 32 > 0xffff_ffff { return Err(errors::InvalidOutputLen); } // The checks in the ScryptParams constructor guarantee // that the following is safe: 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); let mut v = vec![0u8; nr128]; let mut t = vec![0u8; r128]; for chunk in &mut b.chunks_mut(r128) { romix::scrypt_ro_mix(chunk, &mut v, &mut t, n); } pbkdf2::<Hmac<Sha256>>(&password, &b, 1, output); Ok(()) }