Which pbkdf2 to use?

As I understand rust-crypto is the official source for cryptographic functions for Rust. It provides a pbkdf2 function.

However, the Rust Cookbook, which I understand to be a somewhat official source as well, uses the ring::pbkdf2 function from https://briansmith.org/rustdoc/ring/.

And then there's also a pbkdf2 crate.

rust-crypto is unmaintained, so it's strongly recommended to avoid it.

If you only need PBKDF2, then I would recommend to use the pbkdf2 crate, since it's a lightweight pure-Rust dependency (disclaimer: it's part of the RustCrypto project and I am one of its maintainers).

ring is a good option if you already have it in your dependency tree (e.g. via rustls) and if you absolutely want to squeeze the last drop of performance (ring uses assembly and C inherited from BoringSSL, so it's a bit more performant than the pure Rust implementation), but it has downsides of relying on non-Rust code (e.g. it's less portable and harder to cross-compile).

1 Like

Ooooh, now I understand.

rust-crypto, with all these modules:

image

is an old monolithic crate. It's unmaintained, which is why the last update was 2016. It is basically the predecessor to the separate crates maintained by https://github.com/RustCrypto, for example these:

image

Those are alive and well. One of those is the pbkdf2 crate.

Correct?


I'm not sure yet. I also need to do AES-CBC, preferably with AES hardware detection. I haven't found out yet how to do AES-CBC with ring.

1 Like

Yes.

ring principally supports only a relatively small list of cryptographic algorithms and does not expose "dangerous" low-level primitives (such as unauthenticated encryption), so you will not be able to use AES-CBC with it.

Take a look at block-modes and aes. The latter one does support AES-NI hardware acceleration, but at the moment it can switch only at compile time, see this issue for more information.

Can I do my own hardware detection? Something like this?

#[target_feature(enable = "aes")]
fn decrypt_with_hardware(cipher: Aes128Cbc, ciphertext: &[u8]) -> Vec<u8> {
    cipher.decrypt_vec(&ciphertext).unwrap()
}

fn decrypt_without_hardware(cipher: Aes128Cbc, ciphertext: &[u8]) -> Vec<u8> {
    cipher.decrypt_vec(&ciphertext).unwrap()
}

if is_x86_feature_detected!("aes") {
    plaintext = decrypt_with_hardware(cipher, &ciphertext);
} else {
    plaintext = decrypt_without_hardware(cipher, &ciphertext);
}

Unfortunately, no. Currently cargo does not provide a way to compile a dependency crate several times with different compiler flags.

I could require both aes-soft and aesni and then call into them depending on is_x86_feature_detected!("aes")? But I would have to force aesni to assume the aes feature is there.

Note that you would have enable not only aesni target feature, but also several SIMD-related ones, which with high probability will influence code generation in other parts of your project.

And why is that not a concern when I just use the aes crate? Sorry, I don't fully understand Rust's target feature system yet.

Because if you will not enable all required features, aes will use the bitsliced fallback.

1 Like