Module ring::pbkdf2 [−][src]
PBKDF2 derivation and verification.
Use derive
to derive PBKDF2 outputs. Use verify
to verify secret
against previously-derived outputs.
PBKDF2 is specified in RFC 2898 Section 5.2 with test vectors given in RFC 6070. See also NIST Special Publication 800-132.
Examples
Password Database Example
use ring::{digest, pbkdf2}; use std::{collections::HashMap, num::NonZeroU32}; static PBKDF2_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256; const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; pub type Credential = [u8; CREDENTIAL_LEN]; enum Error { WrongUsernameOrPassword } struct PasswordDatabase { pbkdf2_iterations: NonZeroU32, db_salt_component: [u8; 16], // Normally this would be a persistent database. storage: HashMap<String, Credential>, } impl PasswordDatabase { pub fn store_password(&mut self, username: &str, password: &str) { let salt = self.salt(username); let mut to_store: Credential = [0u8; CREDENTIAL_LEN]; pbkdf2::derive(PBKDF2_ALG, self.pbkdf2_iterations, &salt, password.as_bytes(), &mut to_store); self.storage.insert(String::from(username), to_store); } pub fn verify_password(&self, username: &str, attempted_password: &str) -> Result<(), Error> { match self.storage.get(username) { Some(actual_password) => { let salt = self.salt(username); pbkdf2::verify(PBKDF2_ALG, self.pbkdf2_iterations, &salt, attempted_password.as_bytes(), actual_password) .map_err(|_| Error::WrongUsernameOrPassword) }, None => Err(Error::WrongUsernameOrPassword) } } // The salt should have a user-specific component so that an attacker // cannot crack one password for multiple users in the database. It // should have a database-unique component so that an attacker cannot // crack the same user's password across databases in the unfortunate // but common case that the user has used the same password for // multiple systems. fn salt(&self, username: &str) -> Vec<u8> { let mut salt = Vec::with_capacity(self.db_salt_component.len() + username.as_bytes().len()); salt.extend(self.db_salt_component.as_ref()); salt.extend(username.as_bytes()); salt } } fn main() { // Normally these parameters would be loaded from a configuration file. let mut db = PasswordDatabase { pbkdf2_iterations: NonZeroU32::new(100_000).unwrap(), db_salt_component: [ // This value was generated from a secure PRNG. 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a ], storage: HashMap::new(), }; db.store_password("alice", "@74d7]404j|W}6u"); // An attempt to log in with the wrong password fails. assert!(db.verify_password("alice", "wrong password").is_err()); // Normally there should be an expoentially-increasing delay between // attempts to further protect against online attacks. // An attempt to log in with the right password succeeds. assert!(db.verify_password("alice", "@74d7]404j|W}6u").is_ok()); }
Structs
Algorithm | A PBKDF2 algorithm. |
Statics
PBKDF2_HMAC_SHA1 | PBKDF2 using HMAC-SHA1. |
PBKDF2_HMAC_SHA256 | PBKDF2 using HMAC-h. |
PBKDF2_HMAC_SHA384 | PBKDF2 using HMAC-SHA384. |
PBKDF2_HMAC_SHA512 | PBKDF2 using HMAC-SHA512. |
Functions
derive | Fills |
verify | Verifies that a previously-derived (e.g., using |