Статьи Королевства Дельфи

Собственно сам PGPsdk


28 октября 1997 г. PGP, Inc. объявила о поставке PGPsdk сторонним производителям программного обеспечения. PGPsdk - это средство разработки для программистов на С, позволяющее разработчикам программного обеспечения встраивать в него стойкие криптографические функции. Можно сказать что в PGPsdk реализованы все функции пакета PGP, мало того - версия PGP начиная с 5.0 хранит криптографические функции в динамических библиотеках – dll (о том насколько это не безопасно – вопрос к Крису Касперски, я лишь скажу что насколько я силен в математике).

PGPsdk - это динамическая библиотека, состоящая из трех файлов [табл. 1], поддерживающая базовые алгоритмы криптования (перечислены выше), гибкое управление ключами, сетевой интерфейс и др. (можно использовать одну библиотеку - PGP_sdk.dll, если Вы не будите использовать фирменный интерфейс пользователя от NAI и сетевую библиотеку).

Установка

Скачайте архив с PGPsdk [9], на момент написания статьи доступна версия 1.7.2 (должен заметить что архив занимает 3 с лишним мегабайт), необходимо его разархивировать и из каталога \Libraries\DLL\Release взять следующие файлы - табл. 1

Табл.1
PGP_SDK.dllдля криптования, управление ключами и т.д.
PGPsdkUI.dll (UI= user interface) интерфейсные штучки, если Вам нужно будет только шифровать/расшифровывать, то этот файл необязателен. Но очень полезен для ввода пароля, выбора получателей сообщений, генерации ключей и другое.
PGPsdkNL.dll (NL= network library) сетевая библиотека для работы с сервером ключей или для transport layer security. Ее мы рассматривать не будем, но в ближайшем будущем я попытаюсь ее описать.

Собственно распространять Вам приложение придется с этими файлами, подложить их необходимо или в системный каталог WINDOWS или в каталог вместе с приложением - механизм стандартный как и для всех dll, главное чтоб библиотеку было видно Вашему приложению.

Переходим к делу.

Для работы система предоставляет ряд низкоуровневых PGP API (Application Programmig Interface) функций. Заголовки (хеадеры, описания) этих функций поставляются вместе с пакетом на Ц и лежат в каталоге Headers. Если Вы как и я пишите на Delphi, можете сами сконвертировать их, а можете взять готовые тут [10]. Это проект по переводу Ц-ных хеадеров на любимый мною язык программирования. Занимается всем этим делом Стивен Хейлер (Steven R. Heller ).


Описатели переведены на Delphi по принципу как это сделано для Ц - разбросаны на кучи модулей (листинг 1). Все названия модулей аналогичны Ц-ным заголовкам, за исключением pgpEncode - переименовано в pgpEncodePas, из-за особенностей объявления в Delphi (нельзя чтоб имя процедуры совпадало с названием модуля).

Листинг 1. Объявление используемых библиотек. uses // PGPsdk pgpEncodePas, pgpOptionList, pgpBase, pgpPubTypes, pgpUtilities, pgpKeys, pgpErrors, // always last pgpSdk;
Единственная трудность, которая возникает на пути включения криптования в Ваше приложение - это использование слишком уж низкоуровневых PGP API функций. Для того что бы сделать какую-нибудь операцию - будь то подсчет публичных ключей в связке или просто зашифровать файл - необходимо создавать контекст, указать где находятся ключи, создать фильтр ключей, подготовить файловые дескрипторы, если с памятью - выделить ее (в случае шифрования-/-расшифрования), затем все это в обратном порядке освободить (если контекст неправильно освобождается - файлы с резервными ключиками не удалятся). И все это при том что в системном каталоге WINDOWS создается файл, в котором содержится информация где находятся файлы с публичными и секретными ключами (о нем будет подробно сказано ниже). Для сравнения работы через PGP API предоставлен листинг2.

Листинг 2. Пример использования PGPsdk через PGP API Var context : pPGPContext; keyFileRef : pPGPKeySet; defaultKeyRing : pPGPKeySet; foundUserKeys : pPGPKeySet; filter : pPGPFilter; countKeys : PGPUInt32; keyFileName : PChar; userID : PChar; inFileRef, outFileRef : pPGPFileSpec; inFileName, outFileName : PChar; Begin // Init от C++ context:=NIL; keyFileName:='pubring.pgp'; userID:=''; inFileName:='myInFile.txt'; outFileName:='myOutFile.txt.asc'; // Begin PGPCheckResult('sdkInit', PGPsdkInit); PGPCheckResult('PGPNewContext', PGPNewContext( kPGPsdkAPIVersion, context )); PGPCheckResult('PGPNewFileSpecFromFullPath', PGPNewFileSpecFromFullPath( context, keyFileName, keyFileRef )); PGPCheckResult('PGPOpenKeyRing', PGPOpenKeyRing( context, kPGPKeyRingOpenFlags_None, keyFileRef, defaultKeyRing )); PGPCheckResult('PGPNewUserIDStringFilter', PGPNewUserIDStringFilter(context, userID, kPGPMatchSubString, filter)); PGPCheckResult('PGPFilterKeySet', PGPFilterKeySet(defaultKeyRing, filter, foundUserKeys)); // Открываем файловые манипуляторы PGPCheckResult('PGPNewFileSpecFromFullPath', PGPNewFileSpecFromFullPath(context, inFileName, inFileRef)); PGPCheckResult('PGPNewFileSpecFromFullPath', PGPNewFileSpecFromFullPath(context, outFileName, outFileRef)); // // А вот здесь уже идет кодирование. // PGPCheckResult('PGPEncode', PGPEncode( context, [ PGPOEncryptToKeySet(context, foundUserKeys), PGPOInputFile(context, inFileRef), PGPOOutputFile(context, outFileRef), PGPOArmorOutput(context, 1), PGPOCommentString(context, PChar('Comments')), PGPOVersionString(context, PChar('Version 5.0 assembly by Evgeny Dadgoff')), PGPOLastOption(context) ] )); // // Освобождаем занимаемые ресурсы и контекст PGP // if (inFileRef<>NIL) then PGPFreeFileSpec(inFileRef); if (outFileRef<>NIL) then PGPFreeFileSpec(outFileRef); if (filter<>NIL) then PGPFreeFilter(filter); if (foundUserKeys<>NIL) then PGPFreeKeySet(foundUserKeys); if (defaultKeyRing<>NIL) then PGPFreeKeySet(defaultKeyRing); if (keyFileRef<>NIL) then PGPFreeKeySet(keyFileRef); if (context<>NIL) then PGPFreeContext(context); PGPsdkCleanup; End;


Здесь реализован пример из [9] со страницы 39. Функция PGPCheckResult позаимствована у Стивена из его примеров - принимает два параметра - строковую и код выполнения функции PGP API, если была ошибка - генерируется исключение и на экран выводится описание ошибки с именем функции (Очень помогает для ловли ошибок, а при вызове dll-библиотеки, тем более написанной на другом языке – помогает избавиться от Access violation).

Листинг 3. Функция PGPCheckResult. procedure PGPCheckResult(const ErrorContext: shortstring; const TheError: PGPError); var s : Array [0..1024] of Char; begin if(TheError<>kPGPError_NoError)then begin PGPGetErrorString(TheError, 1024, s); if(PGPGetErrorString(TheError, 1024, s) = kPGPError_NoError)then raise exception.create(ErrorContext + ' [' + IntToStr(theError)+'] : '+StrPas(s)) else raise exception.create(ErrorContext + ': Error retrieving error description'); end; end;
Там же у Стивена я нашел еще один проект - написанная на Delphi библиотека для VB, проект под названием SimplePGP (SPGP). Дело в том, что VB не может использовать библиотеку PGPsdk из-за ограничения импортирования библиотек dll [9, раздел FAQ]. Сам Стивен предложил мне добавить к проекту еще одну dll, тем самым забыть про PGP API, и использовать облегченную модель вызова функций криптований.

Сам интерфейс к доступу функциям выполнен не плохо, продуманно и вызов их не должен вызвать затруднений у Вас.

Открыв ее я подумал - а не убрать ли мне все эти "stdcall;export;" и просто присоединить библиотеку к ехе-файлу (ну не устраивает меня хитросплетение dll). Сказано сделано.


Содержание раздела