Региональный этап Всероссийской олимпиады профессионального мастерства обучающихся по специальности среднего профессионального образования 10.02.03 Информационная безопасность автоматизированных систем Профессиональное задание 1 часть Используя стандартные элементы управления Windows Form, cоздать текстовый редактор c возможностью шифрования и дешифрования введенной текстовой информации. Для шифрования и дешифрования использовать интерфейс CryptoAPI. При разработке программы использовать ассиметричный метод шифрования. Данный текстовый редактор должен обеспечить: 1. Создание открытого и закрытого ключей в виде отдельных файлов с разным расширением. 2. Шифрование информации с использованием закрытого ключа и класса RSACryptoServiceProvider среды NET. FrameWork 4.0. 3. Дешифрование информации с использованием открытого ключа и класса RSACryptoServiceProvider среды NET. FrameWork 4.0. 4. Сохранение зашифрованной информации в отдельном файле. 2 часть Используя Windows Form для ввода логина и пароля, создать программу формирования и сохранения зашифрованной информации о пароле пользователя в отдельном файле. Данная программа должна обеспечить проверку соответствия пароля и зашифрованной в файле информации. Для решения поставленной задачи рекомендуется использовать классы SHA256Managed и HashAlgorithm для получения хештаблицы пароля. Данные классы описаны в пространстве имен System.Security.Cryptography. Кроме того, программа должна исключить возможность появления одной и той же хеш-таблицы пароля даже при наборе разными пользователями одинакового символьного пароля. 1. Алгоритм выполнения заданий. Работа с CryptoAPI. Прототипы функций CryptoAPI описаны в файле wincrypt.h. Названия функций имеют префикс Crypt. Для использования этих функций в свойствах проекта нужно определить константу _WIN32_WINNT и задать ей значение 0x0400 (или больше). Данная константа применяется в файле wincrypt.h для проверки версии Windows. Для некоторых функций CryptAPI также требуются библиотеки crypt32.lib и advapi32.lib. 2. Криптопровайдер. Прежде чем использовать какие-либо функции Crypto API, необходимо запустить криптопровайдер. Делается это с помощью функции CryptAcquireContext: BOOL CRYPTFUNC CryptAcquireContext( HCRYPTPROV* hCryptProvider,//дескриптор провайдера, out-параметр LPCTSTR pszContainer, // имя контейнера ключей LPCTSTR pszProvider, // имя провайдера DWORD dwProvType, // тип провайдера DWORD dwFlags // флаги ) Кроме инициализации криптопровайдера, данную функцию можно использовать для создания и удаления контейнеров ключей. Для этого параметру dwFlags присваивается значение, соответственно, CRYPT_NEWKEYSET и CRYPT_DELETEKEYSET. Функция CryptAcquireContext работает в два этапа: сначала она ищет криптопровайдер по имени и типу, указанному в аргументах, а затем контейнер ключей с заданным именем. По окончании работы с криптопровайдером необходимо вызвать функцию CryptReleaseContext (см. листинг 1). Работа с ключами 3. Генерация ключей. В CryptoAPI имеются функции для генерации ключей любого типа. Функция CryptGenKey генерирует сессионные ключи и пары для обмена и подписи на основе случайного числа. BOOL CRYPTFUNC HCRYPTPROV ALG_IG DWORD HCRYPTKEY* ) CryptGenKey( hProv Algid dwFlags phKey Сессионные ключи можно сгенерировать также на основе некоторого заданного значения (пароля) при помощи функции CryptDeriveKey. Это стоит делать, например, в том случае, когда нужно избежать пересылки сессионного ключа вместе с зашифрованными данными (см. рис. 2). Получатель данных, зная пароль и алгоритм, может сам сгенерировать сессионный ключ и с его помощью расшифровать данные (см. листинг 2). Рис. 2. Шифрование. 4. Получение дескриптора ключа. Дескриптор открытого ключа можно получить, вызвав функцию CryptGetUserKey. 5. Экспорт ключей. Операция экспорта выполняется при сохранении сессионных ключей и при передаче ключей третьим лицам. Двоичные данные ключа могут быть получены при помощи функции CryptExportKey: BOOL CRYPTFUNC CryptExportKey ( HCRYPTKEY hKeyToExport HCRYPTKEY hCryptKey DWORD dwBlobType DWORD dwFlags BYTE* pbData, // указатель на буфер DWORD* pdwDataLen ) // длина буфера Поясним значения аргументов. Первый аргумент — дескриптор экспортируемого ключа. Второй аргумент — дескриптор ключа, которым шифруется экспортируемый ключ. Открытые ключи экспортируются в незашифрованном виде. В этом случае hCryptKey = 0. При экспорте сессионных и закрытых ключей необходимо их предварительно зашифровать. Аргумент hCryptKey должен содержать дескриптор открытого ключа получателя. При вызове с аргументом pbData = NULL функция вернет необходимую длину буфера по адресу, на который указывает аргумент pdwDataLen (см. листинг 3). После успешного завершения переменная dwSessionKeyLen будет содержать действительную длину BLOB-структуры ключа. Это значение необходимо сохранить для обратной операции — импорта ключа в криптопровайдер. 6 Импорт ключей. Ключи импортируются функцией CryptImportKey: CryptImportKey ( HCRYPTPROV hProv BYTE* pbData DWORD dwDataLen HCRYPTKEY DWORD HCRYPTKEY* hCryptKey dwFlags phImportedKey ) hCryptKey = 0 в том случае, если импортируемый ключ был зашифрован асимметричным ключом или не был зашифрован вообще. Если импортируемый ключ шифровали сессионным ключом, то hCryptKey должен содержать дескриптор этого ключа. По окончании работы с ключом необходимо для его дескриптора вызвать функцию CryptDestroyKey(HCRYPTKEY hKey). Шифрование и дешифровка данных. 7. В CryptoAPI для шифрования и дешифровки используются и симметричный, и асимметричный алгоритмы. Симметричный алгоритм менее надежен, но работает намного быстрее, чем асимметричный. Поэтому в CryptoAPI применяется комбинация алгоритмов. Данные шифруются с помощью симметричного алгоритма с сессионным ключом, а сам сессионный ключ шифруется по асимметричному алгоритму открытым ключом получателя. Дешифровка происходит в обратном порядке: сначала закрытым ключом получателя дешифруется сессионный ключ, затем этим сессионным ключом дешифруются сами данные (см. рисунки 2 и 3). Рис. 3. Дешифровка. Таким образом, расшифровать данные можно только, имея закрытый ключ из той же ключевой пары, что и открытый ключ, которым данные были зашифрованы. Для шифрования и дешифровки применяется функция (см. листинг 4). BOOL CRYPTFUNC CryptEncrypt ( HCRYPTKEY hKey, // дескриптор ключа для шифрования HCRYPTHASH hHash BOOL bFinal BYTE* pbData, // параметр [in, out DWORD* pdwDataLen, // параметр [in, out DWORD dwBufferLen ) Последний и предпоследний параметры являются одновременно входными и выходными. Это означает, что зашифрованные данные записываются поверх исходных в буфер pbData, а длина данных, соответственно, в dwBufferLen. Как и в случае с функцией Crypt-ExportKey, CryptEncrypt позволяет предварительно определить необходимый размер буфера под зашифрованные данные. Для этого нужно вызвать функцию с аргументами: pbData = NULL; pdwDataLen = длина исходных данных. Длину буфера функция вернет по адресу: pdwDataLen. Дешифровка данных производится аналогично функцией CryptDecrypt. Необходимое обрудование: ПК с ОС Windows и установленной средой NET. FrameWork 4.0.