使用unity的www下载文本之后解密遇到的坑,记录一下。
首先是c#des的加密解密,这个网上一大堆,博主只粘贴代码好了。
定义两个key,注意key字符串长度必须是8,否则会异常。
static string encryptKey = "qweasdqw";
static string ivKey = "dseaseas";
//加密
static byte[] EncryptBytes(string str)
{
string result = string.Empty;
DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
descsp.Mode = CipherMode.CBC;
byte[] key = Encoding.UTF8.GetBytes(encryptKey);
byte[] data = Encoding.UTF8.GetBytes(str);
byte[] iv = Encoding.UTF8.GetBytes(ivKey);
MemoryStream MStream = new MemoryStream();
CryptoStream CStream = new CryptoStream(MStream, descsp.CreateEncryptor(key, iv), CryptoStreamMode.Write);
CStream.Write(data, 0, data.Length);
CStream.FlushFinalBlock();
Console.WriteLine("加密后byte长度:"+ MStream.ToArray().Length);
return MStream.ToArray();
}
//解密
static byte[] DecryptBytes(byte[] data)
{
Console.WriteLine("解密时byte长度:"+data.Length);
string result = string.Empty;
DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
descsp.Mode = CipherMode.CBC;
byte[] key = Encoding.UTF8.GetBytes(encryptKey);
byte[] iv = Encoding.UTF8.GetBytes(ivKey);
MemoryStream MStream = new MemoryStream();
CryptoStream CStream = new CryptoStream(MStream, descsp.CreateDecryptor(key, iv), CryptoStreamMode.Write);
CStream.Write(data, 0, data.Length);
CStream.FlushFinalBlock();
return MStream.ToArray();
}
然后利用文件流读取原文件内容,加密之后将byte数组写入文件中的,放到文件服务器供下载。这里面感觉好多坑。
首先原文件是加密前的内容,也就是一个字符串,这个字符串我用StreamReader来读取,一是因为只需要读字符串,二是因为我用BinaryReader读取的时候总是异常,很无奈。字符串的读取也就几行代码,简单。
StreamReader sr = new StreamReader(@"C:\MyDataFile\Json.txt");
string line = sr.ReadToEnd();
Console.WriteLine("data:\n" + line);
sr.Close();
之后就是对字符串的加密,加密之后注意直接把加密结果,byte数组写入到文件中,不要转换成字符串再写入文件中,转来转去的绝对会出问题,深有体会。代码如下,注意这里必须要用字节流的写入了,BinaryWriter类
BinaryWriter bw = new BinaryWriter(new FileStream(@"C:\Share\Data\afterkey.txt", FileMode.Create));
byte[] value = EncryptBytes(line);
try
{
bw.Write(value.Length);
bw.Write(value);
}
catch (IOException e)
{
Console.WriteLine(e.Message);
}
写入到文件中之后开始读文件解密,这个也比较简单,直接readbytes,解密返回的byte数组就行。而且也要用字节流的读取,代码
BinaryReader br = new BinaryReader(new FileStream(@"C:\Share\Data\afterkey.txt", FileMode.Open));
int len = br.ReadInt32();
byte[] cache = br.ReadBytes(len);
Console.WriteLine(cache.Length);
Console.WriteLine("data:\n" + Encoding.UTF8.GetString( DecryptBytes(cache)));
br.Close();
这个是模拟本地的加密写入,然后读取解密,把读取解密的过程放到unity里面,改动的不多,但是也是很坑的。首先加密写入的过程还是由本地来操作,然后把加密后写入的文件放到文件服务器上下载,之后利用unity的www访问文件的字节流,直接解密这个字节流就行,代码如下:
IEnumerator DownLoadData()
{
Debug.Log("down load data");
Debug.Log(url_02);
WWW w = new WWW(url_02);
yield return w;
if (!string.IsNullOrEmpty(w.error))
{
Debug.LogError(w.error);
}
if (w.isDone)
{
Debug.Log(w.text);
}
Debug.Log(w.bytes.Length);
Debug.Log(Encoding.UTF8.GetString( DesDoString.DecryptBytes(w.bytes)));
}
这里面desdostring. DecryptBytes跟上面的方法完全一样。这里一定要注意www.bytes的长度。这个bytes的长度=声明字节长度内容的长度+字节内容的长度。拿上面代码来说,如果你利用BinaryWriter先写入字节长度,在写入字节内容。这样的话你使用www获取到的字节长度就是字节内容的长度+声明字节长度内容的长度,也就是说加入你这个文本字节内容长度之后400,但是其实你log下www.bytes的长度其实是404,多了4个长度,这就会导致你解密异常。所以在前面写入字节的时候,一定不要写入字节长度,即bw.Write(value.Length)这句要注释掉,这样的话www.bytes的长度就与文本字节长度一致了。