I've written the C# code below to encrypt a string but the decryption code I've written in Python fails, apparently because the IV is derived incorrectly.
Encryption code:
public string Encrypt(string plainText)
{
// Transformar la clave de encriptación de Base64 a bytes
var base64Key = "MiEncryptKey=".Replace('_', '/').Replace('-', '+');
var keyBytes = Convert.FromBase64String(base64Key);
// Derivar la clave y el IV usando Rfc2898DeriveBytes con SHA256
var salt = Encoding.UTF8.GetBytes("AgenteSalt");
var pdb = new Rfc2898DeriveBytes(keyBytes, salt, 1000);
var key = pdb.GetBytes(32);
var iv = pdb.GetBytes(16);
// Configurar el cifrador AES en modo CBC con PKCS7 padding
using (var aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
// Encriptar el texto
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
var bytes = Encoding.UTF8.GetBytes(plainText);
cs.Write(bytes, 0, bytes.Length);
cs.Close();
}
var encrypted = ms.ToArray();
// Codificar el resultado en Base64
return Convert.ToBase64String(encrypted);
}
}
}
This is the code for decrypting in Python, which doesn't work.
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import base64
class Decryptor:
def __init__(self, base64_key, salt=b"MiSalt"):
self.base64_key = base64_key.replace('_', '/').replace('-', '+')
self.encryption_key = base64.b64decode(self.base64_key)
self.salt = salt
self.iterations = 1000
def _get_cipher(self):
# Usando SHA1 aquí para coincidir con el algoritmo de hash de C#
kdf = PBKDF2HMAC(
algorithm=hashes.SHA1(),
length=32,
salt=self.salt,
iterations=self.iterations,
backend=default_backend()
)
key = kdf.derive(self.encryption_key)
iv = key[:16]
return Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
def decrypt(self, cipher_text):
cipher = self._get_cipher()
decryptor = cipher.decryptor()
ct = base64.b64decode(cipher_text)
decrypted = decryptor.update(ct) + decryptor.finalize()
return self._unpad(decrypted)
def _unpad(self, s):
pad_size = s[-1]
if pad_size > 16:
raise ValueError("Invalid padding")
return s[:-pad_size]
I was the original string encrypted in C#, decryp it with Python, but don't know what I'm doing wrong
I followed this recommendations, but they don't work The key aspects to consider in adjusting the implementation in C# to match that of Python are:
Encryption Key Transformation: Make sure that the encryption key is handled in the same way in C# as it is in Python. This includes how you transform from Base64 to bytes.
Key and IV derivation: In Python, we're using PBKDF2HMAC with SHA256 to derive the key and IV. Make sure that C# uses the same algorithm and process to generate the key.
HELLO I lasted, a week looking for the solution, I hope you don't have to suffer so long :)
SOLUTION:
In C#, I was getting both the key and the IV from the same Rfc2898DeriveBytes object. This is an unusual practice, as the IV is usually randomly generated and transmitted along with the ciphertext, or kept constant and known by both sides of the encryption and decryption process. In your case, you're generating the IV from the same source (the key and the salt), but after generating the key, which means that the IV will depend on the key.
In Python, I was doing something similar: I was using PBKDF2 to generate both the key and the IV from the same source. However, since I don't use the same PBKDF2 object (as is done in C# with Rfc2898DeriveBytes), it's very likely that the IV generated in Python doesn't match the IV generated in C#.
This is the correct way to encrypt in C# and then be able to decrypt in python
To clarify, I have my encryption key in the Visual Studio development secrets trunk you can replace your key, in this variable: mybase64Key ='myEncryptionKey'
Use this approach to solve the problem: Randomly Generate IV and Transmit It A more common and secure practice is to randomly generate the IV for each cipher and then transmit it along with the ciphertext. This means that the IV does not need to be derived from the key.
Code C# correct that encrypt
Code correct that decrypt using Python