Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这个校验和算法可以改进吗?_C++_Algorithm_Checksum - Fatal编程技术网

C++ 这个校验和算法可以改进吗?

C++ 这个校验和算法可以改进吗?,c++,algorithm,checksum,C++,Algorithm,Checksum,我们有一个非常旧的、不受支持的程序,它跨SMB共享复制文件。它有一个校验和算法来确定文件内容在复制之前是否已更改。该算法似乎很容易被愚弄——我们刚刚发现了一个示例,其中两个文件(除了一个“1”变为“2”)返回相同的校验和。以下是算法: unsigned long GetFileCheckSum(CString PathFilename) { FILE* File; unsigned long CheckSum = 0; unsigned long

我们有一个非常旧的、不受支持的程序,它跨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;
}
我不是一个程序员(我是一个系统管理员),但我知道基于XOR的校验和将非常粗糙。对于两个大小相同、内容不同的文件,此算法返回相同校验和的可能性有多大?(我不希望得到准确的答案,“远程”或“很可能”都可以。)

如何在不造成巨大性能损失的情况下进行改进

最后,fread()的
fread()是怎么回事?我快速浏览了一下文档,但还是弄不明白。
Data
是否依次设置为文件的每个字节?编辑:好的,它将文件读入
无符号长
(这里假设为32位操作系统)块。每个区块包含什么?如果文件内容为
abcd
,则第一次通过时
数据的值是多少?是(在Perl中):


(ord('a')您可以使用如下公式轻松改进算法:

Checksum = (Checksum * a + Data * b) + c;
如果a、b和c是大素数,这应该会得到很好的结果。在这之后,旋转(而不是移位!)校验和的位将进一步改善它


使用素数,这是一个与用于的算法类似的算法-它保证了长周期和良好的分布。

我似乎认为您的算法没有努力处理大小不是4字节的精确倍数的文件。fread的返回值不是布尔值,而是实际读取的字节数,这将不同于如果发生EOF或错误,则会检查两者,但只需假设如果它未返回0,则“data”中有4个有效字节用于计算哈希


如果你真的想使用散列,我建议你做几件事。首先,使用一个简单的加密散列,比如MD5,而不是CRC32。CRC32对于检查数据有效性来说是不错的,但是对于跨文件系统和确保没有冲突,它并不是一个很好的工具,因为其他地方的评论中提到了生日悖论。其次,不要编写最后,简单地考虑使用RSyc来复制文件,而不是滚动自己的解决方案。

< P> > Frad BIT是一次读取文件中的一个块。每个块的长度是一个长(C中这不是一个定义良好的大小,但你可以假设32或64位)。根据它是如何缓冲的,这可能不是坏事。Otoh,读取一个较大的块到数组并循环它可能会快很多。

通常用来验证传输文件的完整性。源代码在C++中是容易获得的。它被广泛认为是一种快速和准确的算法。 另请参见

即使是“昂贵”的加密哈希函数也通常需要多次迭代以占用大量时间。尽管不再建议用于加密目的,因为用户会故意尝试创建冲突,但诸如SHA1和MD5之类的函数可广泛使用,并适用于此目的

如果需要较小的散列值,则CRC可以,但不是很好。n位CRC将无法检测到超过n位的一小部分更改。例如,假设文件中只有一个美元金额被更改,从$12345更改为$34567。32位CRC可能会错过该更改

截断较长加密散列的结果将比CRC更可靠地检测更改

{
   CheckSum ^= Data + ++Count;
   Data = 0;
}
我认为“++Count”做不了多少工作。代码与

{
  CheckSum ^= Data;
}
对字节序列进行异或运算是不够的。尤其是对于文本文件。


我建议使用。

我建议您看看,特别是fletcher-32,它应该相当快,并检测当前XOR链不会检测到的各种事情。

SHA-1和(最近的SHA-2)提供了出色的哈希函数,我认为由于更好的哈希属性,它们正在慢慢取代MD5。所有这些都是(md2、sha等)具有高效的实现,并返回数个字符长的缓冲区哈希(尽管总是固定长度)。可以证明,这比将哈希减少为整数更可靠。如果我有druthers,我会使用sha-2。对于实现sha校验和的库,请遵循以下步骤

如果您不想在这些库中编译,linux(可能还有cygwin)有以下可执行文件:md5sum、sha1sum、sha224sum、sha256sum、sha384sum、sha512sum;您可以向它们提供文件,它们将校验和作为十六进制字符串打印出来。 您可以使用popen来执行这些程序,如下所示:

const int maxBuf=1024;
char buf[maxBuf];
FILE* f = popen( "sha224sum myfile", "w" );
int bytesRead = f.read( buf, maxBuf );
fclose( f );
显然,这将运行相当慢,但有助于进行有用的第一次传球。
如果速度是个问题,考虑到像这样的文件散列操作和I/O限制(内存和磁盘访问将成为瓶颈),我希望所有这些算法的运行速度都与生成无符号int的算法一样快。Perl和Python还附带了MD5 SHA1和SHA2的实现,可能与C/C++中的运行速度一样快。

fread正在将一个元素读取到数据的地址。正在读取的元素的大小是无符号长的大小(我认为是8字节)。无符号长字符的大小取决于处理器体系结构(32/64位),这就是为什么使用sizeof。好吧,假设一个大端系统是正确的。在一个小端系统上,情况正好相反。我不知道这对分发有什么帮助!它有助于加强恶意攻击。假设文件是大量ASCII文本,这将确保您不会总是对大约5字节的差异进行异或运算以太,并将通过校验和分散熵
const int maxBuf=1024;
char buf[maxBuf];
FILE* f = popen( "sha224sum myfile", "w" );
int bytesRead = f.read( buf, maxBuf );
fclose( f );