For random values generation Rust ecosystem has the rand
crate, providing unified interface and numerous random values generator implementations with various statistical quality and performance guarantees.
The Rust Rand Book not only explains how to use rand
crate primitives, but also makes a good intro to the basics of random values generation problem and how it's solved in a modern world. Read through it to understand what primitives you should use for different situations:
- when performance is a goal;
- when cryptographical security and good statical quality is a goal;
- what is good for general purpose.
One of the most common cases when you need to deal with generating random values is a generation of universally unique identifiers (such as UUID). Fortunately, Rust has the uuid
crate already, which implements all versions of UUID specification.
More reading:
While at the moment Rust doesn't have The Cryptographic Library, its ecosystem contains a bunch of well implemented (and still maturing) crates for different purposes.
ring
library implements a core set of cryptographic operations exposed via an easy-to-use (and hard-to-misuse) API. It started as a subset of famous BoringSSL library ("ring" is a substring of "Bo_ring_SSL"), so inherits some its code and regularly merges changes from it.
ring
is focused on a general-purpose cryptography. If you need just raw cryptography primitives - that is the way to go. Use it when you need to create:
- digital signature;
- simply encrypt plain data;
- key derivation;
- and so on...
If you need more high-level implementations (like WebPKI X.509 certificate validation, or cryptographic protocols like TLS, SSH) consider to use other crates (which are often built on top of ring
).
While ring
is focused on providing general-purpose cryptography primitives, dalek crates provide only few, but are focused to implement the best theoretical primitives.
If you're going to build something that uses just some high-end cryptographic primitives (like using Curve25519 for signing and verification) you should give dalek a try.
AWS Libcrypto
aws-lc-rs
is a ring
-compatible crypto library using the cryptographic operations provided by AWS-LC.
The motivation provided by authors is quite self-explanatory:
Rust developers increasingly need to deploy applications that meet US and Canadian government cryptographic requirements. We evaluated how to deliver FIPS validated cryptography in idiomatic and performant Rust, built around our AWS-LC offering. We found that the popular
ring
library fulfilled much of the cryptographic needs in the Rust community, but it did not meet the needs of developers with FIPS requirements. Our intention is to contribute a drop-in replacement forring
that provides FIPS support and is compatible with thering
API. Rust developers with prescribed cryptographic requirements can seamlessly integrateaws-lc-rs
into their applications and deploy them into AWS Regions.
More reading:
The basic collection of raw cryptographic hash functions is introduced in RustCrypto/hashes crates collection.
DO NOT use them for password hashing! Consider to use some password hashing algorithm instead (Argon2, bcrypt, scrypt or PBKDF2).
There is the similar RustCrypto/password-hashing crates' collection for password hashing.
However, it lacks implementation for Argon2 and bcrypt algorithms, so those should be found and chosen on your choice. For Argon2 the rust-argon2
crate seems to be the most mature one at the moment.
For constant-time comparison in Rust consider to use subtle
crate from dalek.
For TLS usage Rust ecosystem currently has two common solutions:
native-tls
crate is an abstraction over platform-specific TLS implementations. It uses SChannel on Windows (via schannel
crate), Secure Transport on OSX (via security-framework
crate), OpenSSL on all other platforms (via openssl
crate), and provides a unified interface for using these libraries.
While this solution requires external non-Rust libraries to be present, it's a stable solution based on production-grade TLS implementations.
rustls
crate is a pure-Rust implementation of TLS. It's built on top of ring
and webpki
crates.
Despite the fact it's quite a feature rich solution, it lacks good support for old and legacy cryptography and has no stable version yet. Consider to use it when the legacy is non-concern for you.
- Sylvain Kerkour: Overview of the Rust cryptography ecosystem (Tue, Aug 24, 2021)
- Cheatsheat on cyphering, hashing adn security
Estimated time: 1 day
Implement the following functions:
generate_password()
: generates random password of given length and symbols set;select_rand_val()
: retrieves random element from a given slice;new_access_token()
: generates unique cryptographically secure random value ina-zA-Z0-9
symbols set and has exactly64
symbols.get_file_hash()
: returns SHA-3 hash of a file specified by its path.hash_password()
: returns Argon2 password hash for a given password.
After completing everything above, you should be able to answer (and understand why) the following questions:
- What is the main trade-off of generating random numbers? How is it applied in practice?
- What is symmetric cryptography? What is asymmetric cryptography? Which benefits does each one have?
- What is signing in asymmetric cryptography? What is encryption in asymmetric cryptography? How do they work given the same private and public keys?
- What is hash function? What is password hashing? Why is it not enough to use just a raw hash function for password hashing?
- What is constant-time comparison? When and why it should be used?
- Which are options of using TLS in Rust? Which advantages and disadvantages does each one have?