前言:Unity中通过xml格式保存游戏数据是非常常见的,但是如果不进行加密则非常容易被别人在外部通过修改xml文件修改游戏数据,因此加密xml是非常必要的。
一、工具类
创建一个名叫EncryptXmlDocument的c#文件,并复制下面代码到其中,作为xml加密工具类。
- using UnityEngine;
- using System;
- using System.Security.Cryptography;
- using System.Text;
- using System.IO;
- using System.Xml;
-
- namespace EncryptUtility
- {
- public class EncryptXmlDocument
- {
- ///
- /// 内容加密,加密和解密采用相同的key,具体可以自己定义,条件是必须是32位的
- ///
- ///
- ///
- private string Encrypt(string toE)
- {
- byte[] keyArray = UTF8Encoding.UTF8.GetBytes(EncryptKey);
- RijndaelManaged rDel = new RijndaelManaged();
- rDel.Key = keyArray;
- rDel.Mode = CipherMode.ECB;
- rDel.Padding = PaddingMode.PKCS7;
- ICryptoTransform cTransform = rDel.CreateEncryptor();
-
- byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toE);
- byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
-
- return Convert.ToBase64String(resultArray, 0, resultArray.Length);
- }
-
- ///
- /// 内容解密,千万记住解密和加密采用相同的key,必须是32位
- ///
- ///
- ///
- private string Decrypt(string toD)
- {
- //加密和解密采用相同的key,具体值自己填,但是必须为32位//
- byte[] keyArray = UTF8Encoding.UTF8.GetBytes(EncryptKey);
-
- RijndaelManaged rDel = new RijndaelManaged();
- rDel.Key = keyArray;
- rDel.Mode = CipherMode.ECB;
- rDel.Padding = PaddingMode.PKCS7;
- ICryptoTransform cTransform = rDel.CreateDecryptor();
-
- byte[] toEncryptArray = Convert.FromBase64String(toD);
- byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
-
- return UTF8Encoding.UTF8.GetString(resultArray);
- }
-
- ///
- /// 判断XML文档是否存在
- ///
- ///
- ///
- public static bool IsFileExist(string fileName)
- {
- return File.Exists(fileName);
- }
-
- public void Load(string filename)
- {
- if (IsFileExist(filename))
- {
- StreamReader sReader = File.OpenText(filename);
- string dataString = sReader.ReadToEnd();
- sReader.Close();
- string xxx = Decrypt(dataString);
- _doc.LoadXml(xxx);
- }
- }
-
- public void Save(string filename)
- {
- string xxx = Encrypt(_doc.InnerXml);
- StreamWriter writer;
- writer = File.CreateText(filename);
- writer.Write(xxx);
- writer.Close();
- }
-
- public XmlDocument Instance { get { return _doc; } }
- private XmlDocument _doc = new XmlDocument();
- string dataKey = SystemInfo.deviceUniqueIdentifier; // 设置秘钥,根据平台而定
- public string EncryptKey = "12348578902223367877723456789012"; // 有需要自己修改,必须为32位
- }
- }
二、测试
创建一个名叫XmlEncryptExample 的c#文件,并复制下面代码到其中,新建一个场景并将XmlEncryptExample组件拖动到一个物体上,然后点击运行。
- using UnityEngine;
- using System.Collections;
- using System.Linq;
- using System.Xml.Linq;
- using System;
- using System.IO;
- using System.Xml;
- using EncryptUtility;
-
- public class XmlEncryptExample : MonoBehaviour
- {
- public string xmlpath;
-
- // Use this for initialization
- void Start()
- {
- xmlpath = Application.persistentDataPath + "/Data/myXML.xml";
- var dir = Path.GetDirectoryName(xmlpath);
- if (!Directory.Exists(dir))
- {
- Directory.CreateDirectory(dir);
- }
-
- EncryptXmlDocument doc = new EncryptXmlDocument();
- if(File.Exists(xmlpath))
- {
- doc.Load(xmlpath);
-
- }
- else
- {
- XmlElement root = doc.Instance.CreateElement("XMLContent");
- root.AppendChild( doc.Instance.CreateElement("IsFirstPlayGame"));
- root.AppendChild(doc.Instance.CreateElement("Herb1"));
- root.AppendChild(doc.Instance.CreateElement("Herb2"));
- root.AppendChild(doc.Instance.CreateElement("Herb3"));
-
- doc.Instance.AppendChild(root);
- }
- Debug.Log(doc.Instance.InnerXml);
- doc.Save(xmlpath);
- }
- }
运行结果如下:
正确加载了从加密xml中读取的内容。(若不存在加密xml文件则会在首次运行时自动创建)
