Introduction
In my project, I faced a situation where Encryption and Decryption is needed in both .NET and Android platforms. Suppose a file contains XML data that is produced from an application of C#.NET and that file will be sent to an Android application. The file should be encrypted for security issue and then it should be decrypted in Android side. And again the encrypted data should be sent from Android and it should be decrypted in .NET application. These code snippets solved my problems.
Using the Code
Here's the solution of this, the main challenge was managing the data in Android side as it has some limitations. OutOfMemory
exception is so common when you parse or read a very long string
in Android. To avoid this, I tried a lot of things, but that hampered the encryption. At last, a very easy way solved this matter, I added a property in manifest file in Android application which is: android:largeHeap="true"
.
While encrypting and deciphering the content, you need to be aware of some properties. The key should be matched, the parameters like Mode, Padding and Encoding Type should be matched. At first, I put the C# codes here:
public class Cryptography_CSharp
{
public static string Encrypt(string data, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] plainText = Encoding.UTF8.GetBytes(data);
return Convert.ToBase64String
(transform.TransformFinalBlock(plainText, 0, plainText.Length));
}
public static string Decrypt(string data, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] encryptedData = Convert.FromBase64String(data);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock
(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(plainText);
}
}
The above Cryptography_CSharp
class is written in C# which shows the Encryption and Decryption though
RijndaelManaged
class. It uses some parameters like Mode, Padding which should be matched in Android/JAVA side also. You can send data as String
through this method. I am not putting the file reading and writing codes here. Now the Android side's class would be like this:
public class Cryptography_Android {
public static String Decrypt(String text, String key) throws Exception {
Cipher cipher = Cipher.getInstance
("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] results = new byte[text.length()];
BASE64Decoder decoder = new BASE64Decoder();
try {
results = cipher.doFinal(decoder.decodeBuffer(text));
} catch (Exception e) {
Log.i("Erron in Decryption", e.toString());
}
Log.i("Data", new String(results, "UTF-8"));
return new String(results, "UTF-8");
}
public static String Encrypt(String text, String key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
}
In the above class, it is shown that the Cryptography is done through Cipher Class with AES Algorithm. Mode
and Padding
parameters should be same. BASE64Encoder
is used for encoding and decoding the bytes.
So this is it, this code snippets work perfectly in my application. My next target is to build an API which can support Encryption in any platforms in faster and more efficient ways. The code snippet of Android side is completely JAVA, and you will face OutOfMemoryException
. For solving this, you need to add android:largeHeap="true"
in android.manifest file. And you can use this code snippet in a JAVA application also.
Points of Interest
This was a challenge for me. It is great fun to work with Encryption and Deciphering data.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL).