背景信息:
我正在尝试从Delphi Encryption Compendium中移植遗留加密,它使用Blowfish引擎(
TCipher_Blowfish_
)和CTS操作模式(cmCTS
)。私钥由RipeMD256 (THash_RipeMD256
)哈希。问题:
输入的明文字节数组需要与
CIPHER_BLOCK
的大小相同。据我所知,它不应该这样做。来自维基百科:
在密码学中,密文窃取(CTS)是一种使用块密码操作模式的通用方法,允许处理不均匀分成块的消息而不会导致密文扩展,代价是稍微增加了复杂性。
输出与旧例程不同:
我正在使用:
- 相同的IV - 相同的密码 - 相同的输入明文
这个遗留应用程序使用 ANSI 字符串,新的应用程序使用 Unicode,因此对于每个输入字符串,我都调用了 Encoding.ASCII.GetBytes("plainText")
,Encoding.ASCII.GetBytes("privatepassword")
。
然后,私有密码字节通过 RipeMD256 进行哈希处理,我已经检查了输出字节,它们是相同的。
我可以确认问题特定在 Bouncy Clastle 中(操作模式或缺少配置/步骤),因为我已经下载了第二个库 Blowfish.cs 并使用 8 字节的输入(与密码块大小相同)并使用相同的 IV 的 Encrypt_CBC(bytes[])
得到了与遗留格式相同的输出。
这是我同时使用 Blowfish.cs
和 Bouncy Castle
的代码草图:
Delphi 加密手册
var
IV: Array [0..7] of Byte (1,2,3,4,5,6,7,8);
Key: String = '12345678';
with TCipher_Blowfish.Create('', nil) do
begin
try
InitKey(Key, @IV); //Key is auto hashed using RIPE256 here;
Result:= CodeString('12345678', paEncode, -1); //Output bytes is later encoded as MIME64 here, the result is the hash.
finally
Free;
end;
end;
Blofish.cs
var hashOfPrivateKey = HashValue(Encoding.ASCII.GetBytes("12345678"));
Blowfish b = new BlowFish(hashOfPrivateKey);
b.IV = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8};
var input = Encoding.ASCII.GetBytes("12345678");
var output = b.Encrypt_CBC(input);
我假设如果输入长度为8位,则CTS和CBC的结果始终相同。这只是幸运/巧合还是根本上的真理?
Bouncy Castle
IBufferedCipher inCipher = CipherUtilities.GetCipher("BLOWFISH/CTS");
var hashOfPrivateKey = HashValue(Encoding.ASCII.GetBytes("12345678"));
var key = new KeyParameter(hashOfPrivateKey);
var IV = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8};
var cipherParams = new ParametersWithIV(key, IV);
inCipher.Init(true, cipherParams);
var input = Encoding.ASCII.GetBytes("12345678");
//try one: direct with DoFinal
var output = inCipher.DoFinal(input);
// output bytes different from expected
inCipher.Reset();
//try two: ProcessBytes then DoFinal
var outBytes = new byte[input.Length];
var res = inCipher.ProcessBytes(input, 0, input.Length, outBytes, 0);
var r = inCipher.DoFinal(outBytes, res);
// outBytes bytes different from expected
如我所说,我正在比较基于假设给定8字节的输入,输出将相同的CBC和CTS。如果即使相同的输入输出也不相同,我就不能使用Bouncy Castle的实现。 我不知道:
- Delphi Encryption Compendium中使用的CTS模式是否与CBC一起使用。我无法在任何地方找到记录。
- 调用DoFinal()和ProcessBytes()然后DoFinal()之间的区别,在Bouncy Castle中,我想象这是当输入块大于引擎块大小时需要的,在这种情况下它们具有相同的大小。
- Delphi Encryption Compendium是否正确/错误或Bouncy Castle是否正确/错误。我没有足够的加密知识来理解实现,否则我不会在这里提问(我需要指导)。