首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尝试计算文件的Blake2哈希时非常奇怪的错误

尝试计算文件的Blake2哈希时非常奇怪的错误
EN

Stack Overflow用户
提问于 2019-04-10 00:38:40
回答 2查看 0关注 0票数 0

我正在编写一个小程序来使用libsodium来计算文件的哈希值(blake2b)并发现自己正在盯着一个奇怪的bug。

我的十六进制输出中缺少零,这不是由哈希过程引起的,因为我们使用相同的256位截断哈希函数。

两者都使用Blake2b(针对x64进行了优化)。

我确保验证文件是否被读取,即使是输出完全不同,因为它是一个散列函数(1位足以有不同的输出)。

我还使用C风格的打印和C ++流来查看它是否与格式说明符有关,这表明情况并非如此。

我的程序输出如下:

代码语言:javascript
运行
复制
479b5e6da5eb90a19ae1777c8ccc614b5c8f695c9cffbfe78d38b89e40b865

使用b2sum命令行工具时

代码语言:javascript
运行
复制
b2sum / bin / ls -l 256
479b5e6da5eb90a19ae1777c8ccc614b ** 0 ** 5c8f695c9cffbfe78d38b89 ** 0 ** e40b865
代码语言:javascript
运行
复制
#include<iostream>
#include<fstream>
#include<sstream>
#include<ios>
#include<vector>

#include<sodium.h>

using namespace std;

int main(int argc, char** argv)
{
    using buffer = vector<char>;

    ifstream input(argv[1],ios::binary | ios::ate); 
    // get file size 
    streamsize filesize = input.tellg();
    input.seekg(0,ios::beg);
    // make a buffer with that filesize
    buffer buf(filesize);
    // read the file
    input.read(buf.data(),buf.size());
    input.close();
    // show filesize 
    cout << "Filesize : " << filesize << endl;
    // using the snipped from libsodium docs 
    // https://libsodium.gitbook.io/doc/hashing/generic_hashing
    // Example 1
    unsigned char hash[crypto_generichash_BYTES];

    crypto_generichash(hash,sizeof(hash),(unsigned char*)buf.data(),buf.size(),NULL,0);

    // Print the hash in hexadecimal
    for(int i = 0; i < crypto_generichash_BYTES; i++)
    {
        printf("%x",hash[i]);
    }
    cout << endl;
    // load the hash into a stringstream using hexadecimal
    stringstream ss;
    for(int i=0; i<crypto_generichash_BYTES;++i)
        ss << std::hex << (int)hash[i];
    std::string mystr = ss.str();  
    // output the stringstream
    cout << mystr << endl;
    cout << "hash length :" << mystr.length() << endl;


}
EN

Stack Overflow用户

发布于 2019-04-10 10:06:53

你应该使用类似的东西:

代码语言:javascript
运行
复制
printf("%02x",hash[i]);

打印出字节。这将正确处理十六进制值小于16,在你的版本,会简单的输出一个单独的十六进制数字。

您可以在以下程序中看到:

代码语言:javascript
运行
复制
#include <cstdio>

#define FMT "%02x"
int main() {
    printf(FMT, 0x4b);
    printf(FMT, 0x05);
    printf(FMT, 0xc8);
    putchar('\n');
}

有了FMT如上定义,您可以看到正确4b05c8。随着它的定义(如你"%x"所知),你会看到错误4b5c8

而且,顺便说一句,你可能想要考虑抛弃C遗留物(a)之类的东西printf。我知道它在标准中,但几乎没有人(b)使用它因为它的局限性,尽管iostream相当于更加冗长。

或者做我们已经完成的工作并且只使用fmt库来获得更简洁但仍然是类型安全的输出,特别是因为它目前正在针对C + 20(因此在某些时候几乎肯定会成为标准的一部分)。

(a)没有人希望被称为C +程序员,那个从未完全接受语言全部功能的奇怪品种:-)

(b)基于我曾与之合作的中等数量C ++开发人员的样本:-)

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100009004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档