using System.IO; using System.Security.Cryptography; using System.Text; using UnityEngine; #if !NETFX_CORE namespace Core.Data { /// /// Encryption extension to Json Saver /// public class EncryptedJsonSaver : JsonSaver where T : IDataStore { /// /// IV for Rijndael defaults to 16 if using its default block size /// const int k_InitializationVectorLength = 16; /// /// Longest supported key length for Rijndael is 256 bits (32 bytes) /// Other supported values are 128 or 192 bits /// const int k_KeyLength = 32; /// /// Salt for encryption /// static readonly byte[] s_Salt = { 0x6b, 0xb0, 0xa1, 0x65, 0x08, 0xf8, 0xe6, 0xe8, 0x4d, 0x9e, 0x2f, 0x19, 0x97, 0xec, 0x0d, 0x6e, 0xe7, 0xec, 0xe2, 0x0a, 0xd9, 0x47, 0xa7, 0x8d, 0xff, 0x3d, 0xe1, 0x65, 0x4f, 0x46, 0x00, 0x22 }; public EncryptedJsonSaver(string filename) : base(filename) { } /// /// Get device bytes to prevent copying save file to different device /// static byte[] GetUniqueDeviceBytes() { byte[] deviceIdentifier = Encoding.ASCII.GetBytes(SystemInfo.deviceUniqueIdentifier); return deviceIdentifier; } /// /// Gets encrypted write stream /// /// The write stream. protected override StreamWriter GetWriteStream() { var underlyingStream = new FileStream(m_Filename, FileMode.Create); var byteGenerator = new Rfc2898DeriveBytes(GetUniqueDeviceBytes(), s_Salt, 1000); var random = new RNGCryptoServiceProvider(); byte[] key = byteGenerator.GetBytes(k_KeyLength); byte[] iv = new byte[k_InitializationVectorLength]; random.GetBytes(iv); Rijndael rijndael = Rijndael.Create(); rijndael.Key = key; rijndael.IV = iv; underlyingStream.Write(iv, 0, k_InitializationVectorLength); var encryptedStream = new CryptoStream(underlyingStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write); return new StreamWriter(encryptedStream); } /// /// Gets decrypted read stream /// /// The read stream. protected override StreamReader GetReadStream() { var underlyingStream = new FileStream(m_Filename, FileMode.Open); var byteGenerator = new Rfc2898DeriveBytes(GetUniqueDeviceBytes(), s_Salt, 1000); byte[] key = byteGenerator.GetBytes(k_KeyLength); byte[] iv = new byte[k_InitializationVectorLength]; underlyingStream.Read(iv, 0, k_InitializationVectorLength); Rijndael rijndael = Rijndael.Create(); rijndael.Key = key; rijndael.IV = iv; var encryptedStream = new CryptoStream(underlyingStream, rijndael.CreateDecryptor(), CryptoStreamMode.Read); return new StreamReader(encryptedStream); } } } #endif