08.08.2006 12:28:33Импорт public key Ответов: 7
Есет
Привет!
Спасибо большое за форум!

Задача:

В таблице LDSSCertificateStore базы данных LANDOCS есть BLOB Certificate, мне нужно извлечь из
этого BLOB-а public key

для этого я сохраняю вручную этот BLOB в файл с расширением *.cer
(используя PLSQL Developer)

затем применяю следующий скрипт в C++ :

>> #include "stdafx.h"
>> #include <windows.h>
>> #include <wincrypt.h>
>> #include <stdio.h>
>> #include "cptumar.h"
>>
>> #include <stdlib.h> //atoi()
>>
>> #include <wtypes.h>
>>
>> #define BUFSIZE 1024
>> void HandleError(char *s);
>> void ErrorExit(LPTSTR lpszFunction);
>>
>> int _tmain(int argc, _TCHAR* argv[])
>> {
>> FILE *hFile;
>> FILE *PubKeyFile;
>> BYTE rgbFile[BUFSIZE];
>> DWORD cbRead =0;
>> BOOL bResult =FALSE;
>> HCRYPTPROV hProv = 0;
>> HCRYPTKEY hPubKey;
>> BYTE pbData[1000]; // 1000 will hold the longest
>> // key container name.
>> DWORD cbData;
>>
>>
>> hFile =fopen("1.cer", "r+b");
>> if (hFile)
>> {
>> printf("The file was opened");
>> }
>> else
>> {
>> printf("Error opening file");
>> }
>> //return 0;
>>
>> do
>> {
>> cbRead =(DWORD)fread(rgbFile,1,BUFSIZE,hFile);
>> if (!cbRead)
>> {
>>
>> bResult =TRUE;
>> break;
>> }
>>
>> }
>> while (!feof(hFile));
>> printf( "Number of items read = %d\n", cbRead );
>>
>> //------------------------------------------------------------------
>> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
>>
>> PCCERT_CONTEXT pCertContext = NULL;
>>
>> // Create a new certificate from the encoded part of
>> // an available certificate. pDesiredCert is a previously
>> // assigned PCCERT_CONTEXT variable.
>>
>> if(pCertContext = CertCreateCertificateContext(
>> MY_ENCODING_TYPE, // The encoding type
>> rgbFile, // The encoded data from
>> // the certificate retrieved
>> cbRead)) // The length of the encoded data
>> {
>> printf("A new certificate as been created.\n");
>>
>>
>>
>> if (!CryptAcquireContext(
>> &hProv,
>> NULL,
>> NULL,
>> 25,
>> 0))
>> {
>> // dwStatus = GetLastError();
>> printf("CryptAcquireContext failed:");
>> //fclose(hFile);
>> //return dwStatus;
>> }
>> else
>> {
>> printf("CryptAcquireContext success!!!");
>> }
>>
>> // Read the name of the default CSP.
>>
>> cbData = 1000;
>> if(CryptGetProvParam(
>> hProv,
>> PP_NAME,
>> pbData,
>> &cbData,
>> 0))
>> {
>> printf("CryptGetProvParam succeeded.\n");
>> printf("Provider name: %s\n", pbData);
>> }
>> else
>> {
>> printf("Error reading CSP name. \n");
>> exit(1);
>> }
>>
>> // Read the name of the key container.
>>
>> cbData = 1000;
>> if(CryptGetProvParam(
>> hProv,
>> PP_CONTAINER,
>> pbData,
>> &cbData,
>> 0))
>> {
>> printf("CryptGetProvParam succeeded. \n");
>> printf("Key Container name: %s\n", pbData);
>> }
>> else
>> {
>> HandleError("Error reading key container name. \n");
>> }
>>
>>
>> // через функцию CryptAcquireCertificatePrivateKey получаем доступ к CSP
>> // одна из самых интересных и полезных функций в CryptoAPI
>> /*
>> HCRYPTPROV hProv;
>> DWORD dwKeySpec;
>> BOOL fCallerFreeProv;
>>
>> if(CryptAcquireCertificatePrivateKey(
>> pCertContext,
>> CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
>> NULL,
>> &hProv,
>> &dwKeySpec,
>> &fCallerFreeProv
>> ))
>> {
>> printf("CryptAcquireCertificatePrivateKey выполнилась успешно!\n");
>> }
>> else
>> {
>> printf(" Error CryptAcquireCertificatePrivateKey.\n");
>> }
>> */
>> CERT_INFO *certInfo = pCertContext->pCertInfo;
>> CERT_PUBLIC_KEY_INFO keyInfo = certInfo->SubjectPublicKeyInfo;
//(pCertContext->>>pCertInfo->SubjectPublicKeyInfo)
>> if(CryptImportPublicKeyInfo(
>> hProv,
>> MY_ENCODING_TYPE,
>> &keyInfo,
>> &hPubKey
>> ))
>> {
>> printf("Import public key success.\n");
>> PubKeyFile = fopen( "PubKeyFile.txt", "w+b" );
>>
>> if(!PubKeyFile)
>> printf( "Problem opening the file\n" );
>>
>> fwrite (&hPubKey, 1, 500, PubKeyFile);
>> }
>> else
>> {
>> HandleError("Error Import public key.");
>> }
>>
>>
>>
>>
>> // Use the certificate context as needed.
>> // ...
>>
>> // When finished, free the certificate context.
>> CertFreeCertificateContext(pCertContext);
>>
>> }
>> else
>> {
>> printf("A new certificate could not be created.\n");
>> // exit(1);
>> }
>>
>> }
>> void HandleError(char *s)
>> {
>> printf("Error. \n");
>> printf("%s\n",s);
>> printf("Error number %x\n.", GetLastError());
>> printf("Program terminating. \n");
>> ErrorExit("8009310b");
>> exit(1);
>> }
>> void ErrorExit(LPTSTR lpszFunction)
>> {
>> TCHAR szBuf[80];
>> LPVOID lpMsgBuf;
>> DWORD dw = GetLastError();
>>
>> FormatMessage(
>> FORMAT_MESSAGE_ALLOCATE_BUFFER |
>> FORMAT_MESSAGE_FROM_SYSTEM,
>> NULL,
>> dw,
>> MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
>> (LPTSTR) &lpMsgBuf,
>> 0, NULL );
>>
>> wsprintf(szBuf,
>> "%s failed with error %d: %s",
>> lpszFunction, dw, lpMsgBuf);
>>
>> MessageBox(NULL, szBuf, "Error", MB_OK);
>>
>> LocalFree(lpMsgBuf);
>> ExitProcess(dw);
>> }

И когда вызывается функция CryptImportPublicKeyInfo выдает
следующее сообщение об ошибке:

8009310b failed with error -2146881269: ASN1 bad tag value met

Что я делаю не так?

--
 
Ответы:
08.08.2006 12:49:53Kirill Sobolev
Если Вы читаете сертификат из файла .cer, то функция CryptAcquireCertificatePrivateKey работать не будет - у такого сертификата нет ссылки на секретный ключ.
08.08.2006 14:54:49Есет
Sorry,
там у меня закоментировано, т.е. я не использую функцию
CryptAcquireCertificatePrivateKey.
hProv - я получаю через CryptAcquireContext.
08.08.2006 15:08:46Kirill Sobolev
А точно ОК создан дефолтным провайдером 25 типа?
10.08.2006 9:08:05Есет
Да.

Спасибо.
10.08.2006 10:11:03Kirill Sobolev
Мб этот провайдер вообще импорт открытых ключей не поддерживает?
10.08.2006 15:18:37Есет
Спасибо Кирилл!

Провайдер поддерживает импорт открытых ключей.
Я убедился в этом когда выполнял импорт из сертификата который они сами выпустили. Импорт был успешным.
А когда я делаю импорт из сертификата который был помещен в базу данных, ну предварительно я этот blob извлекаю оттуда и сохраняю в виде файла с расширением *.cer то импорт failed.
Возможно эти черти поместили этот сертификат в БД не в стандартной кодировке ASN1? Намеренно.
10.08.2006 16:45:09Kirill Sobolev
Если был неправильный ASN, то CertCreateCertificateContext не проходил бы. А можно им проверить подпись какую-нибудь?