游戏开发中,有很多文件校验需求。如:安装包、更新包、代码、配置文件、资源包等,都可能需要在安装或者下载更新后,甚至每次启动游戏,对相关文件进行完整及正确性校验,确保与最新版本一致。
校验常常使用诸如CRC32、MD5、SHA1等在内一种或多种校验码,检验本地文件和正确文件是否一致。
下面列出这3种实现方式(C#版):
CRC32(全称循环冗余校验)
CRC检验原理实际上就是在一个p位二进制数据序列之后附加一个r位二进制检验码(序列),从而构成一个总长为n=p+r位的二进制序列。附加在数据序列之后的这个检验码与数据序列的内容之间存在着某种特定的关系,即CRC多项式。如果因干扰等原因使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏。因此,通过检查这一关系,就可以实现对数据正确性的检验。
private static ulong[] Crc32Table;
//计算CRC32码表,也可以直接定义
public static void CalculateCRC32Table()
{
ulong value;
Crc32Table = new ulong[256];
int i, j;
for (i = 0; i < 256; i++)
{
value = (ulong)i;
for (j = 8; j > 0; j--)
{
if ((value & 1) == 1)
value = (value >> 1) ^ 0xEDB88320;
else
value >>= 1;
}
Crc32Table[i] = value;
}
}
//获取文件CRC32校验值
public static string GetCRC32FromFile(string fileName)
{
FileStream file = new FileStream(fileName, FileMode.Open);
byte[] buffer = new byte[file.Length];
file.Read(buffer, 0, buffer.Length);
file.Close();
file.Dispose();
//计算CRC32码表
CalculateCRC32Table();
ulong value = 0xffffffff;
for (int i = 0; i < buffer.Length; i++)
{
value = (value >> 8) ^ Crc32Table[(value & 0xFF) ^ buffer[i]];
}
return String.Format("{0:x8}", value ^ 0xffffffff);
}
MD5(Message-Digest Algorithm)
MD5消息摘要算法以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。(百度百科说明)
public static string GetMD5HashFromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] buffer = md5.ComputeHash(file);
file.Close();
file.Dispose();
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
strBuilder.Append(buffer[i].ToString("x2"));
}
return strBuilder.ToString();
}
catch (Exception ex)
{
throw new Exception("GetMD5 fail,error:" + ex.Message);
}
}
SHA1(Secure Hash Algorithm)
SHA1对任意长度明文的预处理和MD5的过程是一样的,即预处理完后的明文长度是512位的整数倍,但是有一点不同,那就是SHA1的原始报文长度不能超过2的64次方,然后SHA1生成160位的报文摘要。SHA1算法简单而且紧凑,容易在计算机上实现。
public static string GetSHA1FromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
SHA1 sha1 = new SHA1CryptoServiceProvider();
byte[] buffer = sha1.ComputeHash(file);
file.Close();
file.Dispose();
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
strBuilder.Append(buffer[i].ToString("x2"));
}
return strBuilder.ToString();
}
catch (Exception ex)
{
throw new Exception("GetSHA1 fail,error:" + ex.Message);
}
}
参考:
https://blog.csdn.net/android_mnbvcxz/article/details/78902737
https://www.cnblogs.com/scu-cjx/p/6878853.html