- Home /
Encryption/Decryption Issue in Android Device in Unity3d
I am trying to encrypt/decrypt my game score. its working fine as it shoud in Unity Editor. But after build on android device its not working.
Its throwing an error in LogCat, screenshot below
Here is the Scrips I used:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
public class TripleDESEncryptor : MonoBehaviour {
private static string encryptionKey = DataEncryptor.Encrypt("@!#$%6+_|:><{}-=)!:%(#+&*><|");
public static string Encrypt(string toEncrypt, bool useHash){
if (string.IsNullOrEmpty(encryptionKey))
return "";
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
if(useHash){
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(encryptionKey));
hashmd5.Clear();
}else
keyArray = UTF8Encoding.UTF8.GetBytes(encryptionKey);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform ctransform = tdes.CreateEncryptor();
byte[] resultArray = ctransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string cipherString, bool useHash){
if (string.IsNullOrEmpty(encryptionKey))
return "";
byte[] keyArray;
byte[] toDecryptArray = Convert.FromBase64String(cipherString.Replace(' ', '+'));
if(useHash){
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(encryptionKey));
hashmd5.Clear();
}else
keyArray = UTF8Encoding.UTF8.GetBytes(encryptionKey);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
}
And the other script i use for decryption is below:
using UnityEngine;
using System.Collections;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Globalization;
public class DataEncryptor : MonoBehaviour {
private static string k1_1 = "@!#$%6+_|:><";
private static string k2_1 = "@!#$%6+_|:><{}-=)!:%(#+&*><|";
protected static DataEncryptor instance;
// Use this for initialization
void Start () {
if(instance != null){
Destroy(gameObject);
return;
}
instance = this;
transform.parent = null;
DontDestroyOnLoad(gameObject);
}
// Update is called once per frame
void Update () {
}
public static string Encrypt(string data){
//Debug.Log("Data "+data);
if(string.IsNullOrEmpty(data)){
return "";
}
Rijndael aes = Rijndael.Create();
aes.Padding = PaddingMode.PKCS7;
aes.IV = Encoding.ASCII.GetBytes(k1_1);
aes.Key = Encoding.ASCII.GetBytes(k2_1);
byte[] rawData = Encoding.Unicode.GetBytes(data);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write (rawData, 0, rawData.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
byte[] encrypted = memoryStream.ToArray();
memoryStream.Close();
return System.Convert.ToBase64String(encrypted);
}
public static string Decrypt(string data){
if(string.IsNullOrEmpty(data)){
return "";
}
byte[] rawData = System.Convert.FromBase64String(data);
if(rawData.Length < 8){
Debug.Log("Exception");
throw new System.ArgumentException("Invalid Input data");
}
Rijndael aes = Rijndael.Create();
aes.Padding = PaddingMode.PKCS7;
aes.IV = Encoding.ASCII.GetBytes(k1_1);
aes.Key = Encoding.ASCII.GetBytes(k2_1);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(rawData, 0, rawData.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
byte[] decrypted = memoryStream.ToArray();
memoryStream.Close();
return Encoding.Unicode.GetString(decrypted);
}
}
I am saving and encrypting score on OnTriggerEnter like
encryptedScore = TripleDESEncryptor.Encrypt(CoinDetection.currentScore.ToString(), true);
Debug.Log(encryptedScore);
These all are working fine as it should in Unity Editor but not in android device (Didnot checked in iOS). Why? I am hitting my head since 4 days. Please help. Thanks.
Why do you use TripleDES and Rijndael? Both are outdated algorithms. $$anonymous$$ost crypto provider classes are wrapper classes for native crypto providers. It's possible that TripleDES or Rijndael is not supported on Android. Also keep in $$anonymous$$d that you only have security through obscurity. Using two different algorithms doesn't make the whole thing more secure. Your stored "keys" can be easily retrieved by a cheater.
If you want to stick to your code you may want to add some Debug.Logs in between your code of DataEncryptor.Encrypt
to know where you actually get that null reference exception. That might help to pin down what actually went wrong.