关于加密:使用PBKDF2密钥派生用rust-crypto正确创建用户可读的盐

Using PBKDF2 key derivation to properly create user-readable salt with rust-crypto

我目前正在为标准文件创建客户端,这涉及使用PBKDF2来提高安全性。 我正在使用rust-crypto,尽管我已经尝试过ring和rust-openssl。

首先,您通过/auth/param端点从服务器检索盐,成本和版本号。 我已经将这些序列化为Serde的结构。

1
2
3
4
5
6
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PWHash {
    pub pw_salt: String,
    pub pw_cost: u32,
    pub version: String,
}

我看过的以前的客户端是使用Python实现的,其中PBKDF2函数似乎都接受字符串。 但是,对于具有Rust的PBKDF2,它们都接受&[u8]作为参数。

我在调用函数时使用.as_bytes(),然后在str::from_utf8上输出派生键。 但是,这样做时会失败,并显示Err(Utf8Error { valid_up_to: 0, error_len: Some(1) })

这是一个代码片段:

1
2
3
4
5
6
7
pub fn hashcompute(&self, password: String) {
    let mut dk = [0u8; 768]; // derived key
    let mut mac = Hmac::new(Sha512::new(), password.as_bytes());
    pbkdf2::pbkdf2(&mut mac, self.pw_salt.as_bytes(), self.pw_cost, &mut dk);

    println!("{:?}", str::from_utf8(&dk));
}

甚至String::from_utf8_lossy都返回不可读字符的结果。

如何正确格式化Rust字符串以正确使用密码? 还有另一个功能正常的库吗? 还是这是一个失败的原因?


根据标准文件文档,密钥应为十六进制编码(请参见代码示例中的注释)。 所以这样的事情应该工作:

1
2
3
4
5
6
7
8
9
10
extern crate rustc_serialize as serialize;
use serialize::hex::{FromHex, ToHex};

pub fn hashcompute(&self, password: String) {
    let mut dk = [0u8; 768]; // derived key
    let mut mac = Hmac::new(Sha512::new(), password.as_bytes());
    pbkdf2::pbkdf2(&mut mac, self.pw_salt.from_hex().unwrap(), self.pw_cost, &mut dk);

    println!("{}", dk.to_hex());
}

请注意,我还使用了from_hex将盐从字符串转换为&[u8],因为看起来盐也应该进行十六进制编码。