我正在研究将这个“解密”函数从C移植到Python(源代码:https://stackoverflow.com/a/10177020)
public static string Decrypt(string cipherText, string passPhrase)
{
// Get the complete stream of bytes that represent:
// [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
// Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
// Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
// Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
using (var symmetricKey = new RijndaelManaged())
{
symmetricKey.BlockSize = 256;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
var plainTextBytes = new byte[cipherTextBytes.Length];
var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
我用C加密了“Hello World”,并设法在Python中得到了正确的值(包括keyBytes)。我尝试过使用pprp(https://pypi.org/project/pprp/)和其他库来获取解密文本,但是不管我做什么,我只得到“错误的IV大小”或垃圾数据。我想我在为PKCS7填充物而挣扎,但在这一点上我完全迷失了方向。非常感谢最后一部分的帮助。:)
^{pr2}$
如果您发布了完整的代码,包括Rijndael加密(您已经根据您的描述实现了它),那么它就有意义了。无论如何,现有的Python代码(包括使用PBKDF2生成密钥)生成的数据与C代码相同。在
pprp只实现Rijndael-block cipher本身。只允许单个块加密。padding和mode of operation基本上都没有实现,也就是说,它们仍然必须由用户实现。操作模式定义了如何基于块密码对多个块进行加密。”很大程度上”意味着已经有一个适配器实现了(不安全的)ECB模式和PKCS7填充。在这种情况下,这没有帮助,因为C代码使用CBC模式和PKCS7填充。为此,必须首先实现适当的适配器。欧洲中央银行模式的现有实施(py适配器)可以用作蓝图。一种可能的实现(用于解密)是:
关于“错误的IV大小”错误消息,我怀疑您尝试的其他实现实际上是AES实现。AES与Rijndael不同,而是一个特殊的variant或{a5}。例如,AES的固定块大小为16字节,而Rijndael允许16、20、24、28或32字节。在C代码中,使用了块大小为32字节的Rijndael,因此长度必须与块大小相对应的IV也有32个字节大。如果您在AES实现中使用这个IV,您将不可避免地收到错误消息,如“错误的IV大小”或类似的消息。此外,pprp支持16、24和32字节的块大小。默认情况下,使用16字节的块大小。在
相关问题 更多 >
编程相关推荐