Я пытаюсь использовать 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);