Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Задача по CryptoAPI

11K
17 октября 2008 года
zuze
84 / / 07.03.2008
Условие задачи такое

Подписывание сообщение, содержащее ФИО (открытие ключевого контекста, запрос пользовательского ключа подписи, экспорт открытого ключа подписи, создание объекта хеширования, расчёт хеш-функции и подпись хеш значения)

Проверка подписи (импорт открытого ключа в криптопровайдер, создание нового объекта хеша, расчёт хеш-функции и проверка подлинности подписи).

Алгоритм хеширования MD5

А хотел узнать этот код программы для условие этой задачи правелен или надо что-то добавить или убрать?

На то что в коде программы много goto на это можно внимание не обращать хотя я и понимаю что это плохо.

Код вот
11K
18 октября 2008 года
zuze
84 / / 07.03.2008
Надо было добавить вывод на экран открытого и секретного ключа.

Вот код

Код:
#include "stdio.h"
#include "windows.h"
#include "wincrypt.h"
// Объявление функции CryptAcquireContextEx
BOOL CryptAcquireContextEx(HCRYPTPROV *phProv,        //out
                           LPTSTR      pszContainer,  //in
                           LPTSTR      pszpRovider,   //in
                           DWORD       dwProvType,    //in
                           DWORD       dwFlags,       //in
                           DWORD       dwKeySpec,     //in
                           DWORD       KeyFlags       //in
                          );
void main(int argc, char *argv[])
{
    // Объявление и инициализация переменных.
    HCRYPTPROV hProv = 0; // Дескриптор провайдер
    HCRYPTKEY  hKey = 0;  // Дескриптор ключа
    HCRYPTKEY hPubKey = 0;
    HCRYPTHASH hHash = 0;
    // Буфер данных для подписи
    LPBYTE pbBuffer = (BYTE *)"Ivanov Ivan Ivanovich";
    LPTSTR szDescription = (LPTSTR)"Test message";
    LPBYTE pbKeyBlob = NULL, pbSignature = NULL, PrivateBlob = NULL;
    DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
    DWORD dwSigLen = 0, dwBlobLen = 0, dwBlobLen1 = 0;
    // ********************************************************************
    //   Первая фраза.     Подпись сообщения.
    // ********************************************************************
    printf("The message to sign: %s\n", pbBuffer);
    printf("The description of message: %s\n", szDescription);

   
   
    // Получение дискриптора криптопровайдера.
    if (!CryptAcquireContextEx(&hProv, NULL, NULL, PROV_RSA_FULL, 0, AT_SIGNATURE, 0))
       goto ReleaseResource;
    printf("CSP context acquired\n");
   
    // Получение дискриптора ключа подписи.
    // AT_SIGNATURE - алгоритма открытых ключей
    // являются основой для "Цифровых Подписей" (NIST Digital Signature Algorithm - DSA)
    if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
    {
       printf("Error: CryptGetUserKey=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("The signature key has been acquired\n");

    // Для получения необходимого размера памяти параметр pbData равен NULL.
    // Размер ключевого блока возвращается в параметре dwBlodLen
    // PUBLICKEYBLOB - используется для сохранения открытых ключей.
    // Поскольку открытые ключи не являются секретными, они сохраняются в незашифрованном виде;
    if (!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen))
    {
       printf("Error: CryptExportKey=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("Size of the blob for the public key determined\n");

    // Выделение памяти для pbKeyBlob.
    pbKeyBlob = (LPBYTE)malloc (dwBlobLen);

    if (!pbKeyBlob)
    {
       printf("Error: Out of memory\n");
       goto ReleaseResource;
    }
    printf("Memory has been allocated for the blob\n");

    // Экспорт открытого ключа пары подписи.
    if (!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen))
    {
       printf("Error: CryptExportKey=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("Context have been written to the blob\n");

    //выведем ключевой блоб открытого ключа
    printf("\n\nPublicKeyBlob = \"");
    for (DWORD i = 0; i < dwBlobLen; i++)
        printf("%02x",pbKeyBlob);
    printf("\"\n\n");

    //получим ключевой блоб ключевой пары
    // Для получения необходимого размера памяти параметр pbData равен NULL.
    // Размер ключевого блоба возвращается в параметре dwBlodLen1
    if (!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen1))
    {
       printf("Error: CryptExportKey=0x%X.\n", GetLastError());
       goto ReleaseResource;
    }
    printf("Size of the blob for the private key pair determined\n");

    // Выделение памяти для PrivateBlob
    PrivateBlob = (LPBYTE)malloc (dwBlobLen1);

    if (!PrivateBlob)
    {
       printf("Error: Out of memory\n");
       goto ReleaseResource;
    }
    printf("Memory has been allocated for the blob\n");

    // Экспорт секретного ключа пары подписи.
    if (!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, PrivateBlob, &dwBlobLen1))
    {
       printf("Error: CryptExportKey=0x%X.\n", GetLastError());
       goto ReleaseResource;
    }
    printf("Context have been written to the blob\n");

    //выведем ключевой блоб пары
    printf("\n\nPrivateKeyBlob = \"");
    for (DWORD i = 0; i < dwBlobLen1; i++)
        printf("%02x", PrivateBlob);
    printf("\"\n\n");


    // Создание объекта хеширования.
    // CALG_MD5 - идентификатор алгоритма MD5
    if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
    {
       printf("Error: CryptCreateHash=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("Hash object created. Using MD5\n");

    // Хеширование буфера данных
    if (!CryptHashData(hHash, pbBuffer, dwBufferLen, 0))
    {
       printf("Error: CryptHashData=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("The data buffer has been hashed\n");

    // Определение необходимого размера памяти для буфера цифровой подписи.
    if (!CryptSignHash(hHash, AT_SIGNATURE, szDescription, 0, NULL, &dwSigLen))
    {
       printf("Error: CryptSignHash=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("Signature length %d found.\n", dwSigLen);

    // Выделение памяти под буфер цифровой подписи.
    pbSignature = (LPBYTE)malloc(dwSigLen);
    if (!pbSignature)
    {
       printf("Error: Out of memory\n");
       goto ReleaseResource;
    }
    printf("Memory allocated for the signature\n");

    // Вычисление цифровой подписи
    if (!CryptSignHash(hHash, AT_SIGNATURE, szDescription, 0, pbSignature, &dwSigLen))
    {
       printf("Error: CryptSignHash=0x%X.\n", GetLastError());
       goto ReleaseResource;
    }
    printf("pbSignature is the hash signature\n");


    // Уничтожение объекта хеширования
    if (hHash)
       CryptDestroyHash(hHash);
    hHash = 0;
    printf("The hash object has been destroyed\n");
    printf("The signing phase of this program is completed\n\n");


    //***********************************************************
    // Вторая фаза.  Проверка цифровой подписи сообщения
    //***********************************************************

    // Импортируем открытый ключ в криптопровайдер
    if (!CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey))
    {
       printf("Error: CryptImportKey=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("The key has been inported\n");

    // Создание нового объекта хеширования.
    if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
    {
       printf("Error: CryptCreateHash=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("The hash object has been recreated. Using MD5\n");

    // Хеширование буфера данных
    if (!CryptHashData(hHash, pbBuffer, dwBufferLen, 0))
    {
       printf("Error: CryptHashData=0x%X.\n",GetLastError());
       goto ReleaseResource;
    }
    printf("The new has been created.\n");


    // Проверка цифровой подписи
    if (!CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, szDescription, 0))
    {
       if (GetLastError() == NTE_BAD_SIGNATURE)
          printf("SIGNATURE FAILED TO VALIDATED");
       else
          printf("Error: CryptVerifySignature=0x%X.\n",GetLastError());
    }
    else
       printf("SIGNATURE VALIDATED OK!\n");


    ReleaseResource:


    // Освобождаем память блоба открытого ключа
    if (pbKeyBlob)
       free(pbKeyBlob);
    // Освобождаем память подписи
    if (pbSignature)
       free(pbSignature);
    // Уничтожаем объект хеширования
    if (hHash)
       CryptDestroyHash(hHash);
    // Освобождаем дескриптор криптопровайдера
    if (hProv)
       CryptReleaseContext(hProv, 0);

}



BOOL CryptAcquireContextEx(HCRYPTPROV *phProv,  //out
                           LPTSTR pszContainer, //in
                           LPTSTR pszProvider,  //in
                           DWORD  dwProvType,   //in
                           DWORD  dwFlags,      //in
                           DWORD  dwKeySpec,    //in
                           DWORD  KeyFlags      //in
                          )
{
    DWORD dwError;
    HCRYPTKEY hKey;
    // Пытаемся открыть контейнер криптопровайдера
    if(!CryptAcquireContext(phProv, pszContainer, pszProvider, dwProvType, dwFlags))
    {
        dwError = GetLastError();
        if (dwError != NTE_BAD_KEYSET)
        {
            printf("Error: CryptAcquireContext=0x%X.\n", dwError);
            return FALSE;
        }
        else
        {
            // Если контекст не существует, создаем новый
            if (!CryptAcquireContext(phProv, pszContainer, pszProvider, dwProvType, dwFlags|CRYPT_NEWKEYSET))
            {
                printf("Error: CryptAcquireContext=0x%X.\n", GetLastError());
                return FALSE;
            }
        }
    }


 // Если ключевая пара в контейнере отсутствует, создаем новую
 if (!CryptGetUserKey(*phProv, dwKeySpec, &hKey))
 {
    if (!CryptGenKey(*phProv, dwKeySpec, CRYPT_EXPORTABLE, &hKey))
    {
        CryptReleaseContext(*phProv, 0);
        printf("Error: CryptGetUserKey=0x%X.\n", GetLastError());
        return FALSE;
    }
 }
 // Освобождаем дескриптор ключа
 CryptDestroyKey(hKey);

 return TRUE;
}
43K
20 октября 2008 года
Kirjan
1 / / 20.10.2008
Goto, как ты уже понял, нужен для освобождения ресурсов, т. е. очистки памяти. Это не страшно.
Меня смущате только 1 кусок, это объявление без присваивания LPTSTR szDescription.
Билдеру до фени, а вот Вижуал ругается...
А вообще, тебе сюда.
До встречи ;)
240
20 октября 2008 года
aks
2.5K / / 14.07.2006
Kirjan, на самом деле просто не правильно приводить всегда не юникодную стргоку к LPTSTR, который может развернуться как в char * так и в wchar_t *.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог