我在Rust中实现了HKDF,它通过了RFC 5869的所有测试向量,使用HKDF和HMAC-SHA256 256。我也有一个函数来比较字节数组在恒定的时间,我希望有人可以确认是正确的。欢迎任何形式的反馈。
编辑:我主要是指对hkdf_compute()的反馈。hkdf_extract()中的HMAC是在另一个模块中定义的,此处不包括。
pub struct Hkdf {
pub salt: Vec<u8>,
pub data: Vec<u8>,
pub info: Vec<u8>,
pub hmac: usize,
pub length: usize,
}
impl Drop for Hkdf {
fn drop(&mut self) {
//println!("DROPPING");
self.salt.clear();
self.data.clear();
self.info.clear()
}
}
impl Hkdf {
/// Return HMAC matching argument passsed to Hkdf.
pub fn hkdf_extract(&self, data: &[u8], salt: &[u8]) -> Vec<u8> {
let hmac_res = Hmac {
secret_key: salt.to_vec(),
message: data.to_vec(),
sha2: self.hmac
};
hmac_res.hmac_compute()
}
/// The HKDF Expand step. Returns an HKDF.
pub fn hkdf_compute(&self) -> Vec<u8> {
// Check that the selected key length is within the limit.
if self.length as f32 > 255_f32 * (self.hmac / 8) as f32 {
panic!("Derived key length above max. 255 * (HMAC OUTPUT LENGTH IN BYTES)");
}
let n_iter = (self.length as f32 / (self.hmac / 8) as f32).ceil() as usize;
let mut con_step: Vec<u8> = vec![];
let mut t_step: Vec<u8> = vec![];
let mut hkdf_final: Vec<u8> = vec![];
for x in 1..n_iter+1 {
con_step.append(&mut t_step);
con_step.extend_from_slice(&self.info);
con_step.push(x as u8);
t_step.extend_from_slice(&self.hkdf_extract(
&con_step,
&self.hkdf_extract(&self.data, &self.salt))
);
con_step.clear();
hkdf_final.extend_from_slice(&t_step);
}
hkdf_final.truncate(self.length);
hkdf_final
}
}#[inline(never)]
/// Comparison in constant time.
pub fn compare_ct(x: &[u8], y: &[u8]) -> bool {
let length = x.len();
if length != y.len() {
false;
}
let mut result: u8 = 0;
for n in 0..length {
result |= x[n] ^ y[n];
}
result == 0
}发布于 2018-05-09 14:06:07
通常,对于任何特定于密码的代码,您都应该尝试避免浮点操作。浮点数在精度方面有问题,甚至我也没有看到这个特定代码的任何问题,它们总是需要特别注意,例如在代码的检查过程中。
同样,对于加密算法,也强烈建议使用递归代码。如果您的代码可以使用循环(只使用局部变量)进行编码,那么您确实应该这样做。我认为这有悖于Rust的概念(因此值得讨论),但是密码通常需要特别注意。如果您一直使用递归调用,请确保将它们记录为递归调用,包括内联调用和函数描述。
虽然您很好地实现了Drop析构函数,但是创建一个仅使用keyInputMaterial (现在称为data )的类或者将所有数据保存在参数/局部变量中更有意义。只保留keyInputMaterial的思想是,您可以重用对象来使用函数派生其他键,但使用的是不同的salt / info。在这种情况下,您显然需要重新培训Drop以清除输入键材料。
注意,HMAC的内部密钥处理(填充、初始散列)总是相同的。因此,偷偷地加快速度是对充当HMAC键的盐类执行预计算(如果预期有大量输出,这个加速比对PBKDF2来说更重要)。
你的恒定时间函数看起来非常正常,这在这个例子中是很棒的:)我不认为HKDF需要使用一个随机键来比较HMAC(k, x)和HMAC(k, y) --但是现在你知道了这个巧妙的小技巧。
请注意,您可能希望确保您需要在恒定时间内完成比较,或者将其包含在验证函数中(注意截断的值--您在代码中这样做了,但是您也需要在调用代码中考虑!)。
请注意,我不是锈蚀专家,所以我不会评论向量处理/切片等。
https://codereview.stackexchange.com/questions/190204
复制相似问题