GithubHelp home page GithubHelp logo

password-hashes's Introduction

RustCrypto: Password Hashes

Project Chat Apache2/MIT licensed Dependency Status

Collection of password hashing algorithms, otherwise known as password-based key derivation functions, written in pure Rust.

Supported Algorithms

Algorithm Crate Crates.io Documentation MSRV
Argon2 argon2 crates.io Documentation MSRV 1.65
Balloon balloon‑hash crates.io Documentation MSRV 1.65
bcrypt‑pbkdf bcrypt‑pbkdf crates.io Documentation MSRV 1.60
PBKDF2 pbkdf2 crates.io Documentation MSRV 1.60
scrypt scrypt crates.io Documentation MSRV 1.60
SHA-crypt sha‑crypt crates.io Documentation MSRV 1.60

Please see the OWASP Password Storage Cheat Sheet for assistance in selecting an appropriate algorithm for your use case.

Usage

The following code example shows how to verify a password when stored using one of many possible password hashing algorithms implemented in this repository.

use password_hash::{PasswordHash, PasswordVerifier};

use argon2::Argon2;
use pbkdf2::Pbkdf2;
use scrypt::Scrypt;

// Can be: `$argon2`, `$pbkdf2`, or `$scrypt`
let hash_string = "$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQAAAAAAAAAAA$+r0d29hqEB0yasKr55ZgICsQGSkl0v0kgwhd+U3wyRo";
let input_password = "password";

let password_hash = PasswordHash::new(&hash_string).expect("invalid password hash");

// Trait objects for algorithms to support
let algs: &[&dyn PasswordVerifier] = &[&Argon2::default(), &Pbkdf2, &Scrypt];

password_hash.verify_password(algs, input_password).expect("invalid password");

Minimum Supported Rust Version (MSRV) Policy

MSRV bumps are considered breaking changes and will be performed only with minor version bump.

License

All crates licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

password-hashes's People

Contributors

alex avatar baloo avatar brycx avatar c0d3-m4513r avatar daxpedda avatar dependabot[bot] avatar dyc3 avatar equal-l2 avatar ibotty avatar koushiro avatar lkarthee avatar masmullin2000 avatar michaeljones avatar minacode avatar nathanielknight avatar newpavlov avatar numenorean avatar oddgrd avatar pjottos avatar rlee287 avatar sc00bz avatar sorairolake avatar str4d avatar striezel avatar tarcieri avatar tbu- avatar tom25519 avatar tshepang avatar uglyoldbob avatar z33ky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

password-hashes's Issues

the trait `crypto_mac::Mac` is not implemented for `hmac::Hmac<sha1::Sha1>`

Clearly I'm doing something wrong, but can't figure it out. Anyone able to help me? :)

I've cloned this repo and all tests build and pass, yet copy-pasting the test case into my own project fails.

Minimal repro below

cargo.toml:

[dependencies]
hmac = "0.7"
sha-1 = "0.8"
pbkdf2 = { version = "0.2", default-features = false }

src/main.rs:

use sha1::Sha1;
use hmac::Hmac;

fn main() {
    let mut buf = [0u8; 32];
    pbkdf2::pbkdf2::<Hmac<Sha1>>(&"abc1234".as_bytes(), &"123456789".as_bytes(), 100_000, &mut buf);
}

When building:

$ cargo run
   Compiling haitchmac v0.1.0 (/path/to/haitchmac)
error[E0277]: the trait bound `hmac::Hmac<sha1::Sha1>: crypto_mac::Mac` is not satisfied
 --> src/main.rs:6:5
  |
6 |     pbkdf2::pbkdf2::<Hmac<Sha1>>(&"abc1234".as_bytes(), &"123456789".as_bytes(), 100_000, &mut buf);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `crypto_mac::Mac` is not implemented for `hmac::Hmac<sha1::Sha1>`
  |
  = note: required by `pbkdf2::pbkdf2`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

scrypt: Provide read access to the parameter values

Hi,
I am currently migrating a Node application to Rust. This application uses scrypt-kdf which is itself based on node-scrypt. The kdf function in these libraries uses a different format than the one provided by this lib. I plan to eventually move to the PHC string format, but my first step is to perform a simple port.

When porting the Node algorithm, I need to write the current parameters into the output buffer. I planned to store my parameters directly as a scrypt::Param instance but this type does not allow to read the current values, preventing me from using it to write the Node format. My current solution is to store these parameters in my own struct, but it creates duplication. This is especially bad when using Params::recommended as I now have to copy the recommended values to my own crate.

Would it be possible to provide read access to the current values of the parameters?

These values are pub(crate) currently. I understand that making them public might not be desirable as it completely breaks encapsulation (a mut scrypt::Params would allow anyone to change its values at any time). Would it then be possible to add getter methods? Something like:

impl Params {
  pub fn r(&self) -> u32 {
    self.r
  }
  // ...
}

pub fn main() {
   let params = Params::recommended();
   let r = params.r();
   // ...
}

Document rscrypt format upgrade path

It seems that starting with scrypt 0.6.0, "rscrypt" format is no longer supported?

I cannot find any documentation on how to upgrade existing hashes, as they don't seem to be supported anymore.

argon2: make parallel implementation safe

A parallel rayon-based implementation was added in #149, however it works by using raw pointers and creating mutable references from them. The references aren't aliased so in theory it should be sound, but a safe implementation would be better.

I left some comments on how to implement parallel processing safely in this comment:

#149 (comment)

The algorithm operates over a matrix of "blocks" consisting of:

  • 𝒑 rows ("lanes"), where 𝒑 is the desired number of worker threads
  • 𝒒 columns

Each lane is further subdivided into 𝑺 = 4 "slices" (in Argon2 terminology, and referred to as SYNC_POINTS in the code), and the intersection of a slice and a lane forms a segment of length 𝒒 / 𝑺.

Segments of the same slice are computed in parallel and therefore cannot reference each other. So from a memory model perspective, what we'd really like is to mutably borrow the values of a particular slice, partition them into segments, and give each worker thread access to a particular segment.

However, we also need to allow all of the worker threads to simultaneously borrow all of the other blocks which do not belong to the "slice" being operated on to reference as inputs.

This is the tricky part: the fill_segment operation can reference blocks from the current lane, or other lanes, but will not reference blocks from the same "slice" being operated on.

Having just written all of that down (thanks for rubber ducking if nothing else), I think I have a better idea of how to model this problem safely in Rust: "slices" (in the Argon2 sense) should be the core level of granularity in which the working "memory" is organized.

The main loop of the algorithm iterates over the slices. Provided I'm actually understanding this correctly, we can borrow one slice mutably at the time and the others immutably. The mutably borrowed slice can then be subdivided into a segment for each lane, given to the worker threads along with immutable references to all of the other slices.

I think a big part of what's making this so tricky right now is the memory consists of a contiguous Vec<Block>. I think that might still be fine for the backing storage, but perhaps we could mediate access to segments through another type that splits the borrows by Argon2 "slice", allowing one "slice" to be acted on mutably and the others referenced as inputs.

I think a next step which might be helpful in general is to extract a struct Memory which borrows from a backing [Block] slice, pass that to Instance::new instead of the raw &'a mut [Block], and provide a method on Memory for accessing blocks by their Position.

From there we can look at borrow splitting the backing buffer so Memory only holds 3 of the 4 "slices" at a time, and can be used to look up the "reference" blocks being used to fill a segment, but it would not have access to the slice being operated over (which would be borrowed mutably and split up into segments among the worker threads).

Note that after posting this comment, a Memory struct was extracted which is the first step.

The next steps would be using the Memory struct to access Argon2 "slices", then being able to safely split borrows of a mutable slice and immutable slices as outlined above.

argon2: The documentation claims that associated data (and keyid) are deprecated but they are not

Currently, the documentation https://docs.rs/argon2/0.3.2/argon2/struct.Params.html#method.data claims that:

This field is not longer part of the argon2 standard (see: P-H-C/phc-winner-argon2#173), and should not be used for any non-legacy work.

But I don't think that this is true. Notably, the referenced pull request only talks about the encoding, and the reference implementation still supports associated data: https://github.com/P-H-C/phc-winner-argon2/blob/master/include/argon2.h#L204-L205

Happily, #247 fixes this by making it possible to set the associated data.

argon2: support `data` parameter in PHC strings

The Argon2 algorithm supports associated data in addition to a salt, and the PHC string format specifies a data parameter for encoding it into a password hash:

https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md#argon2-encoding

`data`: Associated data. Value is a sequence of 0 to 32 bytes,
 encoded in B64 as 0 to 43 characters. This parameter is optional;
 the default value is the empty sequence (no byte at all). The
 associated data is extra, non-secret value that is included in the
 Argon2 input.

However, the argon2 crate presently does not support this field:

https://github.com/RustCrypto/password-hashes/blob/8fad5a4/argon2/src/lib.rs#L639

It should be added, but lifetime issues made it a bit tricky. It may require upstream changes to the PasswordHasher trait's associated Params type.

balloon-hash: provide `hash_password_into` functionality

I'm in the process of migrating from argon2id to balloon hashing, but I'm unable to do so in a relatively-safe manner.

I relied on argon2's hash_password_into in order to keep track of where the key is, and prevent potential cloning and such. balloon-hash doesn't seem to provide this functionality, and instead returns a GenericArray - which complicates this task further.

What should've been a few lines now requires lots of manual zeroizing, and I just don't think it's a great alternative.

Would it be possible to provide hash_password_into functionality? I had a quick peek into the argon2 crate and it doesn't seem out of scope, but I'm not familiar with the RustCrypto traits, so I don't think it's best for me to attempt.

Thank you.

[Question] Raw output of the Argon2 hash?

Hi there.

I have looked through the docs and I can't seem to find what I am looking for. Is it possible to get the raw output when using the Argon2 hash, when using the default parameters?

I'm specifically looking for any method to get the raw bytes of the hash, using hashed_password_simple doesn't give the output I am looking. I need to get the raw bytes as these will be used as an AES key. The output of the hashed_password_simple function is a string and contains superfluous data (for my intended use case).

If you could point me in the right direction that would be greatly appreciated!

Thanks in advance.

pbkdf2 OutputTooLong error

Trying to use the pbkdf2 algorithm with an output length greater than 64 but I keep getting a OutputTooLong error.

Pbkdf2.hash_password_customized(
    b"password",
    Some(Algorithm::Pbkdf2Sha512.ident()),
    None,
    Params {
        rounds: 100000,
        output_length: 128,
    },
    &SaltString::b64_encode(b"salt").unwrap(),
)
.unwrap();

Error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: OutputTooLong', src/main.rs:17:10
stack backtrace:
   0: rust_begin_unwind
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:142:14
   2: core::result::unwrap_failed
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/result.rs:1785:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/result.rs:1078:23
   4: pbkdf2test::main
             at ./src/main.rs:6:20
   5: core::ops::function::FnOnce::call_once
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

bcrypt_pbkdf: Support passphase that's &[u8] and not &str

The only thing that's done with the passphrase is pass Sha512::digest(passphrase.as_bytes()) so it should be fine to allow it to be arbitrary bytes.

This probably needs to be done by either a) making passphrase's type generic, b) adding a second function

Upgrade to rand 0.7.0

Using this package alongside a project that uses the latest rand crate, and getting an incompatibility:

   Compiling pbkdf2 v0.3.0
error[E0432]: unresolved import `rand::OsRng`
 --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/pbkdf2-0.3.0/src/simple.rs:7:12
  |
7 | use rand::{OsRng, RngCore};
  |            ^^^^^ no `OsRng` in the root

Solution: just upgrade the imports

sha512crypt index out of bounds

The function produce_byte_seq() will cause an index out of bounds panic if the password supplied to sha512_crypt has a length larger than 64 bytes.

Differences to hashes

Please clarify in the README's why this crate is recommended for passwords.
This surprises me especially as this crate, as far as I know, doesn't support pepper.
Therefore, I am interested if there is a security reason to not use something like Blake2b or if it makes it only easier to do everything right.

Argon2 uses wrong value for thread count

Seems like a copy paste error introduced in #213. Error is in line 102:

let mut instance = Instance {
version: context.version,
memory,
passes: context.params.t_cost(),
lane_length,
lanes: context.params.lanes(),
threads: context.params.t_cost(),
alg,
};

Surely the number of threads has nothing to do with t_cost, the number of passes?

It used to use the value of context.threads, which is just parallelism (aka lanes):

let mut instance = Instance {
version: context.version,
memory,
passes: context.t_cost,
lane_length,
lanes: context.lanes,
threads: context.threads,
alg,
};

@tarcieri

sha-crypt: index out of bounds with invalid hashed value input

use sha_crypt::sha512_check;

fn main() {
    let hashed = "$6$rounds=656000$Ykk6fjI2sU3/uprV$Z6yV/9Z741lfroSSzB9MwxSRnGeI9Z74hBkgNsHuojQJxZ9XjPkHg9jqqGLvWZ586wqnSSx5vrXZdhrMSZZE4/";
    assert!(sha512_check("abc", hashed).is_ok());

    let hashed = "$6$rounds=656000$Ykk6fjI2sU3/uprV$Z6yV/9Z741lfroSSzB9MwxSRnGeI9Z74hBkgNsHuojQJxZ9XjPkHg9jqqGLvWZ586wqnSSx5vrXZdhrMSZZE4";
    assert!(sha512_check("abc", hashed).is_err());
}

First assert is OK, second hashed value input misses a / at the end, it will panic with index out of bounds error when running with --release

thread 'main' panicked at 'index out of bounds: the len is 85 but the index is 85', /Users/messense/.cargo/registry/src/github.com-1ecc6299db9ec823/sha-crypt-0.3.0/src/b64.rs:37:37
stack backtrace:
   0: rust_begin_unwind
             at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/std/src/panicking.rs:515:5
   1: core::panicking::panic_fmt
             at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/panicking.rs:92:14
   2: core::panicking::panic_bounds_check
             at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/panicking.rs:69:5
   3: sha_crypt::b64::decode
   4: sha_crypt::sha512_check
   5: sha512_crypt::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

argon2: `Argon2::hash_password` ignores provided configuration

When using Argon::new, and subsequently <Argon as PasswordHasher>::hash_password, the parameters provided in Argon::new are ignored, and default values are used instead:

use argon2::{Argon2, Version, PasswordHasher};

const PASSWORD: &'static str = "password";
const SECRET_KEY: &'static str = "secret_key";
const SALT: &'static str = "longenoughsalt";

let hasher = Argon2::new(
    Some(SECRET_KEY.as_bytes()),
    192,
    8196,
    4,
    Version::V0x10,
).unwrap(); 

hasher
    .hash_password_simple(PASSWORD.as_bytes(), SALT)
    .unwrap()
    .to_string()

// $argon2id$v=19$m=4096,t=3,p=1$longenoughsalt$sqRGsTa4Wz1kLgdImtaf3WfwDAYPp7VZf8wSHfn/KLk
//           ^^^^ ^^^^^^ ^^^ ^^^

WASM/no_std support

I came here from rust-crypto-wasm because of this error.

I wanted to use this crate with a wasm32-unknown-unknown target and wondering is there any possibility to add wasm support?

I faced the following error when I tried to add scrypt:

error: duplicate lang item in crate `std` (which `scrypt` depends on): `panic_impl`.
  |
  = note: first defined in crate `sr_io` (which `runtime` depends on).

error: duplicate lang item in crate `std` (which `scrypt` depends on): `oom`.
  |
  = note: first defined in crate `sr_io` (which `runtime` depends on).

error: aborting due to 2 previous errors

argon2: std feature pulls in rand number generator

I'm not sure to what degree this is expected, but if I enable the std feature in argon2, it pulls in a random number generator via getrandom. This is unfortunately not available in all std environments, especially when compiling to Wasm.

argon2 = { version = "0.3.1", default-features = false, features = ["std"] }

causes a compile fail with target wasm32-unknown-unknown because

$ cargo tree -i getrandom --target wasm32-unknown-unknown
getrandom v0.2.3
└── rand_core v0.6.3
    └── password-hash v0.3.2
        └── argon2 v0.3.1
            └── argon2id-js v0.1.0 (/projects/cosmjs/wasm/argon2id-js)

Seems like password-hash gets pulled in implicitly with default arguments or something like that.

Adding resolver = "2" does not seems to change things.

Using alloc instead lets me compile.

scrypt: Why it takes so long?

  let password = b"asdf1234";
  let salt = SaltString::new("12345123451234561234512345123456").unwrap();
  let params = Params::new(18, 8, 1).unwrap();

  let password_hash = Scrypt.hash_password_customized(password, None, None, params, salt.as_salt()).unwrap();
  println!("{}", password_hash);

I set params to 18_8_1 and run, but it takes over 10000ms to print the result.

Scrypt default parameters

So after looking at a few different argon2 implementations I decided to use scrypt because it's already maintained by this organization.

It looks relatively straightforward to use:

// First setup the ScryptParams arguments with:
// r = 8, p = 1, n = 32768 (log2(n) = 15)
let params = ScryptParams::new(15, 8, 1).unwrap();
// Hash the password for storage
let hashed_password = scrypt_simple("Not so secure password", &params)
    .expect("OS RNG should not fail");
// Verifying a stored password
assert!(scrypt_check("Not so secure password", &hashed_password).is_ok());

But the very first section threw me off, as an experienced web developer without a crypto background.

// --snip
// First setup the ScryptParams arguments with:
// r = 8, p = 1, n = 32768 (log2(n) = 15)
let params = ScryptParams::new(15, 8, 1).unwrap();
// --snip

I stopped and asked myself, what is ScryptParams and why does it take these arbitrary values? Do I need to replace these values with ones of my own for security? How do I know what values are reasonable? 😱

I found a lovely blog post explaining that these are the defaults from the original paper (it also suggests they might need to be revisited?). So for now I'm just going to copy the example from the docs verbatim.

However, I'd like to propose that we could make this API friendlier if we omitted the &params and set it as a default the same way the salt is handled currently.

scrypt: the trait `From<base64ct::Error>` is not implemented for `HasherError`

I updated my dependencies today from scrypt 0.6.1 to 0.6.4 and my build fails now with the following error:

error[E0277]: `?` couldn't convert the error to `HasherError`
  --> /home/demurgos/.cargo/registry/src/github.com-1ecc6299db9ec823/scrypt-0.6.4/src/simple.rs:78:49
   |
78 |                 let pvec = Base64::decode_vec(p)?;
   |                                                 ^ the trait `From<base64ct::Error>` is not implemented for `HasherError`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following implementations were found:
             <HasherError as From<B64Error>>
             <HasherError as From<OutputError>>
             <HasherError as From<ParamsError>>
             <HasherError as From<base64ct::errors::InvalidLengthError>>
             <HasherError as From<password_hash::ParseError>>
   = note: required by `from`

error[E0277]: `?` couldn't convert the error to `HasherError`
  --> /home/demurgos/.cargo/registry/src/github.com-1ecc6299db9ec823/scrypt-0.6.4/src/simple.rs:85:49
   |
85 |                 let pvec = Base64::decode_vec(p)?;
   |                                                 ^ the trait `From<base64ct::Error>` is not implemented for `HasherError`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following implementations were found:
             <HasherError as From<B64Error>>
             <HasherError as From<OutputError>>
             <HasherError as From<ParamsError>>
             <HasherError as From<base64ct::errors::InvalidLengthError>>
             <HasherError as From<password_hash::ParseError>>
   = note: required by `from`

This may be caused by a mismatch between the base64ct versions:

  • scrypt resolves base64ct 1.0.0
  • scrypt resolves also password-hash 0.1.1 which resolves base64ct 0.2.0

Accelerate scrypt using SIMD

scrypt spends most of the time in salsa20_8 function, which can be significantly accelerated using explicit SIMD.

scrypt: parallel implementation

Looking at the source code, it seems this crate always uses a sequential algorithm and only one core, even when the scrypt parameter p is larger than 1. For p>1, the derivation could be made faster by using a parallel algorithm. Are there plans to implement this?

pbkdf2 with nodejs crypto library

I'm trying to use pbkdf2 (rust) together with pbdkf2 (node) but no matter what I try I can't seem to get the output hashes to match up. I know the input password is the same as I've compared them and the algorithm, length, rounds, are all the same. I suspect it might be the way that they are decoding the salts which are different?

If anyone has experience with this and can help I'd really appreciate it.

add bcrypt_simple and bcrypt_check

These two functions are conspicuously missing from bcrypt-pbkdf2 compared to pbkdf2 and scrypt. It would be nice to have them to not have to worry about password string encoding or constant-time equality.

Consider adding algorithm primers

I'm writing a server boilerplate that I hope to eventually use in production, right now it's just for fun. One of the things I'd like to do is store user accounts (and password digests!) in my database.

I noticed y'all have three algorithms listed but no guidance about how to choose one for the naive 🙋‍♂️ . Would it be reasonable to provide a primer about each algorithm and what settings it might be appropriate it?

argon2: Panic with invalid salt

The following code:

fn main() {
    use argon2::PasswordHasher as _;
    let password_hasher = argon2::Argon2::default();

    let _ = password_hasher.hash_password(
        b"password1",
        None,
        None,
        argon2::Params::default(),
        argon2::password_hash::Salt::new("somesalt").unwrap(),
    );
}

panics with

thread 'main' panicked at 'internal error: entered unreachable code', /home/cr/.cargo/registry/src/github.com-1ecc6299db9ec823/argon2-0.1.2/src/lib.rs:583:30

Which is from this expression:

let output = password_hash::Output::init_with(params.output_length, |out| {
hasher
.hash_password_into(algorithm, password, salt_bytes, ad, out)
.map_err(|e| {
match e {
Error::OutputTooShort => password_hash::OutputError::TooShort,
Error::OutputTooLong => password_hash::OutputError::TooLong,
// Other cases are not returned from `hash_password_into`
// TODO(tarcieri): finer-grained error types?
_ => unreachable!(),
}
})
})?;
, the actual error type here is argon2::Error::SaltTooShort

scrypt documentation

  • Add usage example
  • Describe valid values for ScryptParams::new()
  • Add docs for errors module and errors themselves

argon2: test against full set of vectors from reference implementation

Presently the argon2 crate tests include Known Answer Tests (KAT) and some PHC string tests.

However, the test.c file from the Argon2 reference implementation includes a large number of test vectors which we don't presently test against.

We should incorporate all of these test vectors into the argon2 crate's test suite.

Evaluate tobtu.com minimum password settings recommendations

This guide enumerates the minimum settings required to slow attackers to <10 kH/s/GPU (using RTX 3080 or RX 6800 XT as reference GPUs) for various algorithms we implement:

https://tobtu.com/minimum-password-settings/

It might be a good idea to incorporate them into our documentation and/or use them to inform our recommendations/defaults.

Argon2

  • Argon2{id,d}: m=44*1024 (44 MiB), t=1, p=1
  • Argon2{id,d}: m=18*1024 (18 MiB), t=2, p=1
  • Argon2: m=11*1024 (11 MiB), t=3, p=1
  • Argon2: m=8*1024 (8 MiB), t=4, p=1
  • Argon2: m=7*1024 (7 MiB), t=5, p=1

In general:

Argon2i: m≥89062.5/(3*t-1)*α, t≥3, p=1
Argon2{id,d}: m≥89062.5/(3*t-1)*α, t≥1, p=1
RTX 3080 12GB memory bandwidth: 89,062.5 = 912,000,000,000/10,000/1024
For low memory usage (≲64 MiB) α≈95%. Once memory usage is high enough α drops proportional to memory increase.

scrypt

  • N=2^17 (128 MiB), r=8, p=1
  • N=2^16 (64 MiB), r=8, p=2
  • N=2^15 (32 MiB), r=8, p=3
  • N=2^14 (16 MiB), r=8, p=5
  • N=2^13 (8 MiB), r=8, p=9

In general:

scrypt: N≥570000/r/p*α, r=8, p≥1
RTX 3080 12GB memory bandwidth: 570,000 = 912,000,000,000/10,000/128/1.25
For low memory usage (≲64 MiB) α≈95%. Once memory usage is high enough α drops proportional to memory increase.

PBKDF2

  • PBKDF2-HMAC-SHA512: 130,000 iterations (Based on RTX 3080 12GB)
  • PBKDF2-HMAC-SHA256: 350,000 iterations (Based on RX 6800 XT)
  • PBKDF2-HMAC-SHA1: 860,000 iterations (Based on RX 6800 XT)

scrypt: use salsa20 crate?

The salsa20 v0.5.0 crate now contains an implementation of Salsa20/8:

https://docs.rs/salsa20/latest/salsa20/type.Salsa8.html

Screen Shot 2020-06-06 at 10 36 10 AM

I noticed the scrypt crate presently vendors its own. I'm not sure the APIs in the salsa20 crate are sufficient to implement scrypt with it yet (it appears to require direct access to the Salsa core function?) but I think it might be interesting to try migrating it, especially if we were ever to add SIMD optimizations to the salsa20 crate (see RustCrypto/stream-ciphers#50).

We could potentially add a salsa-core cargo feature to the salsa20 crate to expose the core function.

Make easier to support multiple algos?

I try to support the selection of many algorithms to store passwords (like in django) and found it not as easy to do it. This crate has all in a workspace but not a way to select a group alike:

# Ideally:
password-hash = { version = "*",  features = ["argon2", "scrypt"] }

# Today
# All sub-crate reexport dependencies, so I need to manually re-add all?
argon2 = { version = "0.3", features = ["std"] ,  optional=true}
scrypt = {version = "0.8.0",  optional=true"}

# So I can do things generically...
password-hash = "*"
rand-core = "*"

[Q] High CPU usage

Hi there,

first of all: thank you for the nice crate!

But there is one thing that I don't get. I've used an scrypt implementation in Java with the same provided settings as you have mentioned in the documentation (15, 8, 1).
The Java implementation is using a lot of memory and some CPU resources. This is what I expected with the given settings.
When I use the rust version it will consume a lot of CPU, but almost no RAM.

I've setup a load test that will create millions of scrypt hashes and the application is just consuming around 60-80m RAM, but ~1600MHz.
Just for the comparison the Java version with almost the same settings consumes 1500m RAM and ~800MHz.

I am using the simple_crypt() function.

Thank you for any kind of response/help :)

Setting the generated hash length for Scrypt

Hey all 👋
I've been using the scrypt package from RustCrypto in a project but recently I hit a small roadblock since I can't seem to find any way of setting the generated hash's length within the module.

Is there a way of doing this? and if not could I help with implementing a way?

Thanks in advance,
Bradley Schofield

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.