将 C++ std::string 转换为 UTF-16-LE 编码的字符串

我今天已经搜索了几个小时,但找不到任何适合我的东西.我刚刚看过的一个,没有运气,是如何将 UTF-8 编码的 std::string 转换为 UTF-16 std::string".

我的问题是,简要说明:

我想在 std C++ 中创建一个有效的 NTLM 哈希,并且我正在使用 OpenSSL 的库来使用其 MD4 例程创建哈希.我知道怎么做,那么有谁知道如何将 std::string 转换为 UTF-16 LE 编码的字符串,我可以将其传递给 MD4 函数以获得正确的摘要?

那么,我可以拥有一个保存 char 类型的 std::string,并将其转换为 UTF16-LE 编码的可变长度 std::string_type 吗?是 std::u16string 还是 std::wstring?

我会使用 s.c_str() 还是 s.data() 并且 length() 函数会在两者中正确报告案例?

解决方案

抱歉,第一手...这将是一个带有一些长代码的丑陋回复.我最终使用了以下函数,同时在 iconv 中按文件有效地编译到我的 Windows 应用程序文件中:)

希望这会有所帮助.

char* conver(const char* in, size_t in_len, size_t* used_len){const int CC_MUL = 2;//16 位设置区域设置(LC_ALL,");char* t1 = setlocale(LC_CTYPE, "");char* locn = (char*)calloc(strlen(t1) + 1, sizeof(char));如果(锁定 == NULL){返回0;}strcpy(locn, t1);const char* enc = strchr(locn, '.') + 1;#if _WINDOWSstd::string win = "WINDOWS-";赢 += 编码;enc = win.c_str();#万一iconv_t foo = iconv_open("UTF-16LE", enc);if(foo == (void*)-1){如果(错误号 == EINVAL){fprintf(stderr, "不支持从 %s 转换
", enc);}别的{fprintf(stderr, "初始化失败:
");}免费(锁定);返回0;}size_t out_len = CC_MUL * in_len;size_t saved_in_len = in_len;iconv(foo, NULL, NULL, NULL, NULL);char* 转换 = (char*)calloc(out_len, sizeof(char));char *converted_start = 转换;char* t = const_cast(in);int ret = iconv(foo,&t,&in_len,&转换,&out_len);iconv_close(foo);*used_len = CC_MUL * saved_in_len - out_len;如果(ret == -1){开关(错误号){案例 EILSEQ:fprintf(stderr, "EILSEQ
");休息;案例 EINVAL:fprintf(stderr, "EINVAL
");休息;}错误(图标");免费(锁定);返回0;}别的{免费(锁定);返回converted_start;}}

I've been searching for hours today and just can't find anything that works out for me. The one I've just had a look at, with no luck, is "How to convert UTF-8 encoded std::string to UTF-16 std::string".

My question is, with a brief explanation:

I want to make a valid NTLM hash in std C++, and I'm using OpenSSL's library to create the hash using its MD4 routines. I know how to do that, so does anyone know how to convert the std::string into a UTF-16 LE encoded string which I can pass to the MD4 functions to get a correct digest?

So, can I have a std::string which holds the char type, and convert it to a UTF16-LE encoded variable length std::string_type? Whether that be std::u16string, or std::wstring?

And would I use s.c_str() or s.data() and would the length() function report correctly in both cases?

解决方案

Apologies, firsthand... this will be an ugly reply with some long code. I ended up using the following function, while effectively compiling in iconv into my windows application file by file :)

Hope this helps.

char* conver(const char* in, size_t in_len, size_t* used_len)
{
    const int CC_MUL = 2; // 16 bit
    setlocale(LC_ALL, "");
    char* t1 = setlocale(LC_CTYPE, "");
    char* locn = (char*)calloc(strlen(t1) + 1, sizeof(char));
    if(locn == NULL)
    {
        return 0;
    }

    strcpy(locn, t1);
    const char* enc = strchr(locn, '.') + 1;

#if _WINDOWS
    std::string win = "WINDOWS-";
    win += enc;
    enc = win.c_str();
#endif

    iconv_t foo = iconv_open("UTF-16LE", enc);

    if(foo == (void*)-1)
    {
        if (errno == EINVAL)
        {
            fprintf(stderr, "Conversion from %s is not supported
", enc);
        }
        else
        {
            fprintf(stderr, "Initialization failure:
");
        }
        free(locn);
        return 0;
    }

    size_t out_len = CC_MUL * in_len;
    size_t saved_in_len = in_len;
    iconv(foo, NULL, NULL, NULL, NULL);
    char* converted = (char*)calloc(out_len, sizeof(char));
    char *converted_start = converted;
    char* t = const_cast<char*>(in);
    int ret = iconv(foo,
                    &t,
                    &in_len,
                    &converted,
                    &out_len);
    iconv_close(foo);
    *used_len = CC_MUL * saved_in_len - out_len;

    if(ret == -1)
    {
        switch(errno)
        {
        case EILSEQ:
            fprintf(stderr,  "EILSEQ
");
            break;
        case EINVAL:
            fprintf(stderr,  "EINVAL
");
            break;
        }

        perror("iconv");
        free(locn);
        return 0;
    }
    else
    {
        free(locn);
        return converted_start;
    }
}

相关文章