我们有一个非常老旧的、不受支持的程序,可以在SMB共享之间复制文件。它具有检查和复制文件内容前是否发生更改的校验和算法。该算法似乎很容易被欺骗——我们刚刚发现了一个例子,其中两个文件除了一个'1'变成了'2'外完全相同,但返回相同的校验和。以下是该算法:
unsigned long GetFileCheckSum(CString PathFilename)
{
FILE* File;
unsigned long CheckSum = 0;
unsigned long Data = 0;
unsigned long Count = 0;
if ((File = fopen(PathFilename, "rb")) != NULL)
{
while (fread(&Data, 1, sizeof(unsigned long), File) != FALSE)
{
CheckSum ^= Data + ++Count;
Data = 0;
}
fclose(File);
}
return CheckSum;
}
我不是一个很擅长编程的人(我是一名系统管理员),但我知道基于异或的校验和会相当粗糙。使用这种算法,两个大小相同但内容不同的文件返回相同的校验和的几率有多大?(我不期望得到精确答案,“远程”或“相当可能”都可以。)
如何在不影响性能的情况下改进它?
最后,fread()
是怎么回事?我快速浏览了文档,但还是没看懂。是将 Data
依次设置为文件的每个字节吗?编辑:好吧,它将文件读入到 unsigned long
(假设这里是32位操作系统)块中。每个块包含什么?如果文件内容是 abcd
,第一次传递时 Data
的值是什么?它是(在 Perl 中):
(ord('a') << 24) & (ord('b') << 16) & (ord('c') << 8) & ord('d')