Сообщений 3    Оценка 15        Оценить  
Система Orphus

Использование PGP SDK

Часть 3. Цифровая подпись.

Автор: Алексей Кирюшкин
The RSDN Group
Опубликовано: 22.06.2003
Исправлено: 13.03.2005
Версия текста: 1.1

Функции PGP SDK, используемые при наложении цифровой подписи
PGPOClearSign
PGPODetachedSig
PGPOSignWithKey
PGPNewUserIDStringFilter
PGPFreeFilter
PGPFilterKeySet
PGPOrderKeySet
PGPFreeKeyList
PGPNewKeyIter
PGPFreeKeyIter
PGPKeyIterNext
PGPOHashAlgorithm
Поддержка операции наложения цифровой подписи в классе CSimplePGP
Демонстрационная программа PGPTest3

Класс CSimplePGP – исходные тексты (Win API, STL)
Демонстрационный проект (VC7.1, WTL7)
Исполняемый файл демонстрационной программы – PGPtest3.exe (для запуска необходимы PGP_SDK.dll, PGPsdkUI.dll и PGPsdkNL.dll)
PGP_SDK.dll
PGPsdkUI.dll
PGPsdkNL.dll

Функции PGP SDK, используемые при наложении цифровой подписи

Собственно наложение цифровой подписи осуществляется функцией PGPEncode, описанной в первой части. В дополнение к уже описанным ранее в данной операции участвуют следующие опции:

PGPOClearSign

PGPOptionListRef PGPOClearSign(
                   PGPContextRef pgpContext,
                   PGPBoolean clearSign );
pgpContextИспользуемый PGP-контекст
clearSignУстанавливается в TRUE, если не нужно шифровать открытый текст, на который накладывается подпись.

Данную опцию можно устанавливать только при наложении подписи на текстовую информацию, т.к. при установке данной настройки в TRUE автоматически устанавливаются в TRUE опции PGPOArmorOutput и PGPODataIsASCII. Подписываемый текст и собственно подпись находятся в одном файле (буфере памяти), разделенные соответствующими текстовыми метками:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

   Сим  заверяем  вас,  глубокоуважаемый  Заказчик,  в нашем совершеннейшем
почтении  и  безграничном уважении к Вам и нуждам Вашего Бизнеса. По поводу
некоторой  задержки  сроков  реализации  вашего  Заказа, а также превышения
предполагаемой  суммы затрат на 143%, нижайше просим перечитать пункт 4.7.2
Типового Договора На Разработку Программного Решения, "Риски проекта".

-----BEGIN PGP SIGNATURE-----
Version: CSimplePGP v3.0
Comment: no comment

iQA/AwUBPvPF3sJmEIGmukqAEQJJIACgnQA6Ydj8aGzR5Aln6nUVQ0skZakAmgJr
qBv2VMWGGjjuF6qYKTo6URTy
=ZOZa
-----END PGP SIGNATURE----- 

PGPODetachedSig

PGPOptionListRef PGPODetachedSig(
                   PGPContextRef pgpContext,
                   PGPOptionListRef firstOption,
                   ...,
                   PGPOLastOption() );
pgpContextИспользуемый PGP-контекст
firstOptionПервая дополнительная опция
...Список других необходимых опций
PGPOLastOption()Последняя опция в списке, показывает, что список опций закончен

При передаче в PGPEncode указывает на необходимость создания цифровой подписи в отдельном файле, при этом не требуется передавать никаких дополнительных опций в PGPODetachedSig. При передаче в PGPDecode указывает на источник, в котором содержится цифровая подпись для верификации. В этом случае необходимо передать в PGPODetachedSig одну из опций PGPOInputBuffer, PGPOInputFile или PGPOInputFileFSSpec для связи с источником цифровой подписи.

При наложении цифровой подписи с опцией PGPODetachedSig на основе подписываемой информации создается хеш, который затем шифруется секретным ключом (с запросом пароля секретного ключа), полученная таким образом подпись помещается в отдельный файл (либо буфер). Если дополнительно задана опция PGPOArmorOutput (выходные данные в виде ASCII), подпись будет иметь следующий вид:

-----BEGIN PGP SIGNATURE-----
Version: CSimplePGP v3.0
Comment: no comment

iQA/AwUBPvO98sJmEIGmukqAEQJFGQCeMUeux9Ttu0q28pCcnlUj6VV/iSsAn2Ox
8FQcX9zKRf4vbOpAqpQILVic
=PC/t
-----END PGP SIGNATURE-----

Если PGPOArmorOutput не установлена, подпись создается в бинарном формате.

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

Если при наложении цифровой подписи опция PGPODetachedSig не была установлена, секретным ключом подписывающего шифруется вся подписываемая информация, соответственно результат будет иметь вид, близкий к следующему:

-----BEGIN PGP MESSAGE-----
Version: CSimplePGP v3.0
Comment: no comment

owEljzFLXEEQx98paU6OGMRGEAZJiMjjwalBK1NoJWnyASKkUBDExisstVOb+AWC
sdFGm5Sp4iFYiZekTTG3d/Pe3t7u3r5d8IQz6NylWWZ3Zn77+x9G74dfFJbCz7Hq
xuj+2Y/VvVdD03+ib3/L0+H12vjS+eKxWj052rn4N34afZ38tDDxbuXgy+eTmceV
m+/LH99+eHlZ2K+MbG5vbG6tl5PKbqUQRREA/JIaMhTknkiDwDyGRjvUrbJBYIqk
ey24QYVZV6oYBBh84Lnc8sIDGUMtvpaKHdv1ZKQECXXKGg6N7Bqroc8YvCuoouau
CWmTiypTGhauZGYoxwTubJ8hbDOAIWW9dbbFVk1yqZKQO9YR4AjbMsN7xon/+wMx
jAHBo0qJGY5Ej73kE3DZ7Ng2NjgDw/KgdY+R3qHnEFCen3sTg5EpcgIetrns5yBH
XenRP0InGOVhPllIZuG37Mvxh9d8COsQbhFqmDmsW68C3DnLmbU23C4VazQwiGGq
JnPWZzgpj1NJqfgM
=kuyX
-----END PGP MESSAGE-----

Если при верификации удастся расшифровать это сообщение открытым ключом подписавшего, значит информация дошла до нас в неизмененном виде.

PGPOSignWithKey

PGPOptionListRef PGPOSignWithKey(
                   PGPContextRef pgpContext,
                   PGPKeyRef sigKey,
                   PGPOptionListRef firstOption,
                   ...,
                   PGPOLastOption() );
pgpContextИспользуемый PGP-контекст
sigKeyKлюч для подписи
firstOptionПервая дополнительная опция
...Список других необходимых опций
PGPOLastOption()Последняя опция в списке, показывает, что список опций закончен

В списке опций шифрования, требуемых для PGPOSignWithKey должна быть передана одна из опций PGPOPasskeyBuffer, PGPOPassphrase, PGPOPassphraseBuffer, задающих пароль для секретного ключа (см. вторую часть статьи).

PGPNewUserIDStringFilter

PGPError PGPNewUserIDStringFilter(
           PGPContextRef pgpContext,
           char const *userIDString,
           PGPMatchCriterion match,
           PGPFilterRef *outFilter );
pgpContextИспользуемый PGP-контекст
userIDStringСтрока-идентификатор хозяина ключа
matchКритерий выборки
outFilterПоле для получения созданного фильтра

В отличии от операций шифрования, которые выполняются для набора ключей, наложение цифровой подписи должно производится только с одним определенным ключом. Для выбора этого ключа из набора на него нужно наложить фильтр по необходимому критерию. PGP SDK предоставляет около трех десятков функций для задания фильтра по дате создания ключа, номеру ключа, алгоритму шифрования, email хозяина ключа и т.д. Функция PGPNewUserIDStringFilter создает фильтр по строке – идентификатору хозяина ключа. В качестве критерия выборки PGPMatchCriterion могут использоваться значения из следующего перечисления (pgpKeys.h):

enum PGPMatchCriterion_
{        
        kPGPMatchDefault = 1,        /* тоже что и kPGPMatchEqual */
        kPGPMatchEqual = 1,          /* строгое равенство искомой и заданной для сравнения величин */
        kPGPMatchGreaterOrEqual = 2, /* искомая величина >= заданной для сравнения */
        kPGPMatchLessOrEqual = 3,    /* искомая величина <= заданной для сравнения */
        kPGPMatchSubString = 4,      /* искомая строка содержится в заданной для сравнения */

        PGP_ENUM_FORCE( PGPMatchCriterion_ )
};
PGPENUM_TYPEDEF( PGPMatchCriterion_, PGPMatchCriterion );

По окончании использования (до вызова PGPFreeContext) созданный фильтр должен быть освобожден вызовом функции

PGPFreeFilter

PGPError PGPFreeFilter( PGPFilterRef filter );
filterОсвобождаемый фильтр

PGPFilterKeySet

PGPError PGPFilterKeySet(
           PGPKeySetRef origSet,
           PGPFilterRef filter,
           PGPKeySetRef *resultSet );
origSetИсходный набор ключей
filterФильтр, созданый вызовом одной из функций PGPNewxxxxxxxFilter
resultSetРезультирующий набор ключей – после применения фильтра

Функция предназначена для получения набора ключей, отобранных по условию заданному в накладываемом фильтре.

PGPOrderKeySet

PGPError PGPOrderKeySet(
           PGPKeySetRef keySet,
           PGPKeyOrdering order,
           PGPKeyListRef *keyList );
keySetНабор ключей для сортировки
orderКритерий сортировки
keyListРезультат операции – отсортированный список ключей

Функция упорядочивает заданный набор ключей согласно заданному критерию сортировки. Критерий сортировки задается указанием одного из следующих параметров (pgpKeys.h):

/* Key ordering */
enum PGPKeyOrdering_
{       
        kPGPInvalidOrdering                = 0,
        kPGPAnyOrdering                    = 1,
        kPGPUserIDOrdering                 = 2,
        kPGPReverseUserIDOrdering          = 3,
        kPGPKeyIDOrdering                  = 4,
        kPGPReverseKeyIDOrdering           = 5,
        kPGPValidityOrdering               = 6,
        kPGPReverseValidityOrdering        = 7,
        kPGPTrustOrdering                  = 8,
        kPGPReverseTrustOrdering           = 9,
        kPGPEncryptKeySizeOrdering         = 10,
        kPGPReverseEncryptKeySizeOrdering  = 11,
        kPGPSigKeySizeOrdering             = 12,
        kPGPReverseSigKeySizeOrdering      = 13,
        kPGPCreationOrdering               = 14,
        kPGPReverseCreationOrdering        = 15,
        kPGPExpirationOrdering             = 16,
        kPGPReverseExpirationOrdering      = 17,
        
        PGP_ENUM_FORCE( PGPKeyOrdering_ )
};
PGPENUM_TYPEDEF( PGPKeyOrdering_, PGPKeyOrdering );

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

По окончании использования (до вызова PGPFreeContext) созданный список ключей должен быть освобожден вызовом функции

PGPFreeKeyList

PGPError PGPFreeKeyList( PGPKeyListRef keySet );
keySetОсвобождаемый список ключей

PGPNewKeyIter

PGPError PGPNewKeyIter(
           PGPKeyListRef keySet,
           PGPKeyIterRef *keyIter );
keySetСписок ключей, для которого создается итератор
keyIterСозданный итератор для доступа к списку ключей

Функция создает итератор для получения очередного ключа из списка.

По окончании использования (до вызова PGPFreeContext) созданный итератор должен быть освобожден вызовом функции

PGPFreeKeyIter

PGPError PGPFreeKeyIter( PGPKeyIterRef iter );
iterОсвобождаемый итератор

PGPKeyIterNext

PGPError PGPKeyIterNext(
           PGPKeyIterRef iter, 
           PGPKeyRef *key );
iterИтератор для доступа к списку ключей
keyОчередной ключ в списке

Функция предназначена для получения очередного ключа из списка ключей.

PGPOHashAlgorithm

PGPOptionListRef PGPOHashAlgorithm(
                   PGPContextRef pgpContext,
                   PGPHashAlgorithm algID );
pgpContextИспользуемый PGP-контекст
algIDИдентификатор алгоритма хеширования

Данная опция служит для выбора алгоритма хеширования, используемого при цифровой подписи.

В качестве идентификатора алгоритма используются значения из следующего перечисления (pgpPubTypes.h):

enum PGPHashAlgorithm_
{
        /* do NOT change these values */
        kPGPHashAlgorithm_Invalid       = 0,
        kPGPHashAlgorithm_MD5           = 1,
        kPGPHashAlgorithm_SHA           = 2,
        kPGPHashAlgorithm_RIPEMD160     = 3,

        kPGPHashAlgorithm_First         = kPGPHashAlgorithm_MD5,
        kPGPHashAlgorithm_Last          = kPGPHashAlgorithm_RIPEMD160,

        PGP_ENUM_FORCE( PGPHashAlgorithm_ )
};
PGPENUM_TYPEDEF( PGPHashAlgorithm_, PGPHashAlgorithm );

Данная опция не действует при подписи DSS ключом (DSS - Digital Signature Standard от NIST (National Institute for Standards and Technology USA)), в этом случае всегда используется SHA-1.

Поддержка операции наложения цифровой подписи в классе CSimplePGP

Для поддержки операций наложения цифровой подписи в класс CSimplePGP добавлены следующие члены:

   public:
        // установка  - подпись без шифрования исходного текста, в том же файле 
        BOOL SetClearSigning ( BOOL bClearsign );
        // установка - подпись в отдельном файле
        BOOL SetDetachedSig ( BOOL bDetachedSig );
        // установка - строка - идентификатор хозяина ключа
        void SetSignerIDstring ( string signerID );
        // алгоритм хеширования
        BOOL SetHashAlgorithm( PGPHashAlgorithm hashID );
        // ЦИФРОВАЯ ПОДПИСЬ
        // подписываем файл, секретный ключ тоже в файле
        BOOL SignFile2File( LPCTSTR inFileName,      // имя входного файла для подписания
                            LPCTSTR outFileName,     // имя выходного файла
                            LPCTSTR keyFileName );   // имя файла с секретным ключом

        // подписываем файл, секретный ключ в ресурсах
        BOOL SignFile2File( LPCTSTR inFileName,      // имя входного файла
                            LPCTSTR outFileName,     // имя выходного файла
                            LPCTSTR resourceName,    // имя ресурса c секретным ключом 
                            LPCTSTR resourceType );  // тип ресурса

        // данные - из памяти, подпись - в файл, секретный ключ тоже в файле
        BOOL SignBuff2File( const VOID* inData,      // указатель на буфер с данными
                            DWORD dwDataSize,        // размер буффера
                            LPCTSTR outFileName,     // имя выходного файла
                            LPCTSTR keyFileName );   // имя файла с секретным ключом

        // данные - из памяти, подпись - в файл, секретный ключ в ресурсах
        BOOL SignBuff2File( const VOID* inData,      // указатель на буфер с данными
                            DWORD dwDataSize,        // размер буфера
                            LPCTSTR outFileName,     // имя выходного файла
                            LPCTSTR resourceName,    // имя ресурса c секретным ключом 
                            LPCTSTR resourceType );  // тип ресурса

        // данные - из файла, подпись - в буфер, секретный ключ в файле.
        BOOL SignFile2Buff( LPCTSTR inFileName,      // имя входного файла
                            LPBYTE& OutData,         // указатель на буфер для данных
                            DWORD& BuffSize,         // размер буфера 
                            LPCTSTR keyFileName );   // имя файла с секретным ключом

        // данные - из файла, подпись - в буфер, секретный ключ в ресурсах
        BOOL SignFile2Buff( LPCTSTR inFileName,      // имя входного файла
                            LPBYTE& OutData,         // указатель на буфер для данных
                            DWORD& BuffSize,         // размер буфера 
                            LPCTSTR resourceName,    // имя ресурса c секретным ключом 
                            LPCTSTR resourceType );  // тип ресурса

        // данные - из памяти, подпись - в память, секретный ключ в файле
        BOOL SignBuff2Buff( const VOID* inData,      // указатель на буфер с данными
                            DWORD dwDataSize,        // размер буффера
                            LPBYTE& OutData,         // указатель на буфер для данных
                            DWORD& BuffSize,         // размер буфера 
                            LPCTSTR keyFileName );   // имя файла с секретным ключом

        // данные - из памяти, подпись - в память, секретный ключ в ресурсах
        BOOL SignBuff2Buff( const VOID* inData,      // указатель на буфер с данными
                            DWORD dwDataSize,        // размер буфера
                            LPBYTE& OutData,         // указатель на буфер для данных
                            DWORD& BuffSize,         // размер буфера 
                            LPCTSTR resourceName,    // имя ресурса c секретным ключом
                            LPCTSTR resourceType );  // тип ресурса

В качестве примера реализации операции цифровой подписи рассмотрим создание в буфере подписи для файла с данными:

// данные - из файла, подпись - в буфер, секретный ключ в ресурсах
// В функции выделяется память под буфер
// OutData, не забудьте освободить ее после
// использования буфера, размер выделенной
// памяти после выполнения функции
// находится в BuffSize
BOOL CSimplePGP::SignFile2Buff( LPCTSTR inFileName,      // имя входного файла
                                LPBYTE& OutData,         // указатель на буфер для данных
                                DWORD& BuffSize,         // размер буфера 
                                LPCTSTR resourceName,    // имя ресурса c секретным ключом 
                                LPCTSTR resourceType )   // тип ресурса
{
    if ( !m_bIsInit )
        Init();

    BOOL ret = TRUE;

    // код ошибки
    PGPError err = kPGPError_NoErr;

    // входной файл
    PGPFileSpecRef inFileRef = kInvalidPGPFileSpecRef;

    // набор ключей из ресурсов
    PGPKeySetRef secKeysSet = kInvalidPGPKeySetRef;

    // импортируем ключи из ресурсов
    if ( !ImportKeySetFromResorce( resourceName, resourceType, secKeysSet ) )
        return FALSE;

    // извлекаем из набора ключ для подписания
    PGPKeyRef secKeyRef = GetFirstKeyFromSet( secKeysSet );

    if ( secKeyRef == kInvalidPGPKeyRef )
    {
        ret = FALSE;
        goto Clear;
    }

    // готовим входной файл
    err = PGPNewFileSpecFromFullPath( m_context, inFileName, &inFileRef );

    if ( IsPGPError( err ) )
    {
        m_sWhere = StrPrintf( "PGPNewFileSpecFromFullPath - '%s'  ", inFileName );
        goto Exit;
    }

    // начальный размер буффера
    // заведомо маленький, после первого вызова PGPEncode в
    // параметре PGPOOutputBuffer будет передано действительно требуемое
    // значение размера буфера
    // ( 0 в качестве начального значения не проходит, поэтому 1 )
    BuffSize = 1;

    // собственно шифрование
    do
    {
        delete[] OutData;
        // Выделенную здесь память надо освобождать по окончании использования
        // выходного буфера
        OutData = new BYTE[ BuffSize ];

        // собственно подпись
        err = PGPEncode( m_context,
                        // входной файл
                        PGPOInputFile( m_context, inFileRef ),
                        // выходной буфер
                        PGPOOutputBuffer( m_context,
                                          ( void* ) OutData,
                                          ( PGPSize ) BuffSize,
                                          ( PGPSize * ) & BuffSize ),
                        // подписать 
                        PGPOSignWithKey( m_context, secKeyRef, m_optsPassphrase, PGPOLastOption( m_context ) ),
                        // и предварительно сформированный при
                        // инициализации список опций
                        m_optsSigning,
                        // больше опций не будет
                        PGPOLastOption( m_context ) );
    }
    while ( err == kPGPError_OutputBufferTooSmall );

    if ( IsPGPError( err ) )
    {
        m_sWhere = "PGPEncode()";
    }

Exit:

    if ( IsPGPError( err ) )
    {
        ret = FALSE;
        // получаем описание ошибки
        PGPGetErrorString( err, sizeof( m_sWhat ), m_sWhat );
    }

Clear:
    // очистка
    if ( PGPKeySetRefIsValid( secKeysSet ) )
        PGPFreeKeySet( secKeysSet );

    if ( PGPFileSpecRefIsValid( inFileRef ) )
        PGPFreeFileSpec( inFileRef );

    return ret;
}

Как видно из исходного текста порядок операций практически полностью совпадает с операцией шифрования файла, рассмотренной в первой части статьи, за исключением опций, передаваемых в PGPEncode и функции GetFirstKeyFromSet, необходимой для получения одного единственного ключа из набора:

PGPKeyRef CSimplePGP::GetFirstKeyFromSet( PGPKeySetRef &keyset )
{
    // код ошибки
    PGPError err = kPGPError_NoErr;
    // ключ
    PGPKeyRef keyref = kInvalidPGPKeyRef;
    // список ключей
    PGPKeyListRef foundKeysList = kInvalidPGPKeyListRef;
    // итератор по списку ключей
    PGPKeyIterRef keyListIterator = kInvalidPGPKeyIterRef;
    // фильтр
    PGPFilterRef filter = kInvalidPGPFilterRef;
    // отфильтрованный набор
    PGPKeySetRef foundUserKeys = kInvalidPGPKeySetRef;

    // если задана строка - идентификатор хозяина ключа, задаем
    // соответствующий фильтр, если идентификатор не задан,
    // возьмем первый ключ из набора
    if ( !m_sSignerID.empty() )
    {
        // создаем фильтр по идентификатору хозяина ключа
        err = PGPNewUserIDStringFilter( m_context, m_sSignerID.c_str(), kPGPMatchSubString, &filter );

        if ( IsPGPError( err ) )
        {
            m_sWhere = "PGPNewUserIDStringFilter()  ";
            goto Exit;
        }

        // накладываем фильтр на набор ключей
       	err = PGPFilterKeySet( keyset, filter, &foundUserKeys );

        if ( IsPGPError( err ) )
        {
            m_sWhere = "PGPFilterKeySet()  ";
            goto Exit;
        }

        // получаем неупорядоченный список ключей из отфильтрованного набора
        err = PGPOrderKeySet( foundUserKeys, kPGPAnyOrdering, &foundKeysList );
    }
    else
    {
        // получаем неупорядоченный список ключей из полного, неотфильтрованного набора
        err = PGPOrderKeySet( keyset, kPGPAnyOrdering, &foundKeysList );
    }

    if ( IsPGPError( err ) )
    {
        m_sWhere = "PGPOrderKeySet()  ";
        goto Exit;
    }

    // создаем итератор
    err = PGPNewKeyIter( foundKeysList, &keyListIterator );

    if ( IsPGPError( err ) )
    {
        m_sWhere = "PGPNewKeyIter()  ";
        goto Exit;
    }

    // берем первый попавшийся ключ из списка
    err = PGPKeyIterNext( keyListIterator, &keyref );

    if ( IsPGPError( err ) )
    {
        m_sWhere = "PGPKeyIterNext()  ";
    }

Exit:

    if ( IsPGPError( err ) )
    {
        // получаем описание ошибки
        PGPGetErrorString( err, sizeof( m_sWhat ), m_sWhat );
        keyref = kInvalidPGPKeyRef;
    }

    if( PGPFilterRefIsValid( filter ) )
        PGPFreeFilter( filter );

    if( PGPKeyIterRefIsValid( keyListIterator ) )
        PGPFreeKeyIter( keyListIterator );

    if( PGPKeyListRefIsValid( foundKeysList ) )
        PGPFreeKeyList( foundKeysList );

    if( PGPKeySetRefIsValid( foundUserKeys ) )
        PGPFreeKeySet( foundUserKeys );

    return keyref;
}

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

#include "simplepgp.h"

CSimplePGP pgp;

// инициализация PGP
if ( !pgp.Init() )
    ::MessageBox( m_hWnd, pgp.GetErrDesc().c_str(), pgp.GetErrPlace().c_ctr(), MB_OK | MB_ICONSTOP );

// настройка операции цифровой подписи
if ( !pgp.SetASCIIoutput( TRUE ) ||
     !pgp.SetASCIIinput( TRUE ) ||
     !pgp.SetDetachedSig( FALSE ) ||
     !pgp.SetClearSigning( TRUE ) ||
     !pgp.SetCipherAlgorithm( kPGPCipherAlgorithm_3DES ) ||
     !pgp.SetHashAlgorithm( kPGPHashAlgorithm_MD5 ) ||
     !pgp.SetPassphrase( "test" ) )
        ::MessageBox( m_hWnd, m_pgp.GetErrDesc().c_str(), m_pgp.GetErrPlace().c_str(), MB_OK | MB_ICONSTOP );

// задаем каким ключом подписывать
pgp.SetSignerIDstring( "test@pgp.com" );

// собственно подпись
if ( !pgp.SignFile2File( "infile.txt",      // файл, который нужно подписать
                         "signedfile.txt",  // имя файла для подписанного текста
                         "seckey.asc" ) )   // файл с секретным ключом
   ::MessageBox( m_hWnd, m_pgp.GetErrDesc().c_str(), m_pgp.GetErrPlace().c_str(), MB_OK | MB_ICONSTOP );

Демонстрационная программа PGPTest3

ПРИМЕЧАНИЕ

Проект демонстрационной программы создавался и компилировался в VS 2003 (7.1.3088). Если вы используете более раннюю версию VS, можете попробовать воспользоваться A Utility to Convert VS.NET 2003 Project Files by dacris, либо VC++7 to VC++6 project converter by Stephane Rodriguez, либо другой им подобной.

Программа позволяет протестировать возможности PGP SDK по наложению цифровой подписи, реализованные в классе CSimplePGP.


Задавая положение переключателей и имена файлов можно протестировать разные варианты получения входных данных и ключевой информации, а также варианты вывода подписанной информации. В подкаталоге test и в ресурсах программы находятся тестовый ключ из комплекта PGP SDK (2048/1024 DH/DSS, идентификатор test@pgp.com) и тестовый ключ RSA ( идентификатор rsakey). Пароль для обоих ключей одинаковый – test.

ПРИМЕЧАНИЕ

Как уже было сказано выше, настройка алгоритма хеширования действует только для ключа RSA.

Если в качестве места для размещения выходных данных выбрать буфер в памяти, то после нажатия кнопки “Подписать” на экране должно появится окно для просмотра содержимого буфера:


Верифицировать наложенную цифровую подпись можно с помощью программы PGP, предварительно импортировав в менеджер ключей тестовый ключ из комплекта PGP SDK и тестовый ключ RSA (test\rsakey.asc).


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 3    Оценка 15        Оценить