gpt4 book ai didi

c# - PBKDF2 Python key 与 .NET Rfc2898

转载 作者:太空狗 更新时间:2023-10-29 20:56:09 24 4
gpt4 key购买 nike

我正在尝试编写一个 Python 模块来加密我们现有的 .NET 类可以解密的文本。据我所知,我的代码行向上但它没有解密(我在 C# 端收到“无效填充长度”错误)。我的 pkcs7 代码看起来不错,但研究表明无效的 key 可能会导致同样的问题。

这两种设置有何不同? python :

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

我认为 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);
}
}
}

我使用的 Python pkcs7 实现是: https://gist.github.com/chrix2/4171336

最佳答案

首先,我验证了 Rfc2898 和 PBKDF2 是同一个东西。然后,如上所述,问题似乎是 .net 主义。我在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==

.NET 中的相同(大概)代码(同样是伪输出):

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==

对 rfc.GetBytes 的后续调用总是会产生不同的结果。 MSDN 表示它在调用时混合了 key 大小。因此,如果您调用 GetBytes(20) 两次,则与调用 GetBytes(20+20) 或 GetBytes(40) 相同。从理论上讲,这应该只是增加 key 的大小,而不是完全改变它。

有一些解决方案可以解决这个问题,可以是在第一次调用时生成一个更长的 key ,然后将其分成派生 key 和 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.

享受,

关于c# - PBKDF2 Python key 与 .NET Rfc2898,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26168544/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com