以十六进制表示向字符串流输入数据

Inputting data to stringstream with hexadecimal representation

我正在尝试通过字符串流提取十六进制的哈希摘要,但在遍历数据时我无法让它工作。

使用 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 的类型定义,所以我不明白为什么输入不正确。使用 std::cout 打印 return 值会给出正常字符解释的 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));
    }