В консольном приложении Windows C ++ я хотел бы прочитать пароль из командной строки. Пароль используется для шифрования (и более поздней расшифровки, возможно, где-нибудь еще в мире на компьютере с Windows с другой локалью). Поэтому я беспокоюсь о локалях и кодировке этой парольной фразы, которые не дают того же числового представления. На том же компьютере или компьютере с той же локалью это, очевидно, не создает проблем.
Поэтому я хотел бы иметь возможность фиксировать кодирование (и нормализацию?) И хранить как UTF-8. что рекомендуется здесь: http://www.jasypt.org/howtoencryptuserpasswords.html (пункт 4).
Существует много проблем, связанных с кодировкой / unicode / UTF-8 / кодовыми страницами, которые я не полностью (или не совсем) понимаю. Я возился с boost: locale и boost :: nowide, но не смог разобраться или он не работает под windows (не знаю). Некоторые ссылки с большим количеством разъяснений по вопросам (окнам):
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/
Но эти ссылки решают противоположную проблему! Как заставить вещи выглядеть одинаково, независимо от того, какое базовое представление, мне нужно одно и то же [побитовое] представление, независимо от того, как оно выглядит!
Таким образом, вопрос в том, как мне убедиться (и должен ли я?), Чтобы локаль / кодировка не влияла на базовые данные, которые шифруются, данные, как в смысле массива 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).
Во-первых, UTF-8 — это красная сельдь. Чтобы быть международным, вы должны использовать международный набор символов, стоит рассмотреть только один, и он называется Unicode. То, как вы представляете Unicode в своей программе (то есть, как вы его кодируете), зависит от вас, если кодировка может представлять весь Unicode, то проблем нет. Вы можете выбрать UTF-8, но, так как вы работаете в Windows, кажется разумным выбрать кодировку, которую Windows использует для внутреннего использования — UTF-16. Как говорит bmargulies, вы можете использовать MultiByteToWideChar для перехода от локального представления (то есть локальной кодовой страницы) к UTF-16. Я не вижу необходимости делать дополнительный шаг и генерировать UTF-8 из UTF-16, но если вы хотите это сделать, вы можете использовать WideCharToMultiByte.
Если ваше приложение составлено с _UNICODE
тогда просто позвони WideCharToMultiByte
с кодовой страницей UTF-8, чтобы получить UTF-8. Если ваше приложение не скомпилировано с _UNICODE
, вызов MultiByteToWideChar
чтобы получить UTF-16 из ваших байтов ACP, а затем позвоните WideCharToMultiByte
чтобы получить UTF-8.
Поскольку код, который вы добавили, показывает std :: string, данные предположительно находятся в ACP для системы. Так что рецепт здесь будет работать. Сейчас для этого есть множество удобных API, таких как mbtowcs
, Не отвлекайтесь на «МБ». Это просто Windows-говорят «не UTF-16».