Требуется программно сгенерировать запрос на сертификат, кто занимался подскажите как, заранее благодарен.
Код (Text): procedure TCreateReqForm.OKBtnClick(Sender: TObject); var nameAttr: CERT_RDN_ATTR; nameString: PChar; rdn: CERT_RDN; nameInfo: CERT_NAME_INFO; certReqInfo: CERT_REQUEST_INFO; subjNameBlob: CERT_NAME_BLOB; encNameLen: DWORD; encName: PBYTE; prov: HCRYPTPROV; pubKeyInfoLen: DWORD; pubKeyInfo: PCERT_PUBLIC_KEY_INFO; encCertReqLen: DWORD; params: CRYPT_OBJID_BLOB; sigAlg: CRYPT_ALGORITHM_IDENTIFIER; signedEncCertReq: PBYTE; cont: PChar; err: string; encType: DWORD; f: file; begin encType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING; nameString := StrAlloc(length(SubjectEdit.text)+1); StrPCopy(nameString, SubjectEdit.Text); nameAttr.pszObjId := '2.5.4.3'; nameAttr.dwValueType := CERT_RDN_PRINTABLE_STRING; nameAttr.Value.cbData := length(SubjectEdit.text); nameAttr.Value.pbData := PBYTE(nameString); rdn.cRDNAttr := 1; rdn.rgRDNAttr := @nameAttr; nameInfo.cRDN := 1; nameInfo.rgRDN := @rdn; if not CryptEncodeObject(encType, X509_NAME, @nameInfo, nil, @encNameLen) or (encNameLen < 1) then begin MessageDlg('CryptEncodeObject error ' + inttostr(GetLastError), mtError, [mbOK], 0); StrDispose(nameString); exit; end; GetMem(encName, encNameLen); if not CryptEncodeObject(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, X509_NAME, @nameInfo, encName, @encNameLen) or (encNameLen < 1) then begin MessageDlg('2nd CryptEncodeObject error ' + inttostr(GetLastError), mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); exit; end; subjNameBlob.cbData := encNameLen; subjNameBlob.pbData := encName; certReqInfo.Subject := subjNameBlob; certReqInfo.cAttribute := 0; certReqInfo.rgAttribute := nil; certReqInfo.dwVersion := CERT_REQUEST_V1; if length(ContainerEdit.Text) = 0 then cont := nil else begin err := ContainerEdit.Text; cont := StrAlloc(length(err) + 1); StrPCopy(cont, err); end; if not CryptAcquireContext(@prov, cont, nil, PROV_RSA_FULL, 0) then begin case int64(GetLastError) of ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER'; ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY'; NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS'; NTE_BAD_KEYSET: err := 'NTE_BAD_KEYSET'; NTE_BAD_KEYSET_PARAM: err := 'NTE_BAD_KEYSET_PARAM'; NTE_BAD_PROV_TYPE: err := 'NTE_BAD_PROV_TYPE'; NTE_BAD_SIGNATURE: err := 'NTE_BAD_SIGNATURE'; NTE_EXISTS: err := 'NTE_EXISTS'; NTE_KEYSET_ENTRY_BAD: err := 'NTE_KEYSET_ENTRY_BAD'; NTE_KEYSET_NOT_DEF: err := 'NTE_KEYSET_NOT_DEF'; NTE_NO_MEMORY: err := 'NTE_NO_MEMORY'; NTE_PROV_DLL_NOT_FOUND: err := 'NTE_PROV_DLL_NOT_FOUND'; NTE_PROV_TYPE_ENTRY_BAD: err := 'NTE_PROV_TYPE_ENTRY_BAD'; NTE_PROV_TYPE_NO_MATCH: err := 'NTE_PROV_TYPE_NO_MATCH'; NTE_PROV_TYPE_NOT_DEF: err := 'NTE_PROV_TYPE_NOT_DEF'; NTE_PROVIDER_DLL_FAIL: err := 'NTE_PROVIDER_DLL_FAIL'; NTE_SIGNATURE_FILE_BAD: err := 'NTE_SIGNATURE_FILE_BAD'; else err := 'Unknown error'; end; MessageDlg('Ошибка создания контейнера: ' + err, mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); exit; end; if not CryptExportPublicKeyInfo (prov, AT_SIGNATURE, encType, nil, @pubKeyInfoLen) then begin MessageDlg('Ошибка экспорта открытого ключа', mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); exit; end; GetMem(pubKeyInfo, pubKeyInfoLen); if not CryptExportPublicKeyInfo (prov, AT_SIGNATURE, encType, pubKeyInfo, @pubKeyInfoLen) then begin MessageDlg('Ошибка экспорта открытого ключа', mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); FreeMem(pubKeyInfo, pubKeyInfoLen); exit; end; certReqInfo.SubjectPublicKeyInfo := pubKeyInfo^; FillChar(params, sizeof(params), 0); sigAlg.pszObjId := szOID_OIWSEC_sha1RSASign; sigAlg.Parameters := params; if not CryptSignAndEncodeCertificate (prov, AT_SIGNATURE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, @certReqInfo, @sigAlg, nil, nil, @encCertReqLen) then begin MessageDlg('Ошибка получения длины подписанного запроса', mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); FreeMem(pubKeyInfo, pubKeyInfoLen); exit; end; GetMem(signedEncCertReq, encCertReqLen); if not CryptSignAndEncodeCertificate (prov, AT_SIGNATURE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, @certReqInfo, @sigAlg, nil, signedEncCertReq, @encCertReqLen) then begin MessageDlg('Ошибка получения подписанного запроса', mtError, [mbOK], 0); StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); FreeMem(pubKeyInfo, pubKeyInfoLen); FreeMem(signedEncCertReq, encCertReqLen); exit; end; if SaveDlg.Execute then begin AssignFile(f, SaveDlg.FileName); rewrite(f, 1); BlockWrite(f, signedEncCertReq^, encCertReqLen); CloseFile(f); end; StrDispose(nameString); FreeMem(encName, encNameLen); if cont <> nil then StrDispose(cont); FreeMem(pubKeyInfo, pubKeyInfoLen); FreeMem(signedEncCertReq, encCertReqLen); if not CryptReleaseContext(prov, 0) then begin MessageDlg('Ошибка освобождения контекста', mtError, [mbOK], 0); end; end;
Сделал запрос как было предложено в предыдущем посте, использую криптопрошный криптопровайдер. Но размер создаваемого запроса меньше чем если сохранять запрос в файле через интерфейс УЦ, и запрос отклонятся и выводится следующая ошибка: Your Request Id is 0. The disposition message is "Error Parsing Request ASN1 bad tag value met. 0x8009310b (ASN: 267)". В чем может быть дело?
Ну да, но это было так давно... сейчас уже не помню. Код не мой, а из статьи какой-то, я его проверил - работало, может при копипасте чего нарушилось.
Каким должен быть этот параметр если я генрю запрос для MS CA с криптоПРО? И что за структура CRYPT_OBJID_BLOBа?