将十六进制转换为可打印的字符串/字符

时间:2019-01-24 21:38:02

标签: c++ c debugging winapi cng

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

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

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

我该怎么做?

6 个答案:

答案 0 :(得分:2)

要以十六进制编码字节数组并将编码后的数据写入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字符串”是不安全的,因为二进制数据可以包含内部零字节。要了解CNG生成的哈希的长度,请调用BCryptGetProperty以获取BCRYPT_HASH_LENGTH属性。

答案 1 :(得分:1)

我们可以在此处将CryptBinaryToStringList address1;final List<String> address1 = List<String>();CRYPT_STRING_HEXASCIICRYPT_STRING_HEXCRYPT_STRING_HEXRAW结合使用,以设置所需的格式字符串。例如

CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF

答案 2 :(得分:0)

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

但是,如果您想在代码本身中执行此操作,那么我是在较早的线程中发现的(又不是我的工作,而是KEINE LUST中的@ here的工作)< / p>

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;
}

答案 3 :(得分: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]);
}

答案 4 :(得分:0)

将字符叠起来并打印数值(十六进制)。

#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";
}

答案 5 :(得分:0)

我正在围绕我的项目中使用的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"));