07.11.2005 11:41:12Создание сертификата makecert.c Ответов: 6
Mick
Пробую воспроизвести пример создания сертификакта из примера поставляемого с криптопровайдером.
На этапе CryptExportPublicKeyInfo получаю ошибку NTE_NO_KEY, хотя все предыдущие вызовы прошли успешно.
dwSize := 0;
dwKeyType := AT_SIGNATURE;
bResult := CryptExportPublicKeyInfo(hProv,dwKeyType,X509_ASN_ENCODING,nil,@dwSize);

Подскажите, в чем может быть ошибка?
 
Ответы:
08.11.2005 11:03:23Kirill Sobolev
Мб у Вас ключ не AT_SIGNATURE а AT_KEYEXCHANGE?
08.11.2005 11:07:11Mick
В том то и дело, что внутри контейнера оба ключа. Я их всегда генерирую только парами.
Скажите, а у вас нет примеров аналогичных csptest, но на Pascal’e?
08.11.2005 11:11:59Kirill Sobolev
А можно глянуть код генерации?
08.11.2005 11:18:44Mick
Вот код инициализации контейнера. Сорри за инородный язык.

procedure GenerateClick;
var AProv : HCRYPTPROV;
AlgID : ALG_ID; AFlags,ASize : DWORD; hKey : HCRYPTKEY;
AData : PByte; ErrCode : Integer; ErrMsg,ContainerName,ProvName : string;
ALen : Word;
ProvType,Err : integer;
begin
ContainerName := Trim(GetContainterName);
ProvType := GetProviderType;
ProvName := Trim(GetCryptoProProviderName(ProvType));
if CryptAcquireContext(@AProv,PChar(ContainerName),PChar(ProvName),ProvType,CRYPT_NEWKEYSET) then
begin
ASize:=0;
if CryptGetProvParam(AProv,PP_NAME,nil,@ASize,0) then
begin
GetMem(AData,ASize);
if CryptGetProvParam(AProv,PP_NAME,AData,@ASize,0) then
begin
ProvNameEditRO.Text := StrPas(PChar(AData));
AlgID := AT_KEYEXCHANGE;
AFlags := 1024;
AFlags := (AFlags shl 16) OR CRYPT_EXPORTABLE ;
if CryptGenKey(AProv,AlgID,AFlags,@hKey) then
begin
AddToMemo(’AT_KEYEXCHANGE CryptGenKey - ok. ContainerName = ’ + ContainerName);
end
else
begin
ErrCode := GetLastError();
case ErrCode of
ERROR_INVALID_HANDLE : ErrMsg := ’One of the parameters specifies an invalid handle’;
ERROR_INVALID_PARAMETER : ErrMsg := ’One of the parameters contains an invalid value. This is most often an illegal pointer.’;
NTE_BAD_ALGID : ErrMsg := ’The Algid parameter specifies an algorithm that this CSP does not support.’;
NTE_BAD_FLAGS : ErrMsg := ’The dwFlags parameter contains an invalid value.’;
NTE_BAD_UID : ErrMsg := ’The hProv parameter does not contain a valid context handle.’;
NTE_FAIL : ErrMsg := ’The function failed in some unexpected way.’;
else ErrMsg := ’Unknown Error’;
end;
AddToMemo(’CryptGenKey - Failed! ’+ IntToStr(ErrCode)+ ’ ’ + ErrMsg);
end;
AlgID := AT_SIGNATURE;
AFlags := 1024;
AFlags := (AFlags shl 16) OR CRYPT_EXPORTABLE ;
if CryptGenKey(AProv,AlgID,AFlags,@hKey) then
begin
AddToMemo(’AT_SIGNATURE CryptGenKey - ok. ContainerName = ’ + ContainerName);
end
else
begin
ErrCode := GetLastError();
case ErrCode of
ERROR_INVALID_HANDLE : ErrMsg := ’One of the parameters specifies an invalid handle’;
ERROR_INVALID_PARAMETER : ErrMsg := ’One of the parameters contains an invalid value. This is most often an illegal pointer.’;
NTE_BAD_ALGID : ErrMsg := ’The Algid parameter specifies an algorithm that this CSP does not support.’;
NTE_BAD_FLAGS : ErrMsg := ’The dwFlags parameter contains an invalid value.’;
NTE_BAD_UID : ErrMsg := ’The hProv parameter does not contain a valid context handle.’;
NTE_FAIL : ErrMsg := ’The function failed in some unexpected way.’;
else ErrMsg := ’Unknown Error’;
end;
AddToMemo(’CryptGenKey - Failed! ’+ IntToStr(ErrCode)+ ’ ’ + ErrMsg);
end;
end
else
begin
AddToMemo(’Имя провайдера (PP_NAME) has not been resolved’);
end;
FreeMem(AData,ASize);
end
else
begin
AddToMemo(’CryptGetProvParam - Failed! ’+ IntToStr(GetLastError()));
end;
//Освобождение провайдера
AFlags := 0;
CryptReleaseContext(AProv,AFlags);
end
else
begin
Err := GetLastError();
case Err of
ERR_KEYSET_ALREADY_EXISTS : AddToMemo(’CryptAcquireContext - Failed! KeySet already exists!’);
else
AddToMemo(’CryptAcquireContext - Failed ’+ IntToHex(Err,16) + ’ (dec: ’ + IntToStr(Err));
end;
end;
end;
08.11.2005 12:12:44Kirill Sobolev
А вот такой минимальный код будет работать?
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
BOOL bRes;
DWORD size;

bRes = ::CryptAcquireContext(&hProv, _T("mycont"), CP_GR3410_94_PROV, PROV_GOST_94_DH, CRYPT_NEWKEYSET);
bRes = CryptGenKey(hProv, AT_KEYEXCHANGE, 1024 << 16 | CRYPT_EXPORTABLE, &hKey);
bRes = CryptGenKey(hProv, AT_SIGNATURE, 1024 << 16 | CRYPT_EXPORTABLE, &hKey);
CryptReleaseContext(hProv, 0);

bRes = ::CryptAcquireContext(&hProv, _T("mycont"), CP_GR3410_94_PROV, PROV_GOST_94_DH, 0);
bRes = ::CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, &size);
PCERT_PUBLIC_KEY_INFO pInfo = (PCERT_PUBLIC_KEY_INFO)malloc(size);
bRes = ::CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, TYPE_DER, pInfo, &size);
CryptReleaseContext(hProv, 0);

У меня работает нормально, ключи в реестре.
08.11.2005 12:31:29Mick
Этот код работает, спасибо!
Пойду искать 10 отличий.
Скажите, а паскалевских примеров получить невозможно? А то у меня адаптация кода идет слишком медленно.