我试图通过字符串流提取十六进制的哈希摘要,但在迭代数据时无法使其工作。
使用std::hex
,我可以很容易地使用普通整数文字来完成这项工作,比如:
#include <sstream>
#include <iostream>
std::stringstream my_stream;
my_stream << std::hex;
my_stream << 100;
std::cout << my_stream.str() << std::endl; // Prints "64"
然而,当我尝试从摘要中推送数据时,它只是将数据解释为字符,并将它们推送到字符串流中。以下是功能:
#include <sstream>
#include <sha.h> // Crypto++ library required
std::string hash_string(const std::string& message) {
using namespace CryptoPP;
std::stringstream buffer;
byte digest[SHA256::DIGESTSIZE]; // 32 bytes or 256 bits
static SHA256 local_hash;
local_hash.CalculateDigest(digest, reinterpret_cast<byte*>(
const_cast<char*>(message.data())),
message.length());
// PROBLEMATIC PART
buffer << std::hex;
for (size_t i = 0; i < SHA256::DIGESTSIZE; i++) {
buffer << *(digest+i);
}
return buffer.str();
}
类型byte
只是unsigned char
的typedef,所以我不明白为什么它不能正确输入。使用std::cout
打印返回值会导致ASCI混乱的正常字符解释。为什么它在第一种情况下有效,而在第二种情况下无效?
示例:
std::string my_hash = hash_string("hello");
std::cout << hash << std::endl; // Prints: ",≥M║_░ú♫&Φ;*┼╣Γ₧←▬▲▼ºB^s♦3bôïÿ$"
首先,std::hex
格式修饰符适用于整数,而不是字符。由于您正在尝试打印unsigned char
,因此不会应用格式修饰符。您可以通过转换为int
来解决此问题。在您的第一个示例中,它之所以有效,是因为文字100
被解释为一个整数。如果将100
替换为例如static_cast<unsigned char>(100)
,则将不再获得十六进制表示。
其次,std::hex
是不够的,因为您可能希望将每个字符填充为2位十六进制值(即F
应打印为0F
(。您还可以通过应用格式修饰符std::setfill('0')
和std::setw(2)
(reference,reference(来修复此问题。
应用这些修改,您的代码将如下所示:
#include <iomanip>
...
buffer << std::hex << std::setfill('0') << std::setw(2);
for (size_t i = 0; i < SHA256::DIGESTSIZE; i++) {
buffer << static_cast<int>(*(digest+i));
}