Двадцать известный тест ответа - PullRequest
3 голосов
/ 09 апреля 2019

Я пытаюсь использовать twofish для шифрования строк данных. Прежде чем доверить мои драгоценные данные неизвестной библиотеке, я хочу убедиться, что она соответствует тестам с известным ответом , опубликованным на веб-сайте Брюса Шнайера.

К моему ужасу, я попробовал три двойных реализации и не нашел ни одной, которая бы соответствовала KAT Это заставляет меня поверить, что я делаю что-то не так, и мне интересно, может ли кто-нибудь сказать мне, что это такое.

Я убедился, что режим одинаков (CBC), длина ключа одинакова (128 бит), а значения iv / key / pt одинаковы. Есть ли в игре дополнительный параметр для двойного шифрования?

Вот первые две тестовые записи из CBC_E_M.txt из архива KAT:

I=0
KEY=00000000000000000000000000000000
IV=00000000000000000000000000000000
PT=00000000000000000000000000000000
CT=3CC3B181E1495D0495D652B66921DA0F

I=1
KEY=3CC3B181E1495D0495D652B66921DA0F
IV=3CC3B181E1495D0495D652B66921DA0F
PT=BE938D30FAB43B71F2E114E9C0529299
CT=695250B109C6F71D410AC38B0BBDA3D2

Я интерпретирую их как шестнадцатеричные, поэтому 16 байтов = 128 бит в длину.

Я пытался использовать следующие две реализации:

Все три дают один и тот же CT для первого теста, а именно (в шестнадцатеричном коде)

9f589f5cf6122c32b6bfec2f2ae8c35a

Пока все хорошо, кроме того, что не согласен с CT0 в KAT ...

Для второго теста библиотека ruby ​​и онлайн-инструмент дают:

f84268f0293adf4d24e27194911a24c

Пока библиотека js выдает:

fd803b310bb5388ddb76d5faf9e23dbe

И ни один из них не согласуется с CT1 в КАТ.

Я что-то здесь не так делаю? Любая помощь с благодарностью.

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

def twofish_encrypt(iv_hex, key_hex, data_hex)
  iv = iv_hex.gsub(/ /, "").scan(/../).map { |x| x.hex.chr }.join
  key = key_hex.gsub(/ /, "").scan(/../).map { |x| x.hex.chr }.join
  data = data_hex.gsub(/ /, "").scan(/../).map { |x| x.hex.chr }.join

  tf = Twofish.new(key, :mode => :cbc, :padding => :none)
  tf.iv = iv
  enc_data = tf.encrypt(data)
  enc_data.each_byte.map { |b| b.to_s(16) }.join
end

ct0 = twofish_encrypt("00000000000000000000000000000000",
                      "00000000000000000000000000000000",
                      "00000000000000000000000000000000")
puts "ct0: #{ct0}"
ct1 = twofish_encrypt("3CC3B181E1495D0495D652B66921DA0F",
                      "3CC3B181E1495D0495D652B66921DA0F",
                      "BE938D30FAB43B71F2E114E9C0529299")
puts "ct1: #{ct1}"
function twofish_encrypt(iv_hex, key_hex, data_hex) {
    var iv = new BinData()                             
    iv.setHexNibbles(iv_hex)
    iv.setlength(16*8)
    binkey = new BinData()
    binkey.setHexNibbles(key_hex)
    binkey.setlength(16*8)
    key = new TwoFish.Key(binkey);

    data = new BinData()
    data.setHexNibbles(data_hex)
    data.setlength(16*8)

    cipher = new TwoFish.Cipher(TwoFish.MODE_CBC, iv);
    enc_data = TwoFish.Encrypt(cipher, key, data);

    return enc_data.getHexNibbles(32);
}

var ct0 = twofish_encrypt("00000000000000000000000000000000",
                          "00000000000000000000000000000000",
                          "00000000000000000000000000000000");
console.log("ct0: " + ct0);

var ct1 = twofish_encrypt("3CC3B181E1495D0495D652B66921DA0F",
                          "3CC3B181E1495D0495D652B66921DA0F",
                          "BE938D30FAB43B71F2E114E9C0529299");
console.log("ct1: " + ct1);

1 Ответ

3 голосов
/ 10 апреля 2019

Заголовок файла CBC_E_M.txt гласит:

Режим цепочки блоков шифрования (CBC) - ШИФРОВАНИЕ
Тест Монте-Карло

Путаница может бытьобъяснено этим описанием;из описания NIST тестов Монте-Карло :

Каждый тест Монте-Карло состоит из четырех миллионов циклов в реализации алгоритма-кандидата.Эти циклы разделены на четыреста групп по 10 000 итераций в каждой.Каждая итерация состоит из обработки входного блока с помощью алгоритма-кандидата, в результате чего получается выходной блок.На 10 000-м цикле в итерации новые значения присваиваются переменным, необходимым для следующей итерации.Результаты каждого 10 000-го цикла шифрования или дешифрования записываются и включаются отправителем в соответствующий файл.

Таким образом, вы получаете в текстовом файле 400 результатов, каждая из которых представляет 10 000 итераций, где каждый вводитерации зависит от результатов предыдущих итераций.Это явно не то же самое, что одиночное шифрование.Тесты Монте-Карло в основном выполняют множество тестов с использованием рандомизированного ввода;в этом случае для выполнения рандомизации используется большое количество блочных шифров.


Чтобы проверить правильность кода CBC, просто используйте любой из других тестовых векторов (не Монте-Карло)и принять все ноль IV.В этом случае шифрование одного блока (ECB) имеет идентичный результат в режиме CBC.Это также работает для все более популярного режима CTR.

Начальное значение 9f589f5cf6122c32b6bfec2f2ae8c35a, которое вы нашли, является правильным для 128-битового ключа с нулевым ключом, IV и открытого текста.Значение f84268f0293adf4d24e27194911a24c также является правильным.

Что-то не так с вашим шестнадцатеричным кодировщиком, ваш результат даже не соответствует правильному размеру для этого значения (что происходит с начальными нулями шестнадцатеричных кодировок?),Учитывая результаты и код, я определенно посмотрю на ваши функции кодирования / декодирования.

...