I need to do 128 bit AES encryption on an application in Windows Phone 8.1. I used the following code for Encrypting and Decrypting the data respectively:
private string GetEncryptedContent(string content)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(EncryptionKey);
byte[] data = Encoding.UTF8.GetBytes(content);
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, data, null);
return Encoding.UTF8.GetString(cipherText, 0, cipherText.Length);
}
private string GetDecryptedContent(string content)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(EncryptionKey);
byte[] data = Encoding.UTF8.GetBytes(content);
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Decrypt(key, data, null);
return Encoding.UTF8.GetString(cipherText, 0, cipherText.Length);
}
But the encryption and decryption doesn't seem to be working properly. It is getting encrypted to some unicode characters and throwing a crash on decrypting:
Length is not a multiple of block size and no padding is
selected.\r\nParameter name: ciphertext
What am I doing wrong here? Can someone please help?
EDIT
After a lot more time with Google, I found the following methods for encryption and decryption, but they doesn't seem to work either.
public string GetEncryptedContent(string input, string pass)
{
SymmetricKeyAlgorithmProvider SAP = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
CryptographicKey AES;
HashAlgorithmProvider HAP = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
CryptographicHash Hash_AES = HAP.CreateHash();
string encrypted = "";
try
{
byte[] hash = new byte[32];
Hash_AES.Append(CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(pass)));
byte[] temp;
CryptographicBuffer.CopyToByteArray(Hash_AES.GetValueAndReset(), out temp);
Array.Copy(temp, 0, hash, 0, 16);
Array.Copy(temp, 0, hash, 15, 16);
AES = SAP.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(hash));
IBuffer Buffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(input));
encrypted = CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Encrypt(AES, Buffer, null));
return encrypted;
}
catch (Exception ex)
{
return null;
}
}
public string GetDecryptedContent(string input, string pass)
{
SymmetricKeyAlgorithmProvider SAP = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
CryptographicKey AES;
HashAlgorithmProvider HAP = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
CryptographicHash Hash_AES = HAP.CreateHash();
string decrypted = "";
try
{
byte[] hash = new byte[32];
Hash_AES.Append(CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(pass)));
byte[] temp;
CryptographicBuffer.CopyToByteArray(Hash_AES.GetValueAndReset(), out temp);
Array.Copy(temp, 0, hash, 0, 16);
Array.Copy(temp, 0, hash, 15, 16);
AES = SAP.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(hash));
IBuffer Buffer = CryptographicBuffer.DecodeFromBase64String(input);
byte[] Decrypted;
CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(AES, Buffer, null), out Decrypted);
decrypted = Encoding.UTF8.GetString(Decrypted, 0, Decrypted.Length);
return decrypted;
}
catch (Exception ex)
{
return null;
}
}
EDIT 2
Finally managed to get the encryption working properly, but the decryption is still not working presumably because the encoding I am passing is not the right one:
private string GetEncryptedContent(string content)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(EncryptionKey);
byte[] data = Encoding.UTF8.GetBytes(content);
byte[] iv = new byte[128 / 8]; // Adding this solved the encryption issue.
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, data, iv);
return Convert.ToBase64String(cipherText);
}
private string GetDecryptedContent(string content)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(EncryptionKey);
byte[] data = Convert.FromBase64String(content); // Believe this is where the issue is, but not able to figure it out.
byte[] iv = new byte[128 / 8]; // Added this to make the decryption work the same way.
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Decrypt(key, data, iv);
return Convert.ToBase64String(cipherText);
}
I finally solved the problem. The problem was with the text encoding. Using the correct encoding solved the issue. The working code below:
public static string EncryptAES(string content, string password)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(password);
byte[] data = Encoding.UTF8.GetBytes(content);
byte[] iv = new byte[keyMaterial.Length];
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, data, iv);
return Convert.ToBase64String(cipherText);
}
public static string DecryptAES(string content, string password)
{
byte[] keyMaterial = Encoding.UTF8.GetBytes(password);
byte[] data = Convert.FromBase64String(content);
byte[] iv = new byte[keyMaterial.Length];
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Decrypt(key, data, iv);
return Encoding.UTF8.GetString(cipherText, 0, cipherText.Length);
}
WinRTCrypto is available as part of PCLCrypto.
I'm trying to encrypt and decrypt file with RSA. Encryption is working fine. But I get error when I'm decrypting.
Error is key does not exist.
Here is the error: http://i.imgur.com/ebF09cU.png
public byte[] RSA_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes, RSAParameters RSAKeyInfo)
{
//initialze the byte arrays to the public key information.
byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147};
//Values to store encrypted symmetric keys.
byte[] EncryptedSymmetricKey;
byte[] EncryptedSymmetricIV;
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(_stBitov))
{
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey;
//Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo);
//Create a new instance of the RijndaelManaged class.
RijndaelManaged RM = new RijndaelManaged();
var key = new Rfc2898DeriveBytes(PublicKey, saltBytes, 1000);
//Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
encryptedBytes = RSA.Encrypt(bytesToBeEncrypted, false);
}
}
return encryptedBytes;
}
RSAParameters _RSAKeyInfo;
public void EncryptFile()
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Get an instance of RSAParameters from ExportParameters function.
RSAParameters RSAKeyInfo = RSA.ExportParameters(false);
_RSAKeyInfo = RSAKeyInfo;
string path = ofd.FileName;
if (File.Exists(path))
{
string dirPath = Path.GetDirectoryName(path);
byte[] bytesToBeEncrypted = File.ReadAllBytes(path);
byte[] passwordBytes = File.ReadAllBytes(dirPath + "/KEY_" + ofd.SafeFileName);
byte[] bytesEncrypted = RSA_Encrypt(bytesToBeEncrypted, passwordBytes, RSAKeyInfo);
string fileEncrypted = dirPath + "/ENCRYPTED_" + ofd.SafeFileName;
File.WriteAllBytes(fileEncrypted, bytesEncrypted);
}
}
private void button5_Click(object sender, EventArgs e)
{
string path = ofd2.FileName;
if (File.Exists(path))
{
DecryptFile();
richTextBox4.Text = "Dekripcija uspesna";
}
else
{
richTextBox6.Text = "Datoteka ni dodana";
}
} private void richTextBox4_TextChanged(object sender, EventArgs e) { }
public byte[] RSA_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes, RSAParameters RSAKeyInfo)
{
byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147};
//Values to store encrypted symmetric keys.
byte[] EncryptedSymmetricKey;
byte[] EncryptedSymmetricIV;
byte[] decryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(_stBitov))
{
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey;
//Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo);
//Create a new instance of the RijndaelManaged class.
RijndaelManaged RM = new RijndaelManaged();
//Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
decryptedBytes = RSA.Decrypt(bytesToBeDecrypted, false);
}
}
return decryptedBytes;
}
public void DecryptFile()
{
string path = ofd2.FileName;
if (File.Exists(path))
{
string dirPath = Path.GetDirectoryName(path);
byte[] bytesToBeDecrypted = File.ReadAllBytes(path);
byte[] passwordBytes = File.ReadAllBytes(dirPath + "/KEY_" + ofd.SafeFileName);
byte[] bytesDecrypted = RSA_Decrypt(bytesToBeDecrypted, passwordBytes, _RSAKeyInfo);
string file = dirPath + "/DECRYPTED_" + ofd.SafeFileName;
File.WriteAllBytes(file, bytesDecrypted);
}
}
Can somebody tell me what to do that decryption is going to work.
RSA is a kind of public-key cryptography. That means you need a public key to encrypt the message and a private key to decrypt your message. It looks like you're using your public key for both encryption and decryption. Where's your private key?
It seems you're trying to do hybrid encryption with RSA+AES, but you forgot to actually use AES to encrypt the plaintext and you forgot to encrypt the symmetric key with RSA. You also need to generate the symmetric key randomly and should not be derived from the public key which is supposed to be constant and public.
The error that you presented here is the least of your problems, but as ElectroByt already said, you need to use a private key (RSACryptoServiceProvider#ExportParameters(true)) to decrypt something with RSA. In your case, you would need to decrypt with RSA to get the symmetric key to use it to decrypt the symmetric ciphertext to get the actual message back.
So, I am having an issue with decrypting the decoded base64 aes string. Is this possible? I wrote a small console program to work this out but no luck. Here is my example:
As depicted, I have successfully converted the base64 back the aes encrypted string, but when I try to decrypt it I get more junk. If a code snippet is need let me. Thank you all for your help :)
UPDATE: Code snippet for decrypting method
static void Main(string[] args)
{
string plainText;
string decrypted;
string decryptedFromB64EncodedDecoded;
string fromBase64ToEncryptedText;
string encryptedText;
string encryptedTextBase64;
byte[] encryptedBytes;
byte[] encryptedBytes2;
byte[] encryptedBytesBase64;
RijndaelManaged crypto = new RijndaelManaged();
UTF8Encoding UTF = new UTF8Encoding();
Console.WriteLine("Please put in the text to be encrypted.");
plainText = Console.ReadLine();
try
{
encryptedBytes = encrypt(plainText, crypto.Key, crypto.IV);
encryptedText = Encoding.ASCII.GetString(encryptedBytes);
//encryptedBytes2 = Encoding.ASCII.GetBytes(encryptedText);
encryptedTextBase64 = toBase64String(encryptedText);
encryptedBytesBase64 = fromBase64String(encryptedTextBase64);
fromBase64ToEncryptedText = Encoding.ASCII.GetString(encryptedBytesBase64);
encryptedBytes2 = Encoding.ASCII.GetBytes(fromBase64ToEncryptedText);
decrypted = decrypt(encryptedBytes, crypto.Key, crypto.IV);
decryptedFromB64EncodedDecoded = decrypt(encryptedBytes2, crypto.Key, crypto.IV);
Console.WriteLine("Start: {0}", plainText);
Console.WriteLine("Encrypted: {0}", encryptedText);
Console.WriteLine("Encrypted Base64: {0}", encryptedTextBase64);
Console.WriteLine("From Base64 To AES Encypted Text: {0}", fromBase64ToEncryptedText);
Console.WriteLine("Decrypted: {0}", decrypted);
Console.WriteLine("Decrypted From Encode and then Decode Base64 Text: {0}", decryptedFromB64EncodedDecoded);
}
catch (Exception ex)
{
Console.WriteLine("Exception: {0}", ex.Message);
}
Console.ReadLine();
}
public static string decrypt (byte[] textToDecrypt, byte[] key, byte[] IV)
{
RijndaelManaged crypto = new RijndaelManaged();
MemoryStream stream = new MemoryStream(textToDecrypt) ;
ICryptoTransform decryptor = null;
CryptoStream cryptoStream = null;
StreamReader readStream = null;
string text = string.Empty;
try
{
crypto.Key = key;
crypto.IV = IV;
crypto.Padding = PaddingMode.None;
decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);
cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
//cryptoStream.Read(textToDecrypt, 0, textToDecrypt.Length);
readStream = new StreamReader(cryptoStream);
text = readStream.ReadToEnd();
cryptoStream.Close();
byte[] decodedValue = stream.ToArray();
return text;
}
catch (Exception)
{
throw;
}
finally
{
if (crypto != null)
{
crypto.Clear();
}
stream.Flush();
stream.Close();
}
}
public static byte[] encrypt(string text, byte[] key, byte[] IV)
{
RijndaelManaged crypto = null;
MemoryStream stream = null;
//ICryptoTransform is used to perform the actual decryption vs encryption, hash function are a version crypto transforms
ICryptoTransform encryptor = null;
//CryptoStream allows for encrption in memory
CryptoStream cryptoStream = null;
UTF8Encoding byteTransform = new UTF8Encoding();
byte[] bytes = byteTransform.GetBytes(text);
try
{
crypto = new RijndaelManaged();
crypto.Key = key;
crypto.IV = IV;
stream = new MemoryStream();
encryptor = crypto.CreateEncryptor(crypto.Key, crypto.IV);
cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(bytes, 0, bytes.Length);
}
catch (Exception)
{
throw;
}
finally
{
if (crypto != null)
{
crypto.Clear();
}
cryptoStream.Close();
}
return stream.ToArray();
}
public static string toBase64String(string value)
{
UTF8Encoding UTF = new UTF8Encoding();
byte[] myarray = UTF.GetBytes(value);
return Convert.ToBase64String(myarray);
}
public static byte[] fromBase64String(string mystring)
{
//UTF8Encoding UTF = new UTF8Encoding();
//byte[] myarray = UTF.GetBytes(value);
return Convert.FromBase64String(mystring);
}
I don't know how you're decrypting but before you decrypt, you should convert the base 64 string to a byte array before sending it into the decryption.
byte[] encryptedStringAsBytes = Convert.FromBase64String(base64EncodedEncryptedValue);
Then with the byte array you can pass to the CryptoStream via a MemoryStream.
UPDATE
I believe the issue is how you're setting up your streams
using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
{
rijndaelManaged.Padding = paddingMode;
rijndaelManaged.Key = key;
rijndaelManaged.IV = initVector;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream(valueToDecrypt);
using (ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
finally
{
if (memoryStream != null)
memoryStream.Dispose();
}
}
UPDATE 2
This is how you should basically perform the steps.
To encrypt
Encode your plain text string using the Encoding.GetBytes(stringToEncrypt)
pass the byte[] into the crypto API (via memory stream, etc.)
get the bytes from the encrypted stream and encode the results as Base64
To Decrypt (do the reverse)
Convert the base64 encoded string to bytes using Convert.FromBase64String(base64EncodedEncryptedValue)
pass that byte array into your decryption function above
Try:
encryptedBytes2 = Encoding.ASCII.GetBytes(encryptedText);
Based on your comment. The bytes are just that bytes, so in order to decrypt the ciphertext you need to undo any encoding or series of encodings you have done.
If you really want to go from Encrypted Bytes -> Base64String -> ASCII string -> then decrypt that ASCII string? you would need to base64 decode the ascii string then convert that string to bytes using
Encoding.ASCII.GetBytes(yourdecodedstring);
Note that base 64 decoding is not the same as using Convert.FromBase84String.
I'm creating a TCP based chat client. I'm trying to Encrypt some of the data with AES (more security) I have a AES encryption class and it uses UTF-8 by default as the out going and incoming Encoding type. But for some reason when i pass the information over the TCPClient (using UTF-8) and get it the other side it is throwing an error:
`System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()`
So I recreated the problem without using the TCP client, just taking the AES encrypted data and putting it through a UTF-8 Encoding system that gets the string of the byte array then re-gets the byte array all using UTF-8 (basically the same thing as what happens over the network (without the string))
This method works:
string dataToEncrypt = "Hello World";
byte[] key = Encryption.AesEncryption.GenerateKey(32);
byte[] iv = Encryption.AesEncryption.GenerateKey(16);
byte[] encrypted = Encryption.AesEncryption.EncryptString(dataToEncrypt, key, iv);
string decrypted = Encryption.AesEncryption.DecryptedBytes(encrypted, key, iv);
The method doesn't work (throws the error from above)
Encoding encoding = Encoding.UTF8;
string dataToEncrypt = "Hello World";
byte[] key = Encryption.AesEncryption.GenerateKey(32);
byte[] iv = Encryption.AesEncryption.GenerateKey(16);
byte[] encrypted = Encryption.AesEncryption.EncryptString(dataToEncrypt, key, iv);
string encstring = encoding.GetString(encrypted);
byte[] utf8encrypted = encoding.GetBytes(encstring);
string decrypted = Encryption.AesEncryption.DecryptedBytes(utf8encrypted, key, iv);
What am i doing wrong?
This is my Encryption Class:
public sealed class AesEncryption
{
private byte[] Key;
public Encoding Encoder = Encoding.UTF8;
public AesEncryption(byte[] key)
{
Key = key;
}
public byte[] Encrypt(string text, byte[] iv)
{
var bytes = Encoder.GetBytes(text);
var rm = new RijndaelManaged();
var encrypter = rm.CreateEncryptor(Key, iv);
var ms = new MemoryStream();
var cs = new CryptoStream(ms, encrypter, CryptoStreamMode.Write);
cs.Write(bytes, 0, bytes.Length);
cs.FlushFinalBlock();
var output = ms.ToArray();
cs.Close();
ms.Close();
return output;
}
public string Decrypt(byte[] encrypted, byte[] iv)
{
var ms = new MemoryStream();
var cs = new CryptoStream(ms,
new RijndaelManaged().CreateDecryptor(Key, iv),
CryptoStreamMode.Write);
cs.Write(encrypted, 0, encrypted.Length);
cs.FlushFinalBlock();
var output = ms.ToArray();
cs.Close();
ms.Close();
return Encoder.GetString(output);
}
public static byte[] EncryptString(string text, byte[] key, byte[] iv)
{
var ec = new AesEncryption(key);
return ec.Encrypt(text, iv);
}
public static string DecryptedBytes(byte[] encrypted, byte[] key, byte[] iv)
{
var ec = new AesEncryption(key);
return ec.Decrypt(encrypted, iv);
}
public static byte[] GenerateKey(int length)
{
Random rnd = new Random();
var chars = "1!2#3#4$5%6^7&8*9(0)-_=+qQwWeErRtTyYuUiIoOpP[{]}\\|aAsSdDfFgGhHjJkKlL;:'\"zZxXcCvVbBnNmM,<.>/?".ToCharArray();
string randomizedKey = "";
for (int i = 0; i < length; i++)
{
randomizedKey += chars[rnd.Next(0, chars.Length)];
}
return randomizedKey.ToByteArray();
}
}
UTF-8 does not perfectly represent the bytes. The short and simple answer is: Transmit bytes, not a UTF-8 string. If you must have a string, encode it in Base64.