使用固定编码的字符串到字节序列转换,最好是UTF-8

时间:2012-09-08 12:17:54

标签: c++ windows unicode utf-8 codepages

在windows c ++控制台应用程序中,我想从命令行输入中读取密码。密码用于加密(以及后来的解密,可能在具有不同语言环境的Windows PC上的世界其他地方)。所以我担心该密码短语的语言环境和编码没有给出相同的数字表示。在同一台计算机或具有相同语言环境的计算机上,这显然不会产生问题。

因此我希望能够修复编码(和规范化?)并存储为UTF-8。这里推荐:http://www.jasypt.org/howtoencryptuserpasswords.html(第4点)。

有很多与编码/ unicode / UTF-8 / codepages相关的问题我没有完全(或完全没有)掌握。我摆弄了boost:locale和boost :: nowide,但无法解决它或者它在windows下不起作用(dunno)。一些链接有关于涉及的问题(窗口)的更多澄清:

http://alfps.wordpress.com/2011/11/22/unicode-part-1-windows-console-io-approaches/

http://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/

但这些链接解决了相反的问题!无论底层表示如何,如何使事物看起来都一样,无论外观如何,我都需要相同的底层[bit-wise]表示!

所以问题是,我如何确保(并且我必须?)locale / encoding对加密数据的基本数据没有影响,就像8位数组的意义一样整数?我不需要关心UTF-8或Unicode,只需要能够恢复数据,无论什么语言环境/编码。第一个链接有助于解释问题。

思考,C不是Unicode识别,会链接一些C代码帮助,还是C ++会再次改变?或者将输入限制为“ASCII”字符(我知道在Windows上不存在)总是如“在任何Windows计算机上”那样工作?

接受的解决方案:

void EncryptFileNames ( const boost::filesystem::path& p, const std::string& pw );

int main ( int argc, char **argv ) // No checking
{
    // Call with encrypt.exe c:\tmp pässwörd

    boost::nowide::args a ( argc, argv ); // Fix arguments - make them UTF-8

    boost::filesystem::path p ( argv [ 1 ] );

    EncryptFileNames ( p, boost::locale::normalize ( argv [ 2 ], boost::locale::norm_nfc, std::locale ( ) ) );

    return 0;
}

感谢所有捐助者。

PS:对于加密我使用Crypto ++与VS2008SP1和Boost(没有ICU后端)。

2 个答案:

答案 0 :(得分:2)

如果您的应用程序是使用_UNICODE编译的,那么只需使用UTF-8代码页调用WideCharToMultiByte即可获得UTF-8。如果您的应用程序未使用_UNICODE进行编译,请调用MultiByteToWideChar从您的ACP字节获取UTF-16,然后调用WideCharToMultiByte以获取UTF-8。

由于您添加的代码显示std :: string,因此数据可能在系统的ACP中。所以这里的食谱将起作用。现在,有很多方便的API用于此目的,例如mbtowcs。不要被'MB'分心。这只是Windows代表'不是UTF-16'。

答案 1 :(得分:-4)

首先,UTF-8是红鲱鱼。为了国际化,你必须使用国际字符集,只有一个值得考虑,它被称为Unicode。如何在程序中表示Unicode(即如何对其进行编码)取决于您,只要编码可以表示所有Unicode都没有问题。您可以选择UTF-8,但由于您正在使用Windows,因此选择Windows内部使用的UTF-16编码似乎是合理的。正如bmargulies所说,你可以使用MultiByteToWideChar从本地表示(即本地代码页)到UTF-16。我没有看到需要执行额外步骤并从UTF-16生成UTF-8,但如果你想这样做,你可以使用WideCharToMultiByte。