| ||||
| ||||
Пробую воспроизвести пример создания сертификакта из примера поставляемого с криптопровайдером. На этапе CryptExportPublicKeyInfo получаю ошибку NTE_NO_KEY, хотя все предыдущие вызовы прошли успешно. dwSize := 0; dwKeyType := AT_SIGNATURE; bResult := CryptExportPublicKeyInfo(hProv,dwKeyType,X509_ASN_ENCODING,nil,@dwSize); Подскажите, в чем может быть ошибка? | ||||
Ответы: | ||||
| ||||
Мб у Вас ключ не AT_SIGNATURE а AT_KEYEXCHANGE? | ||||
| ||||
В том то и дело, что внутри контейнера оба ключа. Я их всегда генерирую только парами. Скажите, а у вас нет примеров аналогичных csptest, но на Pascal’e? | ||||
| ||||
А можно глянуть код генерации? | ||||
| ||||
Вот код инициализации контейнера. Сорри за инородный язык. 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; | ||||
| ||||
А вот такой минимальный код будет работать? 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); У меня работает нормально, ключи в реестре. | ||||
| ||||
Этот код работает, спасибо! Пойду искать 10 отличий. Скажите, а паскалевских примеров получить невозможно? А то у меня адаптация кода идет слишком медленно. | ||||