# 加密

### 使用 PBKDF2 对密码进行哈希和加盐( salt )

ring::pbkdf2 可以对一个加盐密码进行哈希。

    use data_encoding::HEXUPPER;
    use ring::error::Unspecified;
    use ring::rand::SecureRandom;
    use ring::{digest, pbkdf2, rand};
    use std::num::NonZeroU32;

    fn main() -> Result<(), Unspecified> {
        const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
        let n_iter = NonZeroU32::new(100_000).unwrap();
        let rng = rand::SystemRandom::new();

        let mut salt = [0u8; CREDENTIAL_LEN];
        // 生成 salt: 将安全生成的随机数填入到字节数组中
        rng.fill(&mut salt)?;

        let password = "Guess Me If You Can!";
        let mut pbkdf2_hash = [0u8; CREDENTIAL_LEN];
        pbkdf2::derive(
            pbkdf2::PBKDF2_HMAC_SHA512,
            n_iter,
            &salt,
            password.as_bytes(),
            &mut pbkdf2_hash,
        );
        println!("Salt: {}", HEXUPPER.encode(&salt));
        println!("PBKDF2 hash: {}", HEXUPPER.encode(&pbkdf2_hash));

        // `verify` 检查哈希是否正确
        let should_succeed = pbkdf2::verify(
            pbkdf2::PBKDF2_HMAC_SHA512,
            n_iter,
            &salt,
            password.as_bytes(),
            &pbkdf2_hash,
        );
        let wrong_password = "Definitely not the correct password";
        let should_fail = pbkdf2::verify(
            pbkdf2::PBKDF2_HMAC_SHA512,
            n_iter,
            &salt,
            wrong_password.as_bytes(),
            &pbkdf2_hash,
        );

        assert!(should_succeed.is_ok());
        assert!(!should_fail.is_ok());

        Ok(())
    }