首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HKDF与锈蚀中常数时间的比较

HKDF与锈蚀中常数时间的比较
EN

Code Review用户
提问于 2018-03-22 12:55:59
回答 1查看 344关注 0票数 4

我在Rust中实现了HKDF,它通过了RFC 5869的所有测试向量,使用HKDF和HMAC-SHA256 256。我也有一个函数来比较字节数组在恒定的时间,我希望有人可以确认是正确的。欢迎任何形式的反馈。

编辑:我主要是指对hkdf_compute()的反馈。hkdf_extract()中的HMAC是在另一个模块中定义的,此处不包括。

香港

代码语言:javascript
复制
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
  }
}

比较常数时间:

代码语言:javascript
复制
#[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
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2018-05-09 14:06:07

通常,对于任何特定于密码的代码,您都应该尝试避免浮点操作。浮点数在精度方面有问题,甚至我也没有看到这个特定代码的任何问题,它们总是需要特别注意,例如在代码的检查过程中。

同样,对于加密算法,也强烈建议使用递归代码。如果您的代码可以使用循环(只使用局部变量)进行编码,那么您确实应该这样做。我认为这有悖于Rust的概念(因此值得讨论),但是密码通常需要特别注意。如果您一直使用递归调用,请确保将它们记录为递归调用,包括内联调用和函数描述。

虽然您很好地实现了Drop析构函数,但是创建一个仅使用keyInputMaterial (现在称为data )的类或者将所有数据保存在参数/局部变量中更有意义。只保留keyInputMaterial的思想是,您可以重用对象来使用函数派生其他键,但使用的是不同的salt / info。在这种情况下,您显然需要重新培训Drop以清除输入键材料。

注意,HMAC的内部密钥处理(填充、初始散列)总是相同的。因此,偷偷地加快速度是对充当HMAC键的盐类执行预计算(如果预期有大量输出,这个加速比对PBKDF2来说更重要)。

你的恒定时间函数看起来非常正常,这在这个例子中是很棒的:)我不认为HKDF需要使用一个随机键来比较HMAC(k, x)HMAC(k, y) --但是现在你知道了这个巧妙的小技巧。

请注意,您可能希望确保您需要在恒定时间内完成比较,或者将其包含在验证函数中(注意截断的值--您在代码中这样做了,但是您也需要在调用代码中考虑!)。

请注意,我不是锈蚀专家,所以我不会评论向量处理/切片等。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/190204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档