如何在 c++ 中生成十六进制二进制数据的 sha256 哈希?
How to generate sha256 hashes of hexadecimal binary data in c++?
我需要C++中的一个函数来生成与此命令在 Linux 中生成的类似结果。
echo -n "616161616161616" | xxd -r -p | sha256sum -b | awk '{print $1}'
此命令的作用是:给定一个六转储,将其转换为二进制文件格式,并显示二进制文件的 sha256 哈希。xxd -r 将六转储转换为二进制文件
谁能帮我?
首先,您应该知道您的命令行版本缺少半字节。 也就是说,如果你通过 xxd -r -p 发送'616161616161616
',然后通过 xxd 发送回去,你会看到这个:
echo -n "616161616161616" | xxd -r -p | xxd
00000000: 6161 6161 6161 61 aaaaaaa
请注意,缺少最后一个半6
。xxd 实用程序使用成对数字的十六进制。一旦没有更多的对,它就会停止并发出最终输出。您可能期望将前导半字节视为单个八位字节的行为,因此如下所示:
echo -n "0616161616161616" | xxd -r -p | xxd
00000000: 0616 1616 1616 1616 ........
无论哪种情况,无论您想如何处理,您都应该意识到这个问题。
关于您的实际问题,OpenSSL库具有一组相当丰富的功能,可让您几乎微不足道地完成大部分问题。从输入字符串计算摘要相当简单:
#include <iostream>
#include <vector>
#include <string>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
int main()
{
std::string strHex = "616161616161616"; // get this from wherever
// prepend zero-nibble for odd character counts.
if (strHex.length() % 2)
strHex.insert(strHex.begin(), '0');
// convert to blob. returns dynamic memory allocated with
// OPENSSL_malloc. Use OPENSSL_free to destroy it.
long len = 0;
unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);
// digest the blob
const EVP_MD *md_algo = EVP_sha256();
unsigned int md_len = EVP_MD_size(md_algo);
std::vector<unsigned char> md( md_len );
EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);
// free the input data.
OPENSSL_free(bin);
// print the buffer to stdout in hex.
char *hexOut = OPENSSL_buf2hexstr(md.data(), md_len);
std::cout << hexOut << 'n';
OPENSSL_free(hexOut);
return 0;
}
请注意,上面的代码采用在奇数输入长度的情况下预置零半字节的方法。如果这不是您想要的行为(即,如果您想要与问题文本完全相同的忽略尾随奇数蚕食行为(,另一种方法是修剪最后一个蚕食(我严重怀疑您想要的是它删除相关位并且是摘要冲突的配方,但您的调用(。
#include <iostream>
#include <vector>
#include <string>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
int main()
{
std::string strHex = "616161616161616"; // get this from wherever
// prepend zero-nibble for odd character counts.
if (strHex.length() % 2)
strHex.pop_back();
// convert to blob. returns dynamic memory allocated with
// OPENSSL_malloc. Use OPENSSL_free to destroy it.
long len = 0;
unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);
// digest the blob
const EVP_MD *md_algo = EVP_sha256();
unsigned int md_len = EVP_MD_size(md_algo);
std::vector<unsigned char> md( md_len );
EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);
// free the input data.
OPENSSL_free(bin);
// print the buffer to stdout in hex.
char *hexOut = OPENSSL_buf2hexstr(md.data(), md_len);
std::cout << hexOut << 'n';
OPENSSL_free(hexOut);
return 0;
}
在上述两种情况下,生成的输出都预配置为冒号分隔的八位字节。 即后一个示例输出如下所示:
E4:62:40:71:4B:5D:B3:A2:3E:EE:60:47:9A:62:3E:FB:A4:D6:33:D2:7F:E4:F0:3C:90:4B:9E:21:9A:7F:BE:60
这是由于OPENSSL_buf2hexstr
的功能相当有限。如果这不是您想要的(可能不是(,您可以随时使用简单的查找表自己手动打印它,将每个八位字节处理为两个半字节:
#include <iostream>
#include <vector>
#include <string>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
int main()
{
std::string strHex = "616161616161616";
// prepend zero-nibble for odd character counts.
if (strHex.length() % 2)
strHex.pop_back();
// convert to blob. returns dynamic memory allocated with
// OPENSSL_malloc. Use OPENSSL_free to destroy it.
long len = 0;
unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);
// digest the blob
const EVP_MD *md_algo = EVP_sha256();
unsigned int md_len = EVP_MD_size(md_algo);
std::vector<unsigned char> md( md_len );
EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);
// free the input data.
OPENSSL_free(bin);
// dump as continuous hex string
static const char alpha[] = "0123456789abcdef";
for (auto c : md)
{
std::cout << alpha[ (c >> 4) & 0xF];
std::cout << alpha[ c & 0xF];
}
std::cout.put('n');
return 0;
}
输出
e46240714b5db3a23eee60479a623efba4d633d27fe4f03c904b9e219a7fbe60
无论如何,比我预期的要长,但希望这是你要找的。
实际算法取决于你想要做什么 - 你可以将十六进制转换为字符串。我在下面的示例中做到了这一点。
您首先要做的是将字符串转换为二进制,这可以通过以下方式完成:
std::string toBin(std::string str){
int s = str.length();
std::string bin = ""
for (int i = 0; i <= n; i++){
int v = int(s[i]);
while (val > 0){
(val % 2)? bin.push_back('1') : bin.push_back('0');
val /= 2;
}
}
std::reverse(bin.begin(), bin.end());
}
但是,代码的下一部分太长了,很遗憾我无法将其包含在此答案中。但是我会将您链接到一个包含(希望(您需要的所有代码的网站。http://www.zedwood.com/article/cpp-sha256-function
愿你安好。
- 如何从dicom文件中读取二进制数据
- 如何在Qt中从数据库中检索二进制数据?
- 如何使用位字段将数据从二进制文件复制到结构中?
- readsome() 适合在 Windows 上读取二进制数据吗?
- 如何使用 redis-plus-plus 存储二进制数据,就像我想存储结构一样?@for_stack?
- 在CRC-16 CCITT中将数据从二进制解码为文本,我应该输入一个码字,使用CRC生成器进行编码
- 将包含二进制数据的 QByteArray 传递到按值运行
- C++ 尝试优化每一帧将数据打印到二进制文件
- 如何在 c++ 中生成十六进制二进制数据的 sha256 哈希?
- 在处理网络、二进制数据和序列化时应使用流或容器
- 我能确定从文件中读取的 32 字节二进制数据等于 256 位吗?
- C++:如何通过 curl 调用使用 HTTP post 请求发送二进制数据(protobuf 数据)
- 使用二进制数据更新 PostgreSQL 表
- 在打印方法中,难以在二进制树中打印数据
- 使用二进制数据和无符号字符
- sd_journal_send发送二进制数据.如何使用日志检索数据?
- 从带有 std::ifstream::read() 的文件中读取 int 遍历 char * 二进制数据
- 将文本和二进制数据连接到一个文件中
- 二进制模式 + 格式化文本操作或文本模式 + 二进制数据操作 - 有意义吗?
- 如何仅使用 std::filebuf 将数据(二进制模式)写入文件