HKDF и сравнить постоянные времени в Русте


Я реализовал HKDF в Русте, который проходит все тестовые векторы из RFC 5869, используя HKDF с помощью HMAC-SHA256 для. У меня также есть функция для сравнения массивов байтов в постоянном времени, которое, я надеюсь, кто-нибудь может подтвердить, правильно сделали. Любой тип обратной связи можно только приветствовать.

Редактировать: я в основном имею в виду отзывы о hkdf_compute(). HMAC в hkdf_extract() определена в другом модуле и не включены здесь.

HKDF

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
}


179
4
задан 22 марта 2018 в 12:03 Источник Поделиться
Комментарии
1 ответ

В общем, вы должны попробовать и избежать операций с плавающей точкой для любого криптографически определенный код. Плавающей точки имеют вопросы касаемо точности, и даже я не вижу никакой проблемы для этого конкретного кода, они всегда требуют особого внимания, например, при рецензировании кода.

Аналогичным образом, используя рекурсивный код настоятельно не рекомендуется для криптографических алгоритмов. Если ваш код может быть закодирован с помощью циклов и только локальные переменные, вы должны действительно сделать это. Я представляю, что идет вразрез с идеей ржавчины (и, следовательно, для дебатов), но код шифрования, как правило, требует особого внимания. Если вы держите в рекурсивных вызовов, убедитесь, что вы их как такие, как линейно, так и в описании функции.

Хотя вы прекрасно реализовали Drop деструктор имеет больше смысла, чтобы создать класс с keyInputMaterial (сейчас называется data Я предполагаю) или просто сохранить все данные в параметры / локальные переменные. Идея просто держать keyInputMaterial что вы можете повторно использовать объект , чтобы получить другие ключи с помощью функции но с другой солью / информация. В таком случае вы, очевидно, нужно переучивать Drop чтобы очистить входной ключевой материал.

Обратите внимание, что внутренние ключи в руки (прокладка, начальная хэширования) из ксом всегда одинаков. Поэтому скорость подлый вверх, чтобы выполнить предварительный расчет на соль, которая выступает в качестве ключа HMAC (особенно полезен, если есть большое ожидаемый результат, это ускорение имеет большее значение, например, стандарт PBKDF2).


Ваша постоянная времени функция выглядит очень запустить-из-в-мельница постоянной времени, которая в данном случае отлично подходит :) я не думаю, что HKDF гарантирует функция, где HMAC(k, x) и HMAC(k, y) по сравнению с использованием случайного ключа - но теперь вы знаете о том, что аккуратный маленький трюк.

Обратите внимание, что вам может понадобиться, чтобы убедиться, что Вы документ , что сравнение должно быть сделано в постоянное время или включить его в убедитесь, функция (остерегайтесь усе значения - вы сделали это в ваш код, но вы должны рассмотреть его в вызывающем коде, как хорошо!).


Обратите внимание, что я не эксперт ржавчины, поэтому я не буду комментировать вектора обработки / нарезки и т. д.

2
ответ дан 9 мая 2018 в 02:05 Источник Поделиться