I've been given the task of decrypting some data in C# that was originally encrypted using PHP. Below is the PHP code
$opts = OPENSSL_RAW_DATA;
$res = openssl_decrypt($raw, 'aes-256-ctr', $keyhash, $opts, base64_decode($iv));
$raw is a byte array with a length of 312, $keyhash is 32 bytes and $iv is 16 bytes.
My problem is when I duplicate this code in C# I receive the following CryptographicException - The input data is not a complete block.
Not being a crypto guy, I've tried many, many C# examples to try to get this to work, but pretty much always end up with the same error. This is one sample of the C# code I've tried.
static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.PKCS7;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
I've implemented the code in PHP and it works fine. I've also checked all the input byte arrays and they all exactly the same for both PHP and C#. In desperation I even implemented this in Java and again it works no problem.
SecretKeySpec keySpec = new SecretKeySpec(keyHash, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte [] original = cipher.doFinal(encData);
String plaintext = new String(original);
So what's up with the C# code and how can I make it work?
Thanks in advance.