Crypto++ HexEncoder 无法始终如一地工作

问题描述

这是我的代码

#include <cryptopp/hex.h>

#include <string>
#include <iostream>

void hexlify(CryptoPP::byte* bytes,std::string &hex_string,size_t size)
{
    CryptoPP::StringSource ss(bytes,size,true,new CryptoPP::HexEncoder(new CryptoPP::StringSink(hex_string)));
}

void unhexlify(std::string hex_string,CryptoPP::byte* &bytes)
{
    std::string decoded;

    CryptoPP::StringSource ss(hex_string,new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded)));

    std::cout << decoded + "\n"; // For testing
    bytes = (CryptoPP::byte*)decoded.data();
}

int main()
{
    std::string seed = "BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60";
    std::cout << "\n" + seed + "\n";

    CryptoPP::byte* b;
    unhexlify(seed,b);

    std::string s;
    hexlify(b,s,32);

    std::cout << s;
    std::cout << "\n\n";
}

它应该采用 32 字节、64 字符的十六进制字符串 seed,打印它,将其转换为字节,然后将其转换回十六进制字符串 (s) 并打印它。我还让它在 unhexlify 函数中打印解码的字符串。

我的期望是输出如下所示:

BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60

第一行(seed)和第三行(s,种子转换成字节然后返回)应该是一样的。而且很少,这正是发生的事情。然而,大多数时候第一行和第三行是完全不同的。

奇怪的是,我对代码进行了零更改,而且我什至没有重新编译它。但是每次我运行可执行文件时,它都会说不同的东西。更奇怪的是,每次运行第三行都不一样。同样,即使我在不​​更改代码或重新编译的情况下运行相同的可执行文件,也会发生这种情况。以下是 5 次运行的输出

BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC0AE8B7F0000AB7615AD06EA16A2889A960301000000189C960301000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205B40C2B87F0000AB7615AD06EA16A288FA9B060100000018FC9B0601000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC07DA67F0000AB7615AD06EA16A2885A6C0B01000000185C6C0B01000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC06EB47F0000AB7615AD06EA16A288DAAE090100000018DCAE0901000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC0F9EB7F0000AB7615AD06EA16A288DAF5010100000018DCF50101000000

第二行每次都一样,所以我知道问题出在 hexlify 函数和/或 Crypto++ HexEncoder。此外,AB7615AD06EA16A2 部分在 seeds 中始终匹配。匹配的部分从第 17 个字符到第 32 个字符。对于我尝试的每一粒种子,这总是发生。但其他一切通常都不同。

我不明白为什么它没有正确地将字节编码为十六进制字符串。而且我不明白为什么即使我没有对代码进行任何更改,它也很少起作用。而且我特别不明白每次运行相同的编译代码输出会如何不同。这是怎么回事?

解决方法

void unhexlify(std::string hex_string,CryptoPP::byte* &bytes)
{
    std::string decoded;

    CryptoPP::StringSource ss(hex_string,true,new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded)));

    std::cout << decoded + "\n"; // For testing
    bytes = (CryptoPP::byte*)decoded.data();  // <--
}

您返回指向局部变量 decoded 拥有的缓冲区的指针,该缓冲区在函数退出后消失。通过将悬空指针传递给 hexlify,您会得到未定义的行为。要解决问题,请从 std::string unhexlify(std::string hex_string) 返回字符串并调用 hexlify(bytes.data(),s. bytes.size())

,

这个函数看起来很可疑:

void unhexlify(std::string hex_string,CryptoPP::byte* &bytes)
{
    std::string decoded;
    // stuff added to decoded,maybe...
    bytes = (CryptoPP::byte*)decoded.data();
}

decoded 是一个局部变量,在函数退出时被销毁,但是您让 bytes 指向它的内部数据,导致悬空指针(这是未定义的行为,并且不同输出由此解释。)

您应该只返回解码后的返回值(按值),并将其存储在调用者的堆栈中。然后在该函数在调用代码中返回后将字节设置为其数据。