How can I securely save my app data?

Before we look at encrypting data on a device, you may want to read up on this.

What do you mean I have to be “properly authorized” to use encryption in my apps?

Unity has this very nice feature of being able to easily store data on the device via “PlayerPrefs”. The only problem is that it is stored in plain text. If you don’t really care, then it’s not that big of a deal, but if you are caching information to send back to your web server because the user doesn’t have any internet connectivity at the time, then it could be an issue.  Especially if that data contains information you don’t want tampered with like scores, ranking, etc… We’ll take a look at some encrypting functions we can throw into our code that will make encrypting/decrypting information pretty trivial. I’ve pulled in this code from various places so I can’t take credit for most of it. We’ll be using the Triple DES encryption capabilities that we have access to and once done, this should also make it safe to send via POST to a web server without mangling the data since the final data is encoded to BASE64. I’ll have another post detailing how I setup app-to-web server communications here in a bit. I created a file named Crypt.cs and made all the functions static so that we could call these functions anywhere in our code. We just have to pass in what we want to encrypt and the key we will be using. So from anywhere in the code we can call something like:

// Encrypt the data
string data = "Something to encrypt";
string key = "your_key";
string encryptedData = Crypt.Encrypt(data, key);

// Decrypt the data
data = Crypt.Decrypt(encryptedData, key);

Something that bothered me is having the key all in one place like that. So, you could just have it split up in various places in your app and create a function to put the key back together again and pass that in. So, here is the code I used (for the most part) to do this, just take it and put it in a .cs file.


using UnityEngine;
using System;
using System.Collections;
using System.Security.Cryptography;
using System.Text;

public class Crypt : MonoBehaviour {

/**
 */
 private static string GetMd5Hash(MD5 md5Hash, string input) {
 // Convert the input string to a byte array and compute the hash.
 byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

 // Remove last 8 bytes to make it 192 bits (24 bytes) and compatible with the DES key property
 byte[] finalData = new byte[12];
 for (int i = 0; i < 12; i++) {
 finalData[i] = data[i];
 }

 // Create a new Stringbuilder to collect the bytes
 // and create a string.
 StringBuilder sBuilder = new StringBuilder();

 // Loop through each byte of the hashed data
 // and format each one as a hexadecimal string.
 for (int i = 0; i < finalData.Length; i++) {
 sBuilder.Append(finalData[i].ToString("x2"));
 }

 // Return the hexadecimal string.
 return (sBuilder.ToString());
 }

/**
 */
 public static string Encrypt(string data, string secret) {
 TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
 MD5 md5 = MD5.Create();

 string key = GetMd5Hash(md5, secret);
 byte[] finalKey = System.Text.Encoding.UTF8.GetBytes(key); 

 des.Mode = CipherMode.ECB;
 des.Key = finalKey;

 des.Padding = PaddingMode.PKCS7;
 ICryptoTransform DESEncrypt = des.CreateEncryptor();
 Byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(data);

 return (Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length)));
 } 

 /**
 */
 public static string Decrypt(string data, string secret) {
 TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
 MD5 md5 = MD5.Create();

 string key = GetMd5Hash(md5, secret);
 byte[] finalKey = System.Text.Encoding.UTF8.GetBytes(key); 

 des.Mode = CipherMode.ECB;
 des.Key = finalKey;

 des.Padding = PaddingMode.PKCS7;
 ICryptoTransform DESEncrypt = des.CreateDecryptor();
 Byte[] Buffer = Convert.FromBase64String(data.Replace(" ", "+"));

 return (Encoding.UTF8.GetString(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length)));
 }

}