如何在Python中解密C#的AES加密数据?
How to decrypt a AES encrypted data of C# in Python?
我正在尝试用 C# 加密文本,然后尝试在 Python 中解密数据,但我无法在 python 中解密 C# 加密数据。我想也许我无法获得与我在 C# 中使用的相同的 IV。
我不知道我哪里错了。
class AesEncryption
{
public static void Main()
{
var original = "Here is some data to encrypt!";
using (var myAes = Aes.Create())
{
var key = "My private key";
myAes.Key = Encoding.ASCII.GetBytes(key);
myAes.Mode = CipherMode.CBC;
myAes.IV = new byte[16];
// Encrypt the string to an array of bytes.
var encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);
Console.WriteLine("Encrypted: {0}", encrypted);
// Decrypt the bytes to a string.
var roundtrip =
DecryptStringFromBytes_Aes(System.Convert.FromBase64String(encrypted), myAes.Key, myAes.IV);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
}
private static string EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException(nameof(plainText));
if (key == null || key.Length <= 0)
throw new ArgumentNullException(nameof(key));
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException(nameof(iv));
// Create an Aes object
// with the specified key and IV.
using var aesAlg = Aes.Create();
aesAlg.Key = key;
aesAlg.IV = iv;
// Create an encryptor to perform the stream transform.
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using var msEncrypt = new MemoryStream();
using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
using (var swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
var encrypted = msEncrypt.ToArray();
// Return the encrypted bytes from the memory stream.
return Convert.ToBase64String(encrypted);
}
private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException(nameof(cipherText));
if (key == null || key.Length <= 0)
throw new ArgumentNullException(nameof(key));
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException(nameof(iv));
// Declare the string used to hold
// the decrypted text.
string plaintext;
// Create an Aes object
// with the specified key and IV.
using (var aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = iv;
// Create a decryptor to perform the stream transform.
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
我正在使用IV
iv = as new byte[16];
在上面的代码中,我正在检查在加密和解密过程中生成的加密文本是什么,并试图在我的 python 加密中匹配它。
import base64
import binascii
import hashlib
from Crypto.Cipher import AES
def r_pad(payload, block_size=16):
length = block_size - (len(payload) % block_size)
return payload + chr(length) * length
key = "My private key"
body = "Here is some data to encrypt!"
iv = binascii.unhexlify(16 * "00")
length = len(body)
encoded_key = hashlib.sha256(key.encode()).digest()
data_from_encryption = r_pad(body).encode('utf-8')
encrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).encrypt(data_from_encryption)
encrypted_data_to_base64_str = base64.b64encode(encrypted_data).decode('utf-8')
print("Encrypted data: ", encrypted_data_to_base64_str)
bytes_to_decrypt = base64.decodebytes(encrypted_data_to_base64_str.encode())
decrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).decrypt(bytes_to_decrypt)[:length]
decode_str = decrypted_data.decode('utf-8')
print(decode_str)
我尝试使用不同的 IV 值
iv = binascii.unhexlify(16 * "00")
但无法在两种代码中获得相同的加密文本。
我也知道 r_pad 函数在 python 中做什么,但如果我不使用它 Python 会引发异常,关于我的数据未根据 16 位
进行填充
任何人都可以帮助我并告诉我哪里错了吗?
在C#代码中,密钥是key
的ASCII编码,但在Python代码中是key
的SHA-256散列。
以便Python代码产生相同的密文,只需替换:
encoded_key = key.encode('ascii')
注意以下问题:
- 静态 IV 是不安全的。通常,每次加密都会生成一个随机 IV,并与密文一起传递(通常是串联的)。
- 如果要从密码派生密钥,则应使用可靠的密钥派生函数,例如 Argon2 或 PBKDF2,而不是摘要。
- PyCryptodome 在专用模块中支持填充:Crypto.Util.Padding
我正在尝试用 C# 加密文本,然后尝试在 Python 中解密数据,但我无法在 python 中解密 C# 加密数据。我想也许我无法获得与我在 C# 中使用的相同的 IV。 我不知道我哪里错了。
class AesEncryption
{
public static void Main()
{
var original = "Here is some data to encrypt!";
using (var myAes = Aes.Create())
{
var key = "My private key";
myAes.Key = Encoding.ASCII.GetBytes(key);
myAes.Mode = CipherMode.CBC;
myAes.IV = new byte[16];
// Encrypt the string to an array of bytes.
var encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);
Console.WriteLine("Encrypted: {0}", encrypted);
// Decrypt the bytes to a string.
var roundtrip =
DecryptStringFromBytes_Aes(System.Convert.FromBase64String(encrypted), myAes.Key, myAes.IV);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
}
private static string EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException(nameof(plainText));
if (key == null || key.Length <= 0)
throw new ArgumentNullException(nameof(key));
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException(nameof(iv));
// Create an Aes object
// with the specified key and IV.
using var aesAlg = Aes.Create();
aesAlg.Key = key;
aesAlg.IV = iv;
// Create an encryptor to perform the stream transform.
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using var msEncrypt = new MemoryStream();
using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
using (var swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
var encrypted = msEncrypt.ToArray();
// Return the encrypted bytes from the memory stream.
return Convert.ToBase64String(encrypted);
}
private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException(nameof(cipherText));
if (key == null || key.Length <= 0)
throw new ArgumentNullException(nameof(key));
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException(nameof(iv));
// Declare the string used to hold
// the decrypted text.
string plaintext;
// Create an Aes object
// with the specified key and IV.
using (var aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = iv;
// Create a decryptor to perform the stream transform.
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
我正在使用IV
iv = as new byte[16];
在上面的代码中,我正在检查在加密和解密过程中生成的加密文本是什么,并试图在我的 python 加密中匹配它。
import base64
import binascii
import hashlib
from Crypto.Cipher import AES
def r_pad(payload, block_size=16):
length = block_size - (len(payload) % block_size)
return payload + chr(length) * length
key = "My private key"
body = "Here is some data to encrypt!"
iv = binascii.unhexlify(16 * "00")
length = len(body)
encoded_key = hashlib.sha256(key.encode()).digest()
data_from_encryption = r_pad(body).encode('utf-8')
encrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).encrypt(data_from_encryption)
encrypted_data_to_base64_str = base64.b64encode(encrypted_data).decode('utf-8')
print("Encrypted data: ", encrypted_data_to_base64_str)
bytes_to_decrypt = base64.decodebytes(encrypted_data_to_base64_str.encode())
decrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).decrypt(bytes_to_decrypt)[:length]
decode_str = decrypted_data.decode('utf-8')
print(decode_str)
我尝试使用不同的 IV 值
iv = binascii.unhexlify(16 * "00")
但无法在两种代码中获得相同的加密文本。 我也知道 r_pad 函数在 python 中做什么,但如果我不使用它 Python 会引发异常,关于我的数据未根据 16 位
进行填充任何人都可以帮助我并告诉我哪里错了吗?
在C#代码中,密钥是key
的ASCII编码,但在Python代码中是key
的SHA-256散列。
以便Python代码产生相同的密文,只需替换:
encoded_key = key.encode('ascii')
注意以下问题:
- 静态 IV 是不安全的。通常,每次加密都会生成一个随机 IV,并与密文一起传递(通常是串联的)。
- 如果要从密码派生密钥,则应使用可靠的密钥派生函数,例如 Argon2 或 PBKDF2,而不是摘要。
- PyCryptodome 在专用模块中支持填充:Crypto.Util.Padding