问题描述
我试图通过读取文件的内容来创建文件的哈希值,然后使用 SHA1
对其进行哈希处理,之后我尝试使用此哈希值创建一个文件名,但问题只有哈希值的前两个字符字符串被占用。
哈希函数
void hash(const std::string& content,std::string& retValue,bool isFile)
{
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx,content.c_str(),content.size());
if (isFile) {
FILE* f = fopen(content.c_str(),"r");
assert(f != NULL);
char buffer[1024]={0};
while(fgets(buffer,1024,f))
SHA1_Update(&ctx,buffer,strlen(buffer));
fclose(f);
}
unsigned char hash[SHA_DIGEST_LENGTH] = {0};
SHA1_Final(hash,&ctx);
retValue.resize(60);
int cnt = 0;
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
char ch[3] = {0};
sprintf(ch,"%02x",hash[i]);
retValue[cnt++] = ch[0];
retValue[cnt++] = ch[1];
retValue[cnt++] = ch[2];
}
std::cout<<retValue<<std::endl;
}
当我在控制台中打印哈希值时,我得到一个有效的 val,例如 51d946cde43e90ec03493f88914ca948b5215916
,但在这种情况下它只包含前两个字符 '51',我切换到 gdb 来查看字符串,gdb 显示我以一种奇怪的方式将字符串 51\000d9\000\064\066\000cd\000e4\000\063e\000\071\060\000ec\000\060\063\000\064\071\000\063f\000\070\070\000\071\061\000\064c\000a9\000\064\070\000b5\000\062\06 1\000\065\071\000\061\066
。我正在使用 std::ofstream
保存文件。我看过上一个答案,说这是 gdb 中的一个错误,所以它会像这样打印,但在这里我可以看到创建的文件不是只有第一个哈希字符。
为什么会这样?
谢谢。
- - - - - - - - - - - - - - - - - - - - - - - -编辑 - -------------------------------------------------- ---------------------
从 dvix 的评论来看,它得到了解决,我用 ch[2] 复制了 '\0',所以基本上我只需要从每个十六进制字符 ch[0] 和 ch[1] 复制前两个字符,然后放置null 在字符串的最后。
所以for循环里面的代码应该是这样的
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
char ch[3] = {0};
sprintf(ch,hash[i]);
retValue[cnt++] = ch[0];
retValue[cnt++] = ch[1];
}
retValue[cnt] = '\0';
解决方法
这是一个稍微短一点的版本,它做同样的事情:
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
sprintf(retValue + cnt,"%02x",hash[i]);
cnt += 2;
}