c++ 将带有“:”的十六进制字符串转换为原始"binary"字符串

c++ convert hexadecimal string with ":" to original "binary" string

我有以下代码可以将加密的密文转换为可读的十六进制格式:

std::string convertToReadable(std::string ciphertext)
{
    std::stringstream outText;

    for(unsigned int i = 0; i < ciphertext.size(); i++ )
        outText << std::hex << std::setw(2) << std::setfill('0') << (0xFF & static_cast<byte>(ciphertext[i])) << ":";

    return outText.str();
}

这个函数的可读结果是这样的:

56:5e:8b:a8:04:93:e2:f1:5c:20:8b:fd:f5:b7:22:0b:82:42:46:58:9b:d4:c1:8e:ac:62:85:04:ff:7f:c6:d3:

现在我需要返回,将可读格式转换为原始格式ciphertext以便解密:

std::string convertFromReadable(std::string text)
{
    std::istringstream cipherStream;

    for(unsigned int i = 0; i < text.size(); i++ )
    {
        if (text.substr(i, 1) == ":")
            continue;

        std::string str = text.substr(i, 2);
        std::istringstream buffer(str);
        int value;
        buffer >> std::hex >> value;
        cipherStream << value;
    }

    return cipherStream.str();
}

这不是绝对有效,因为我找回了错误的字符串。

如何修复 convertFromReadable() 以便我可以恢复原来的 ciphertext

感谢您的帮助

在进一步调试之前,您应该解决以下问题:

  • cipherStream 应该是 ostringstream,而不是 istringstream
  • for 循环应该在结束前停止两个字符。否则你的 substr 将会失败。使循环条件i+2 < text.size()
  • 当您从输入中读取两个字符时,您需要将 i 提前两个,即在 std::string str = text.substr(i, 2); 行之后添加 i++
  • 因为要字符输出,所以在写数据到cipherStream的时候加一个cast到char,即cipherStream << (char)value

很好,您的代码可以正常工作了。只是想我会说明一种使用流的稍微简单、更直接的方法,而无需繁琐的索引跟踪和子字符串提取:

std::string convertFromReadable(const std::string& text)
{
    std::istringstream iss(text);
    std::ostringstream cipherStream;
    int n;
    while (iss >> std::hex >> n)
    {
        cipherStream << (char)n;
        // if there's another character it better be ':'
        char c;
        if (iss >> c && c != ':')
            throw std::runtime_error("invalid character in cipher");
    }
    return cipherStream.str();
}

请注意,在最后一个十六进制值之后,如果没有冒号,if (iss >> c... 测试将评估 falsewhile (iss >> ... 测试也会评估,一直到 return。