我正在研究使用 twofish 来加密数据字符串。在将我的宝贵数据委托给未知图书馆之前,我希望验证它是否与Bruce Schneier 网站上发布的已知答案测试一致。
令我沮丧的是,我尝试了三个 twofish 实现,但没有一个与 KAT 一致。这让我相信我做错了什么,我想知道是否有人可以告诉我它是什么。
我确保模式相同(CBC),密钥长度相同(128 位)并且 iv/key/pt 值相同。twofish 加密是否有其他参数在起作用?
以下是来自 KAT 存档的 CBC_E_M.txt 的前两个测试条目:
I=0
KEY=00000000000000000000000000000000
IV=00000000000000000000000000000000
PT=00000000000000000000000000000000
CT=3CC3B181E1495D0495D652B66921DA0F
I=1
KEY=3CC3B181E1495D0495D652B66921DA0F
IV=3CC3B181E1495D0495D652B66921DA0F
PT=BE938D30FAB43B71F2E114E9C0529299
CT=695250B109C6F71D410AC38B0BBDA3D2
我将这些解释为十六进制,因此 16bytes=128bits 长。
我尝试使用以下 twofish 实现:
- 红宝石:https ://github.com/mcarpenter/twofish.rb
- JS:https ://github.com/ryanofsky/twofish/
- 在线:http ://twofish.online-domain-tools.com/
所有三个在第一次测试中给出相同的 CT,即(十六进制编码)
9f589f5cf6122c32b6bfec2f2ae8c35a
到目前为止一切顺利,除了它与 KAT 中的 CT0 不一致......
对于第二个测试,ruby 库和在线工具给出:
f84268f0293adf4d24e27194911a24c
虽然 js 库提供:
fd803b310bb5388ddb76d5faf9e23dbe
这些都不与 KAT 中的 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);