正确使用openssl获取sha-1文件

我正在尝试为一些文件获取sha-1。 我目前所做的是循环给定path中的文件,分别打开并读取每个文件,并将内容加载到缓冲区中,然后将其发送到openssl的SHA函数以获取散列值。 代码看起来像这样:

void ReadHashFile(LPCTSTR name) { FILE * pFile; long lSize; char * buffer; size_t result; pFile = _tfopen ( name , L"rb" ); if (pFile==NULL) {fputs ("File error",stderr); return;} // obtain file size: fseek (pFile , 0 , SEEK_END); lSize = ftell (pFile); rewind (pFile); if(lSize == -1){fputs ("Read Error",stderr);return;} // allocate memory to contain the whole file: buffer = (char*) malloc (sizeof(char)*lSize); if (buffer == NULL) {fputs ("Memory error",stderr); return;} // copy the file into the buffer: result = fread (buffer,1,lSize,pFile); if (result != lSize) {fputs ("Reading error",stderr); return;} /* the whole file is now loaded in the memory buffer. */ // terminate fclose (pFile); //Do what ever with buffer unsigned char ibuf[] = "compute sha1"; unsigned char obuf[20]; SHA1((const unsigned char*)buffer, strlen((const char*)buffer), obuf); fwprintf(stderr, L"file %s\n", name); int i; for (i = 0; i < 20; i++) { printf("%02x ", obuf[i]); } printf("\n"); free(buffer); } 

有些文件似乎是不可读的,有些给我一个-1大小其他我只能读取前2-3个字节,即使它们不同,也会给出许多相同的文件。

我将不胜感激,如果有人可以帮助我,或者如果有人有文件散列经验。 哦,有没有办法让文件的sha1没有加载整个文件在内存中,我的意思是考虑大文件,这种解决scheme将无法正常工作。

问候

Solutions Collecting From Web of "正确使用openssl获取sha-1文件"

如果在读取文件内容时遇到麻烦,那么调用散列函数代码之前,您的问题与散列无关。

你应该使用标准的fopen()函数,而不是_tfopen() 。 在C中,通常最好避免以下划线开头的东西。 特别是因为_tfopen()似乎映射到fopen()或者Windows特定的_wfopen()这取决于是否所谓的“unicode支持”被激活。 或者,在纯粹的Windows应用程序中,您可能依赖于Win32函数,如CreateFile()

在内存中读取整个文件,然后散列它是粗糙的。 例如,它将无法处理比可用RAM大的文件。 另外,为了知道文件大小,你必须去查找它,这是不可靠的(可能有伪文件实际上是管道进入一些数据生成过程,为此寻求是不可能的)。 散列函数可以通过块处理数据; 您应该使用一个小缓冲区(8 kB是传统的大小),并使用SHA1_Init()SHA1_Update()SHA1_Final()函数。

fread()不一定会按照您的要求读取尽可能多的数据。 这不是一个错误。

当你调用SHA1() ,你的缓冲区使用strlen() ,这是假的。 strlen()返回一个字符串的长度; 换句话说,直到下一个字节值为零的字节数。 许多文件包含值为0的字节。如果文件没有,那么不能保证你的缓冲区包含任何值为0的字节,所以对strlen()的调用可能会在分配的缓冲区之外读取内存是不好的 )。 既然你已经习惯了获取文件长度和分配一个很大的缓冲区的问题,那么至少应该使用这个长度,而不是用一个不这样做的函数来重新计算它。

总结一下:你的代码看起来应该是这样的(未经测试):

 /* * Hash a file, which name is given. Hash output is written out in * buffer "out[]". The hash output consists in exactly 20 bytes. * On success, 0 is returned; on error, returned value is -1 and * out[] is unaltered. */ int do_sha1_file(char *name, unsigned char *out) { FILE *f; unsigned char buf[8192]; SHA_CTX sc; int err; f = fopen(name, "rb"); if (f == NULL) { /* do something smart here: the file could not be opened */ return -1; } SHA1_Init(&sc); for (;;) { size_t len; len = fread(buf, 1, sizeof buf, f); if (len == 0) break; SHA1_Update(&sc, buf, len); } err = ferror(f); fclose(f); if (err) { /* some I/O error was encountered; report the error */ return -1; } SHA1_Final(out, &sc); return 0; } 

不要忘记包含相关的文件头! ( <stdio.h>和OpenSSL的sha.h