I use AES to encrypt data in a web application. Everything works fine for me when the secret key does not contain any special characters. If I add any, the encryption works but not the decryption. I would like to know if the 16-character 128-bit secret key I am using allows the use of special characters or only alphanumeric characters instead. I can't figure it out with the Microsoft documentation. From what I read, the Key property is a value of type byte[] . If the length of the key in my case is 16 characters, it is an array of 16 bytes (128 bits). But I haven't found where they specify if those bytes have to be alphanumeric characters, special characters, etc.
The Ca function returns a string resulting from the encryption (E) or decryption (D) operation. Depending on the type of operation, the encryption or decryption function is used. Encryption never gives me any trouble, but decryption fails when I add a special character to the secret key. This secret key is a 16-character string set as the session value when the application loads.
The code is the following:
public string Ca(string texto, string operacion)
//Cifrado Aes (Ca)
{
string base64;
using (Aes myAes = Aes .Create())
{
myAes.Padding = PaddingMode.Zeros;
byte[] key_aes = Encoding.UTF8.GetBytes(Convert.ToString(HttpContext.Current.Session["key_AES"]));
if (key_aes == null || key_aes.Length == 0)
{
goto salida;
}
if (operacion == "E")
{
// Encrypt the string to an array of bytes.
byte[] encriptado = EncryptStringToBytes_Aes(texto, key_aes, key_aes);
//Convertimos en un string
base64 = Convert.ToBase64String(encriptado);
return base64;
}
else if (operacion == "D")
{
byte[] bytedesdeCampo = Encoding.UTF8.GetBytes(texto);
// Decrypt the bytes to a string.
try
{
string desencriptado = DecryptStringFromBytes_Aes(bytedesdeCampo, key_aes, key_aes);
return desencriptado;
}
catch (Exception e)
{ //este error se produce cuando la key no es correcta (EL relleno entre caracteres no es admitido y no se puede quitar)
string asdfads = e.Message;
if (e.Message.Contains("Longitud no válida"))
{
}
return texto;
}
}
salida:
return "";
}
}
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
if (plainText.Length == 0)
{
return Encoding.UTF8.GetBytes("");
}
if (Key == null)
{
return Encoding.UTF8.GetBytes("");
}
// 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("IV");
byte[] encrypted;
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;
}
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 Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// 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;
}
I have already solved.
I have changed
by
The Encoding.UTF8.GetBytes method was causing the problem by not being able to implicitly convert a string to a byte[]. However the Convert.FromBase64String method returns the byte[] correctly. Now I can use special characters in the AES Key without giving an error both when encrypting and decrypting.
I have also verified that not all combinations of special characters and not all special characters are supported. When they happen not to be in the Convert.FromBase64String method , the error that the length of the byte array or Base 64 string is invalid will occur. At least the following special characters are allowed in the secret key (in addition to the alphanumeric ones):
When they are repeated, errors are produced, and if they appear three or more times, the error is always produced. With the character * repeated up to four times I have had no problems.