C++ 使用openssl正确获取文件的sha-1
我正在尝试为一些文件获取sha-1。我目前所做的是在给定路径中循环文件,分别打开和读取每个文件,并将内容加载到缓冲区中,然后将其发送到openssl的SHA函数以获取哈希值。代码如下所示:C++ 使用openssl正确获取文件的sha-1,c++,windows,file,cryptography,openssl,C++,Windows,File,Cryptography,Openssl,我正在尝试为一些文件获取sha-1。我目前所做的是在给定路径中循环文件,分别打开和读取每个文件,并将内容加载到缓冲区中,然后将其发送到openssl的SHA函数以获取哈希值。代码如下所示: void ReadHashFile(LPCTSTR name) { FILE * pFile; long lSize; char * buffer; size_t result; pFile = _tfopen ( name , L"rb" ); if (pFile==NULL) {fp
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);
}
void ReadHashFile(LPCTSTR名称)
{
文件*pFile;
长时间lSize;
字符*缓冲区;
结果的大小;
pFile=_tfopen(名称,L“rb”);
if(pFile==NULL){fputs(“文件错误”,stderr);return;}
//获取文件大小:
fseek(pFile,0,SEEK_END);
lSize=ftell(pFile);
倒带(pFile);
if(lSize==-1){fputs(“读取错误”,stderr);return;}
//分配内存以包含整个文件:
缓冲区=(char*)malloc(sizeof(char)*lSize);
if(buffer==NULL){fputs(“内存错误”,stderr);return;}
//将文件复制到缓冲区:
结果=fread(缓冲区,1,lSize,pFile);
if(result!=lSize){fputs(“读取错误”,stderr);return;}
/*整个文件现在加载到内存缓冲区中*/
//终止
fclose(pFile);
//用缓冲器做什么
无符号字符ibuf[]=“计算sha1”;
无符号字符obuf[20];
SHA1((常量无符号字符*)缓冲区,strlen((常量字符*)缓冲区,obuf);
fwprintf(标准格式,L“文件%s\n”,名称);
int i;
对于(i=0;i<20;i++){
printf(“%02x”,obuf[i]);
}
printf(“\n”);
自由(缓冲);
}
有些文件似乎无法读取,有些文件大小为-1,其他文件我只能读取前2-3个字节,这使许多文件具有相同的sha,即使它们不同
如果有人能帮我解决这个问题,或者有人有文件哈希方面的经验,我将不胜感激。哦,有没有一种方法可以在不首先将整个文件加载到内存的情况下获取文件的sha1,我的意思是考虑到大文件,这个解决方案不起作用
关于如果在调用哈希函数代码之前读取文件内容时遇到问题,则问题与哈希无关 您应该使用标准的
fopen()
函数,而不是\u tfopen()
。在C语言中,最好避免以下划线字符开头。特别是由于\u tfopen()
似乎映射到fopen()
或Windows特定的\u wfopen()
,这取决于是否激活了所谓的“unicode支持”。或者,在纯Windows应用程序中,您可以依赖Win32函数,例如CreateFile()
在内存中读取整个文件,然后对其进行哈希运算是很粗糙的。例如,它将无法处理大于可用RAM的文件。另外,为了知道文件的大小,您必须搜索它,这是不可靠的(可能有伪文件实际上是管道到某些数据生成过程中,而搜索是不可能的)。散列函数可以按块处理数据;您应该使用一个小的缓冲区(8 kB是传统大小),并使用SHA1_Init()
、SHA1_Update()
和SHA1_Final()
函数
fread()。这不是一个错误
调用SHA1()
时,在缓冲区上使用strlen()
,这是假的strlen()
返回字符串的长度;简而言之,直到下一个字节的值为零为止的字节数。许多文件包含值为0的字节。如果文件没有,则无法保证缓冲区中包含任何值为0的字节,因此对strlen()
的调用可能最终读取分配的缓冲区之外的内存(这是错误的)。由于您在获取文件长度和分配如此大的缓冲区时遇到了麻烦,因此您至少应该使用该长度,而不是尝试使用不这样做的函数重新计算它
总而言之:您的代码应该是这样的(未经测试):
不要忘记包含相关的文件头!(
,以及来自OpenSSL的sha.h
)
/*
* 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;
}