CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2002 ГОД

Мышление в стиле Visual Basic

Андрей ГОНЧАРОВ ag@ukr.net

(Продолжение, начало см. в МК № 6, 9—10, 19, 25, 27, 29—30, 33, 36—38, 45, 48, 3 (125, 128—129, 138, 144, 146, 148—149, 152, 155—157, 164, 167, 174))
Прошлый урок объяснил вам, что такое CryptoAPI, зачем нужна вообще криптография со своими сильными и слабыми сторонами; я попытался рассказать, почему сегодня криптография является оптимальным способом защиты информации, наряду с хард- и софт-изолированием ресурсов. Сегодня мы продолжим знакомиться с API-вызовами функций из разряда криптографических. Понятно, что для работы с данным материалом вам понадобится, как минимум, набор установленных компонентов. Это либо IE 3.3x, либо операционная система семейства MS Windows не ниже Win95 OSR2. Следует учесть также, что не лишним окажется обновление ОС: если у вас имеется какой-либо MS Win-сервиспак, то самое время найти ему применение. Идеальными условиями является Win98 (лучше — Win2000, WinXP), IE5+.

Итак, теперь мы умеем перечислять провайдеров криптослужб. Однако кроме этого нам может потребоваться знание их типов... Другими словами, требуется перечисление типов провайдеров, доступных (установленных) в системе. Если перечисление самих крипт-провайдеров производится применением CryptEnumProviders, то перечисления их типов можно добиться вызовом очень похожей функции — достаточно сменить в вызове несколько слов:

Как видно, функции действительно весьма идентичны.

Обратите внимание на ByVal в списке передаваемых аргументов pdwProvType и pcbTypeName — единственные параметры, передаваемые по ссылке, здесь являются контейнерами для получаемых от функции значений, а переданные по значению аргументы не могут быть изменены внутри функции (по умолчанию — в случаях без явного указания — VB подразумевает передачу по сылке (ByRef)).

Для зарезервированных аргументов по-прежнему передаем нули.

При помощи тех же интерфейсных функций можно узнать, какой из провайдеров назначен в качестве «провайдера по умолчанию». В этом нам поможет CryptGetDefaultProvider.

В первом аргументе мы даем наводку CryptoAPI на предмет того, каким типом следует определить Default-провайдера; второй аргумент зарезервирован для будущих поколений Таблица.Crypto-интерфейсов; третий несет в себе опцию: либо CSP назначается по умолчанию для текущего пользователя, либо он является Default в рамках данной машины (в первом случае (юзер) передаем &H2, во втором (компьютер) —&H1.В документации по Win32API этим значениям назначены константы: CRYPT_MACHINE_DEFAULT = &H1 и CRYPT_USER_DEFAULT = &H2); в четвертом параметре мы получаем результат — имя провайдера по умолчанию; в пятом после завершения функции будет храниться длина имени провайдера.

Функция возвращает данные логического типа — используйте CBool для соответствующего преобразования типов.

Кроме определения провайдера по умолчанию, вы можете его также назначить. Для этого следует передать по значению функции CryptSetProvider константы (или их значения) имени провайдера (строкового типа) и его типа (типа Long). В результирующей переменной типа Boolean можно отловить результат ее выполнения — опять-таки через CBool.

Кстати, если в качестве первого параметра функции CryptAcquireContext (см. прошлый урок) передать пустую строку (запомните — в интерфейсах API используют VB-константу vbNullString!!!), то будет открыт контекст именно «умолчательного» провайдера.

Сама по себе функция назначения провайдера шифро-сервиса хороша, но не достаточно для «продвинутых» крипто-программ. Здесь у вас связаны руки по причине отсутствия возможности применения опций. В тех случаях, когда различают Default-провайдеров для текущего пользователя или компьютера (рабочей станции) в целом, а также дополнительные аспекты обращения к этой функции, удобнее использовать CryptSetProviderEx. Эта функция, кроме упомянутых аргументов, принимает еще два дополнительных: собственно опции (dwFlags) и зарезервированный аргумент (передавайте ноль).

В качестве опций можно использовать &H1, &H2 или &H4 — соответствующие им константы в документации озвучены как CRYPT_MACHINE_DEFAULT, CRYPT_USER_DEFAULT и CRYPT_DELETE_DEFAULT. Несложно догадаться, что &H4 (CRYPT_DELETE_DEFAULT) означает удаление (или аннулирование) провайдера по умолчанию.

Различные типы провайдеров поддерживают различные алгоритмы шифрования (или формирование цифровой подписи)... Очевидный вывод. Естественно, для того чтобы реализовать в программе тот или иной алгоритм шифрования, необходимо позаботиться о типе провайдера, который может обеспечить программу данным алгоритмом. В таблице приведены типы провайдеров и поддерживаемые ими алгоритмы — в качестве примера взят CryptoAPI в версии, поставляемой с IE5.

Вызовы рассмотренных функций

Демонстрацию вызовов упомянутых функций было бы логично начать с перечисления доступных в ОС провайдеров крипто-сервисов. Так и поступим.

Для начала создаем обычный проект VB 6.0 — Standard EXE. Помещаем на главную форму список (ListBox). Имена элементам управления задавайте самостоятельно, на свой вкус, или же следуйте моему примеру и именуйте компоненты так, чтобы вы впоследствии были в состоянии что-либо разобрать в коде через неделю-другую. Мой список провайдеров назван lstProviders, имена единственной пары кнопок, нажатие на которые вызывает заполнение списка, выбраны произвольно, поскольку не принципиальны.

Перечисление провайдеров, как вы помните, происходит в функции CryptEnumProviders. До тех пор, пока она не возвращает логическое False (получаемое от преобразования результата через CBool), мы получаем информацию о следующем провайдере. Таким образом, введя вызов в цикл, нетрудно добиться формирования целого списка провайдеров:

Таким же образом можно построить и код формирования списка типов провайдеров — за редким исключением нижеприведенный код повторяет предыдущий:

Полный исходный код простейшей программы, перечисляющей имена провайдеров криптослужб Win32 и их типов, доступен на http://www.vb.kiev.ua.

Хеширование

Еще с незапамятных времен человеку пришла в голову мысль защищать информацию, имущество и пр. с помощью паролей. Возможно, пример окажется не самым удачным, однако ключ и дверной замок все же являются неким подобием принципа «пароль-система_доступа». Ну, примеров можно понапридумывать с дюжину, речь не о способах защиты, а о той концепции «ключ-доступ», которая до боли знакома и встречается нам в быту чуть ли не каждый день.

Как известно, в компьютерных программах довольно часто используются всякого рода защитные «мульки», наподобие серийных номеров программных продуктов, активирующих их ключей и даже пароли доступа к Сети Интернет. Некоторые провайдеры (по крайней мере киевские) используют собственноручно слепленные программы, генерирующие пароли RAS. Возможно, проще составлять пароли вручную :-). И опять-таки, речь не о способах...

Пароль

Что такое пароль, ясно и так. Вы вводите его в нужное место в программе, та в свою очередь проверяет его на «правильность», после чего решает, впускать ли вас в защищенную область. На данном этапе некоторые программисты на Visual Basic допускают весьма грубые ошибки, рассчитывая на незыблемость визуальных компонентов (все равно, встроенных или внешних), кода VB и неграмотность хакеров (в данном случае я вынужден применить это слово), которые вдруг загорятся желанием взломать софт. Во-первых, всегда приветствуется сохранение данных в переменных вместо использования ЭУ, видимых или невидимых во время выполнения. Объясню: поскольку все в Win32 строится на сообщениях, несложно отловить любые свойства любого из компонентов в приложении, равно как и все текущие на данный момент процессы. Таким образом, у заинтересованного лица на ладони могут оказаться разблокированные «звездочки»-пароли, текст в скрытых полях и т. д. Во-вторых, сама структура защитного блока кода программы должна строиться не на свойствах типа Enabled/Disabled (вернее, значениях соответствующего свойства —True/False), а на функциональных ветвлениях хода выполнения. Например, программу нельзя считать хорошо защищенной только исходя из неактивности кнопки «Далее». Например, используя сообщения Windows, можно изменить свойства любого из компонентов программы, в том числе и кнопки «Далее» в неграмотно сделанном инсталляторе...

Итак, что такое пароль с точки зрения CryptoAPI?

Да, вы в чем-то правы: пароль — это ваш ключ к софтверной парадной двери. Однако он лишь косвенно принимает участие в шифровании/обработке. Как правило, идея пароля состоит в том, чтобы пользователь хранил его в своей памяти, не прибегая к запискам на клочках бумаги, надписям на клавиатуре или сзади монитора, и вводил при необходимости для идентификации. Защита по принципу «да кому все это нужно?!» или «у меня ничего важного нет», конечно, не вызовет особого доверия у тех, кто хотя бы раз оплатил чьи-то прогулки по Интернету :-)... Пароль должен быть «удобозапоминаем» (или по крайней мере удобочитаем) и, естественно, уникален. Это главные к нему требования. Таким образом, пароль типа «Vasya» ни на что не годен. Однако я знаю множество людей, которые:

1) Выбирают в качестве паролей на Yahoo! mail свои «имена наоборот» (нет в русском языке слов, чтоб выразить мое негодование) :-);

2) Используют латинскую раскладку и вводят там свои имена «якобы-по-русски». Неплохо придумано, правда? :-)... Вроде бы, да только существует масса утилит для BruteForce-переборов по словарю, причем многие из них такие штучки уже имеют в виду... Наверное... :-)

Каков же выход? Как выбирать пароль, чтобы тот оставался читаемым, относительно понятным, и при этом шифрование на его основе давало сколько-нибудь надежный результат? Ведь недостаточно длинный пароль (читай: ключ для алгоритма шифрования) не в состоянии надежно закупорить информацию, а доводить его в качестве заполнителя (например, «vasyavasyavasya») до необходимой длины нам тоже незачем, так как первый враг шифрования — закономерность... Да и не только поэтому. Все просто, господа: на основе пароля (можно использовать даже слова из трех букв!) генерируется — прозрачно для пользователя — хеш, причем в большинстве случаев он (хеш) уже будет состоять из достаточного количества знаков. На основе хеша генерируется пароль. Вы спросите: ну, так что же такое хеш? Хеш — это «временный» (во многих алгоритмах он действительно, отработав, уничтожается, «забывается», однако нередко хеш является объектом сравнения, цифровыми «отпечатками пальцев» в особо критичных ситуациях; такой хеш хранится неопределенно долго) мусор, который генерируется, дабы обеспечить подходящую длину пароля, т. к. в формировании зашифрованного текста будет принимать участие поочередно каждый из элементов обоих массивов символов. Таким образом, длина пароля (хеша) должна хотя бы равняться длине шифруемой информации. Так, по широкоизвестному алгоритму MD5 слово «Andy» будет иметь такой хеш: da41bceff97b1cf96078ffb249b3d66e. Очевидно, что это неподходящий пароль, потому как запомнить его может только гений (и то не всякий), однако в качестве ключа для шифрования подходит. Не даром хеширование считается основой защиты/проверки/аутентификации во многих системах фильтрации доступа — практически на всех платформах. Таким образом, при вводе пользователем пароля «Andy» в шифрующую функцию поступает «da41bceff97b1cf96078ffb249b3d66e». Однако на этом положительные стороны хеширования не заканчиваются: генерируя хеш строчной информации, мы можем проверить, достоверна ли она, порой даже не глядя в ее текст. И еще: не обязательно хранить в Системе (на винчестере) «открытый» (в смысле human-readable) пароль — достаточно сохранить его хеш, после чего при необходимости сравнивать хеш преподносимой строки с хешем, сохраненным локально. Между прочим, CryptoAPI создает хеш на основании таких параметров, как имя машины, временная метка, отношение веса пыли из под кулера к его диаметру, серийный номер ковра для мыши и частота кадров монитора, деленная на количество непристойностей в Temporary Internet Files :-) — то есть, расшифровке хеш не поддается в принципе :-)*.

* Хеш является результатом необратимого процесса генерирования псевдослучайных (о компьютерных случайностях я говорил ранее) чисел, он действительно основан на комбинациях параметров ОС, временной метки и др., отчего считается уникальным производным и даже носит название «односторонний», т. к. алгоритм его формирования исключает возможность взлома, «расшифровки», — если такой термин здесь вообще уместен.

Один из самых распространенных — благодаря скорости выполнения и простоте реализации — методов шифрования является классическая пара «обычный_текст-зашифрованный_текст». Тогда получатель при расшифровке, используя тот же пароль, который был использован для шифрования информации, будет следовать обратной, «зеркальной» схеме: «зашифрованный_текст-обычный_текст». Очевидный факт...

Такой «стиль» шифрования называют симметричным. Это самая простая из всех существующих схем шифрования. Существует еще много интересных концептуальных методов запереть на ключ парадную дверь — это и шифровальные блокноты, и многочисленные подстановочные таблицы (классический пример: каждый символ сообщения подлежит подстановке согласно таблице или списку символов, или согласно арифметическому расчету), обработка ASCII-массива на n-позиций, элементарный XOR-based алгоритм, шифрование по модулю n и т. д. — однако отнюдь не все дожили до теперешнего времени в виду их несостоятельности в борьбе со взломами. Типичный алгоритм по модулю 26 (количество латинских кнопочек у вас на клавиатуре) мы рассмотрим в ближайшее время как «передышку» между моими CryptoAPI-атаками Читателя :-). Кстати, это и есть основанный на исключении (XOR) алгоритм. А пока попрошу приготовиться к вызову CryptCreateHash.

Что, все оказалось настолько просто? — спросит Читатель... Нет — отвечу я, — все куда проще.. :-)

(Продолжение следует)

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov