出于兼容性/传统原因,我需要使用RC2加密在CBC模式下。我正在编写测试-但在C#,Python和在线工具中,(似乎)输入值相同,结果却截然不同。
对于所有实现,我都使用以下数据:
Data: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Key: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
IV: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
Mode: CBC
Padding: PKCS7
我曾尝试使用Python,C#和一个名为CyberChef的在线工具对此进行测试。所有人给我的结果完全不同。
Python结果:d123f2ac56146f3cebd19b285eb1e1744b828a177778be07
C#结果:f278304ee422a8bbccd54c9157afa818ac4e5b21858ff267
CyberChef结果:c91e276fc97e71acb72426f29c3a6c6f5181d8e83dcf1a98
Python脚本:
from Crypto.Cipher import ARC2
from Crypto.Util.Padding import pad
input = bytes([0]*16)
key = bytes([0]*8)
iv = b"\x01\x02\x03\x04\x05\x06\x07\x08"
cipher = ARC2.new(key, ARC2.MODE_CBC, iv=iv)
msg = cipher.encrypt(pad(input,8,style='pkcs7'))
print("{} {}".format(len(msg), msg.hex()))
C#脚本(部分):
public byte[] Encrypt(Rc2CryptoParameters cryptoParameters)
{
using var outputStream = new MemoryStream();
using var provider = GetRc2Provider(cryptoParameters);
using var encryptor = provider.CreateEncryptor();
using var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(cryptoParameters.Data);
cryptoStream.Close();
return outputStream.ToArray();
}
private RC2CryptoServiceProvider GetRc2Provider(Rc2CryptoParameters cryptoParameters)
{
return new RC2CryptoServiceProvider
{
Key = cryptoParameters.Key,
BlockSize = cryptoParameters.BlockSize,
KeySize = cryptoParameters.KeySize,
Padding = cryptoParameters.PaddingMode,
Mode = cryptoParameters.CipherMode
};
}
public Rc2CryptoParameters(byte[] data, byte[] key, byte[] iv)
{
Data = data;
Iv = iv;
Key = key;
CipherMode = CipherMode.CBC;
PaddingMode = PaddingMode.PKCS7;
}
所以-为什么我到处都得到不同的结果?我尝试使用一些CBC测试向量,我只能找到的是这些:http://cryptomanager.com/tv.html
如何确定哪个结果正确?为什么所有的实现都产生不同的结果?
RC2在RFC2268中描述。这是具有可变密钥长度的分组密码,并且具有一个称为有效密钥长度(以位为单位)>>的附加参数,请参见RFC2268, Section 2。在这两个代码中以及在网站上,使用了不同的有效密钥长度(以位为单位),从而导致不同的结果。
在Python代码中,当使用PyCryptodome时,在创建effective_keylen
-cipher实例时,使用参数ARC2指定有效密钥长度(以位为单位),该实例的值可能在40到1024之间,其中默认值为1024值。由于未在发布的Python代码中明确指定该参数,因此将使用默认值。请注意,此参数在PyCrypto文档中有所描述,但在PyCryptodome文档中没有描述。
website的密文将得出effective_keylen = 128
。在网站上似乎无法更改有效密钥长度(以位为单位)。
无法复制C#代码的密文,可能是因为GetRc2Provider
中未设置IV(因此使用了随机生成的IV)。如果这是固定的,则可以看出以位(RC2CryptoServiceProvider#EffectiveKeySize
)为单位的有效密钥长度被隐式设置为实际密钥长度。如果将参数显式切换为另一个值,则会抛出System.Security.Cryptography.CryptographicUnexpectedOperationException: EffectiveKeySize must be the same as KeySize in this implementation.
。