We have implemented AES encryption in our project. And it works fine.
But, if the user tampers the byte[] then the Decrypt function returns a wrong plain text with different symbols like � in it.
We want to handle this case by determining that the data is tampered.
Please find below the code of Decrypt function:
public static string Decrypt(string encryptedText)
{
try
{
// First convert the base64 string to byte[].
var cipherText = Convert.FromBase64String(encryptedText);
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
string plaintext = null;
// Create an Aes object
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Encoding.ASCII.GetBytes("abc");
aesAlg.IV = Encoding.ASCII.GetBytes("xyz");
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
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
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
catch (Exception ex)
{
return null;
}
}
Please help me to solve my issue.
Thanks!
Related
I have a requirement where I need to convert some PHP code to C#.. following is the PHP Code that needs to be converted:
$data = "Hello World!";
$key = "RTc0MDkwMEEwMDYxQjc4Mg=="
$encRaw = openssl_encrypt($data, 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
To convert this openssl encryption, I am using below C# code:
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
//aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
But somehow this is not giving me same result that PHP function is returning.
Can someone please help me to identify the issue in my code? Or suggest me what other changes should I do in my code so that I get the similar result that PHP function is returning.
I make a chat application and I use AES algorithm. But I see this error " the input data is not complete block".
This is my code:
public static string DecryptStringFromBytes_Aes(byte[] cipherText, string key, string mode)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
if (mode == "ECB") aesAlg.Mode = CipherMode.ECB;
else if (mode == "CBC") aesAlg.Mode = CipherMode.CBC;
else if (mode == "CFB") aesAlg.Mode = CipherMode.CFB;
aesAlg.Key = Convert.FromBase64String(key);
aesAlg.IV = ASCIIEncoding.ASCII.GetBytes(key.Substring(0, 16));
// Create a decryptor 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;
}
The error is in line: plaintext = srDecrypt.ReadToEnd();
I don't know why.
Help me, please. Thank you very much.
Hello Friendly OverFlowers:
I have a line of code in the bigger example that is not working:
plaintext = srDecrypt.ReadToEnd();
It reports an exception:
The input data is not a complete block.
I have:
1) Looked at Encodings
2) Verified Decrypt (args) were correct.
Oh the intention from the simple main was to get back the encrypted value from the decrypted value. The plaintext = line is in the Decryption portion.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Encryptor
{
class Program
{
static void Main(string[] args)
{
CryptDecrypt cd = new CryptDecrypt(new Guid());
string s = cd.Encrypt("Password");
Console.WriteLine(s);
string t = cd.Decrypt(s);
Console.WriteLine(t);
Console.ReadKey();
}
}
public class CryptDecrypt
{
private byte[] Key;
private byte[] IV;
public CryptDecrypt(Guid keyBase)
{
string Hash = keyBase.ToString();
Key = Encoding.UTF8.GetBytes(Hash.Take(32).ToArray());
IV = Encoding.UTF8.GetBytes(Hash.Reverse().Take(16).ToArray());
}
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.IV = IV;
aesAlg.Key = IV;
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string inputStr)
{
// Check arguments.
if (inputStr == null || inputStr.Length <= 0)
throw new ArgumentNullException("cipherText");
byte[] cipherText = Encoding.UTF8.GetBytes(inputStr);
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.Zeros;
// 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;
}
}
}
You have two errors. First is that you use IV as the Key in the Encrypt method, and second you forgot to convert back from Base64 before decrypting.
See the code amended to correct these problems.
void Main()
{
CryptDecrypt cd = new CryptDecrypt(new Guid());
string s = cd.Encrypt("Password");
Console.WriteLine(s);
string t = cd.Decrypt(s);
Console.WriteLine(t);
}
public class CryptDecrypt
{
private byte[] Key;
private byte[] IV;
public CryptDecrypt(Guid keyBase)
{
string Hash = keyBase.ToString();
Key = Encoding.UTF8.GetBytes(Hash.Take(32).ToArray());
IV = Encoding.UTF8.GetBytes(Hash.Reverse().Take(16).ToArray());
}
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.IV = IV;
aesAlg.Key = Key; <- HERE
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
swEncrypt.Flush();
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string inputStr)
{
// Check arguments.
if (inputStr == null || inputStr.Length <= 0)
throw new ArgumentNullException("cipherText");
byte[] cipherText = Convert.FromBase64String(inputStr); <- HERE
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.Zeros;
// 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 am doing an Aes decryption but I am keep getting an exception "Padding is invalid and cannot be removed". The encrypted message given to me as response from the server which I am trying to decrypt. This is the function I am using to decrypt the code
Any ideas?
public async static Task<string> DecriptResponse(string data)
{
try
{
byte[] decodedData = Convert.FromBase64String(data);
using (Aes aesAlg = new AesManaged())
{
aesAlg.Key = Encoding.UTF8.GetBytes(Constants.DecryptionKey);
aesAlg.IV = Encoding.UTF8.GetBytes(Constants.DecryptionIv);
// 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(decodedData))
{
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.
string plaintext = srDecrypt.ReadToEnd();
Debug.WriteLine(plaintext);
return plaintext;
}
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
return "";
}
return "";
}
I am trying to encrypt my data using the AES algorith.I got the functions from the MSDN site encryption decryption. What i am doing is i'm encrypting the data and storing it as a string using the following method
byte[] encrypted = EncryptStringToBytes_Aes(response, myAes.Key, myAes.IV);
string saveresponse = Convert.ToBase64String(encrypted);
and then i save it in IsolatedStorageSettings
settings.Add(merchantId, saveresponse);
But the problem i am facing is when the user comes after sometime and hits my page i check first in the IsolatedStorageSettings object if the data is present i pass that data to decrypt and process further.The step i use to decrypt is as follows
byte[] temp = Convert.FromBase64String(response);
response = DecryptStringFromBytes_Aes(temp, myAes.Key, myAes.IV);
But the above line gives me error "Value can not be null.
Parameter name: inputBuffer"
I am unable to find where i am going wrong.Can u guys please let me know what steps should be taken to make it up and running.
Here is the Encryption Code
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
and here is the decryption code
static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
try
{
// 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("Key");
// 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;
// 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;
}
catch (Exception ex) {
return "Error";
}
}
and on button1 click i call the encryption method
using (AesManaged myAes = new AesManaged())
{
byte[] encrypted = EncryptStringToBytes_Aes(response, myAes.Key, myAes.IV);
string saveresponse = Convert.ToBase64String(encrypted);
}
and on button 2 i call decryption method
using (AesManaged myAes = new AesManaged())
{
byte[] temp= Convert.FromBase64String(response)
response = DecryptStringFromBytes_Aes(temp, myAes.Key, myAes.IV);
}
The problem was the using (AesManaged myAes = new AesManaged()){} block what it does it generates the new key and IV for encryption and decryption.So while decryption the key and IV doesnt match hence the error generates.Just remove the using block and declare the Aesmanaged myAes object at global level and the problem is solved. So the final code would look like
AesManaged myAes = new AesManaged();
On button one click to encrypt;
byte[] encrypted = EncryptStringToBytes_Aes(response, myAes.Key, myAes.IV);
string saveresponse = Convert.ToBase64String(encrypted);
and button2 click to decrypt
byte[] temp = Convert.FromBase64String(response);
response = DecryptStringFromBytes_Aes(temp, myAes.Key, myAes.IV);
Thats it, happpy coding.