Информационная безопасность



              

Windows и Delphi на защите секретов (часть 4) - часть 5


Эта функция закодирует структуру CERT_REQUEST_INFO и все данные, на которые в этой структуре имеются ссылки, подпишет эту закодированную информацию и еще раз закодирует уже подписанные данные.

Полученный в результате подписанный и закодированный запрос сертификата нужно сохранить в файле и отправить в центр сертификации. Далее приведен текст процедуры (без обработки ошибок), реализующей описанный выше алгоритм:

{SubjectEdit - поле формы, в которое пользователь вводит текст поля Subject сертификата; поле формы ContainerEdit может содержать имя контейнера ключей (если остается пустым, используется контейнер по умолчанию)} 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; {выясняем размер закодированного имени пользователя} CryptEncodeObject (encType, X509_NAME, @nameInfo, nil, @encNameLen) or (encNameLen < 1); GetMem (encName, encNameLen); {кодируем имя пользователя} CryptEncodeObject (PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, X509_NAME, @nameInfo, encName, @encNameLen) or (encNameLen < 1); 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; CryptAcquireContext (@prov, cont, nil, PROV_RSA_FULL, 0); CryptExportPublicKeyInfo (prov, AT_SIGNATURE, encType, nil, @pubKeyInfoLen); GetMem (pubKeyInfo, pubKeyInfoLen); CryptExportPublicKeyInfo (prov, AT_SIGNATURE, encType, pubKeyInfo, @pubKeyInfoLen); certReqInfo.SubjectPublicKeyInfo:= pubKeyInfo^; FillChar (params, sizeof (params), 0); sigAlg.pszObjId:= szOID_OIWSEC_sha1RSASign; sigAlg.Parameters:= params; CryptSignAndEncodeCertificate (prov, AT_SIGNATURE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, @certReqInfo, @sigAlg, nil, nil, @encCertReqLen); GetMem (signedEncCertReq, encCertReqLen); CryptSignAndEncodeCertificate (prov, AT_SIGNATURE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, @certReqInfo, @sigAlg, nil, signedEncCertReq, @encCertReqLen); 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); CryptReleaseContext (prov, 0); end;




Содержание  Назад  Вперед