she*_*ydz 8 c# python encryption aes pbkdf2
我正在尝试编写一个Python模块,它将加密我们现有.NET类可以解密的文本.据我所知,我的代码行,但它没有解密(我在C#端得到'无效的填充长度'错误).我的pkcs7代码看起来不错,但研究表明无效密钥可能会导致同样的问题.
这两种设置有什么不同?蟒蛇:
derived_key = PBKDF2(crm_key, salt, 256 / 8, iterations)
iv = PBKDF2(crm_key, salt, 128 / 8, iterations)
encoder = pkcs7.PKCS7Encoder()
cipher = AES.new(derived_key, AES.MODE_CBC, iv)
decoded = cipher.decrypt(encoded_secret)
#encode - just stepped so i could debug.
padded_secret = encoder.encode(secret) # 1
encodedtext = cipher.encrypt(padded_secret) # 2
based_secret = base64.b64encode(encodedtext) # 3
Run Code Online (Sandbox Code Playgroud)
我认为based_secret可以传递给C#并在那里解码.但它失败了.相同的加密c#代码是:
var rfc = new Rfc2898DeriveBytes(key, saltBytes);
// create provider & encryptor
using (var cryptoProvider = new AesManaged())
{
// Set cryptoProvider parameters
cryptoProvider.BlockSize = cryptoProvider.LegalBlockSizes[0].MaxSize;
cryptoProvider.KeySize = cryptoProvider.LegalKeySizes[0].MaxSize;
cryptoProvider.Key = rfc.GetBytes(cryptoProvider.KeySize / 8);
cryptoProvider.IV = rfc.GetBytes(cryptoProvider.BlockSize / 8);
using (var encryptor = cryptoProvider.CreateEncryptor())
{
// Create a MemoryStream.
using (var memoryStream = new MemoryStream())
{
// Create a CryptoStream using the MemoryStream and the encryptor.
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
// Convert the passed string to a byte array.
var valueBytes = Encoding.UTF8.GetBytes(plainValue);
// Write the byte array to the crypto stream and flush it.
cryptoStream.Write(valueBytes, 0, valueBytes.Length);
cryptoStream.FlushFinalBlock();
// Get an array of bytes from the
// MemoryStream that holds the
// encrypted data.
var encryptBytes = memoryStream.ToArray();
// Close the streams.
cryptoStream.Close();
memoryStream.Close();
// Return the encrypted buffer.
return Convert.ToBase64String(encryptBytes);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用的Python pkcs7实现是:https://gist.github.com/chrix2/4171336
首先,我验证了Rfc2898和PBKDF2是一回事.然后,如上所述,问题似乎是.net ism.我在msdn上找到了
Rfc2898DeriveBytes中GetBytes的实现在每次调用时都会发生变化,即.它掌握着国家.(见关于页面中间的评论)
Python中的示例(伪输出):
derived_key = PBKDF2(key, salt, 32, 1000)
iv = PBKDF2(key, salt, 16, 1000)
print(base64.b64encode(derived_key))
print(base64.b64encode(iv))
$123456789101112134==
$12345678==
Run Code Online (Sandbox Code Playgroud)
.NET中的相同(ish)代码(再次,伪输出):
var rfc = new Rfc2898DeriveBytes(key, saltBytes);
using (var cryptoProvider = new AesManaged())
{
// Set cryptoProvider parameters
cryptoProvider.BlockSize = cryptoProvider.LegalBlockSizes[0].MaxSize;
cryptoProvider.KeySize = cryptoProvider.LegalKeySizes[0].MaxSize;
cryptoProvider.Key = rfc.GetBytes(cryptoProvider.KeySize / 8);
cryptoProvider.IV = rfc.GetBytes(cryptoProvider.BlockSize / 8);
}
Console.Writeline(Convert.ToBase64(cryptoProvider.Key));
Console.Writeline(Convert.ToBase64(cryptoProvider.IV));
$123456789101112134==
$600200300==
Run Code Online (Sandbox Code Playgroud)
对rfc.GetBytes的后续调用总是会产生不同的结果.MSDN表示它会影响通话的密钥大小.因此,如果您调用两次GetBytes(20),则与调用GetBytes(20 + 20)或GetBytes(40)相同.从理论上讲,这应该只是增加密钥的大小,而不是完全改变它.
有一些解决方案可以解决这个问题,可以在第一次调用时生成一个更长的密钥,然后将其切换为派生密钥和IV,或者随机生成IV,将其附加到编码消息并将其剥离在解密之前.
切片python输出产生与.NET相同的结果.它看起来像这样:
derived_key = PBKDF2(key, salt, 32, 1000)
iv = PBKDF2(key, salt, 32 + 16, 1000) # We need 16, but we're compensating for .NETs 'already called' awesomeness on the GetBytes method
split_key = iv[32:]
print(base64.b64encode(derived_key))
print(base64.b64encode(iv))
print(base64.b64encode(split_key))
$ 123456789101112134== # matches our derived key
$ 12345678== # doesn't match
$ 600200300== # matches. this is the base 64 encoded version of the tailing 16 bytes.
Run Code Online (Sandbox Code Playgroud)
请享用,
归档时间: |
|
查看次数: |
2743 次 |
最近记录: |