将 HEX 转换为可打印 string/char

Convert HEX to printable string/char

我正在使用 CNG 生成哈希。 BCryptFinishHash 调用的结果是十六进制形式的输入的 MD5。 示例:

char *outHash = "\x02\x34\x75..."

我想将其转换为可打印字符串:02347501...

我该怎么做?

如果您需要一个简单的一次性解决方案,这是一个有用的工具: https://codebeautify.org/hex-string-converter

但是,如果您想在自己的代码中执行此操作,我是从较早的线程中找到的(也就是,这不是我的工作,而是@KEINE LUST from here 的工作)

int main(void)
{
unsigned char readingreg[4];
readingreg[0] = 0x4a;
readingreg[1] = 0xaa;
readingreg[2] = 0xaa;
readingreg[3] = 0xa0;
char temp[4];

sprintf(temp, "%x", readingreg[0]);
printf("This is element 0: %s\n", temp);
return 0;
}

你可以这样打印:

for(const char *wsk=outHash; *wsk; ++wsk){
    printf("%02hhx", *wsk);
}

编辑基于 cstring 可以有 0x00 数字。
C

const char outHash[] = "\x02\x34\x75";
const int size = sizeof(outHash)/sizeof(char) - 1;
for(int i = 0; i < size; ++i){
    printf("%02hhx", outHash [i]);
}

C++

std::string outHash = "\x02\x34\x75";
for(int i = 0; i < outHash.size(); ++i) {
    printf("%02hhx", outHash [i]);
}

我们可以在这里使用 CryptBinaryToStringCRYPT_STRING_HEXASCII or CRYPT_STRING_HEX or CRYPT_STRING_HEXRAW or CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF or CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF depen how you want format string .例如

void print(PUCHAR pbHash, ULONG cbHash, DWORD dwFlags = CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF)
{
    ULONG cch = 0;
    if (CryptBinaryToStringW(pbHash, cbHash, dwFlags, 0, &cch))
    {
        if (PWSTR sz = (PWSTR)_malloca(cch * sizeof(WCHAR)))
        {
            if (CryptBinaryToStringW(pbHash, cbHash, dwFlags, sz, &cch))
            {
                DbgPrint("%S\n", sz);
            }
            _freea(sz);
        }
    }
}

要以十六进制编码字节数组并将编码数据写入 std::string,请执行以下操作:

static inline char
hex_digit(unsigned int n)
{
    if (n < 10) return '0' + n;
    if (n < 16) return 'a' + (n - 10);
    abort();
}

std::string
encode_bytes(const unsigned char *bytes, size_t len)
{
    std::string rv;
    rv.reserve(len * 2);
    for (size_t i = 0; i < len; i++) {
        rv.push_back(hex_digit((bytes[i] & 0xF0) >> 4));
        rv.push_back(hex_digit((bytes[i] & 0x0F) >> 0));
    }
    return rv;
}

请注意,您必须知道字节数组的长度。将其视为以 NUL 结尾的 "C string" 是不安全的,因为二进制数据可以包含内部零字节。要知道 CNG 生成的散列的长度,请调用 BCryptGetProperty 以获取 BCRYPT_HASH_LENGTH 属性.

遍历字符并打印数值(十六进制)。

#include <iostream>
#include <iomanip>

int main()
{
    char*  outHash = "\x02\x34\x75\x01\x23\xff";  // Get from your Hash function.
    int    sizeOfHash = 6;                        // Use appropriate size for BCryptFinishHash()


    // Set up the characteristics of the stream.
    // setw(2):       Each printed object will use a min width of 2
    // setfill('0'):  If the object is less than 2 char then fill the space with '0'
    // hex:           Print numbers in hex.
    std::cout << std::setw(2) << std::setfill('0') << std::hex;

    // Create a view of the object.
    // Makes it simpler to loop over.
    std::string_view view(outHash, sizeOfHash);

    // Loop over the string.
    for(unsigned char val: view) {
        // Convert to `unsigned char` to make sure you don't print
        // negative numbers. Then convert from there to `int` so that
        // the `std::hex will kick in and convert to hex value.
        std::cout << static_cast<int>(val);
    }   
    std::cout << "\n";
}

我正在围绕我在项目中使用的 Windows Crypto API & CNG 开发 C++ 包装器。我计划将其全部移动到 github,但目前它只是一项正在进行的工作,但您会发现它对 HEX / Base64 编码/解码等加密基础知识很有用。

https://github.com/m4x1m1l14n/Crypto

您可以使用 Crypto::Hex::Encode() 方法来实现您想要的。

#include <Crypto\Hex.hpp>
#include <Crypto\Random.hpp>

using namespace m4x1m1l14n;

char arr[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0x99, 0x00 };

encoded = Crypto::Hex::Encode(arr, sizeof(arr));

/* encoded = "aabbccdd9900" */

您也可以使用位于 Hash 命名空间中的 MD5 包装器,就像这样。 (如果您使用的数据量不大)

#include <Crypto\Hex.hpp>
#include <Crypto\Hash.hpp>

using namespace m4x1m1l14n;

encoded = Crypto::Hex::Encode(Crypto::Hash::MD5("Whatever you want to hash"));