Задать вопрос
Filyushin
@Filyushin
Python, Delphi, Firebird

Как использовать ЭЦП в файле .p12 в Delphi?

Имеется ЭЦП в формате PKCS12. Необходимо прочитать сертификат, определить владельца, актуальность сертификата (дата выдачи, дата истечения срока действия). Решается, думаю, что через OpenSSL. Встречали обёртки для функций, оптимизированные заголовки для Делфей, готовый работающий код примеров?
  • Вопрос задан
  • 1969 просмотров
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 1
mylp
@mylp
php + js = site + crm
Решал похожую задачу используя CryptoCSP от компании CryptoPro (документация по теме). Это обертка на работу с сертификатами, можно попробовать поработать через CryptoAPI от Майкрософта, если разберетесь.

Даю пару примеров, чтобы Вы поняли, в каком направлении двигаться:

Пример 1.

// Пример работы с сертификатами. Поиск по номеру сертификата.
// В дельфи номер пишется в обратном порядке!
class function TDigitalSigner.GetCertificateBySerialNumber(const aSerialNumber: string): PCCERT_CONTEXT;
var
	hStore: hcertstore;
begin
	hStore := CertOpenSystemStore(0, 'MY');
	Result := CertFindCertificateInStore(hStore, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, PChar(aSerialNumber), nil);
end;


Пример 2.

function EncryptAndSign(ASignCertContent: string; AEncCerts: TStringList; FileName, OutFileName: string; out ErrText: string): Boolean;
var
	hProv       : HCRYPTPROV;
	hStoreHandle: hcertstore;
	pSignerCert : jwawincrypt.PCCERT_CONTEXT;
	encCert     : jwawincrypt.CRYPT_DATA_BLOB;
	SigParams   : jwawincrypt.CRYPT_SIGN_MESSAGE_PARA;
	pCertContext: PCCERT_CONTEXT;
	Stream      : TMemoryStream;
	Certificates: array [0 .. 100] of PCCERT_CONTEXT;
	EncParams   : CRYPT_ENCRYPT_MESSAGE_PARA;
	cbEncrypted : DWORD;
	i           : integer;
	pszObjId    : LPSTR;
const
	PROV_GOST_2001_DH = 75;
begin
	Result := false;
	for i := 0 to 100 do
		Certificates[i] := nil;

	if not jwawincrypt.CryptAcquireContext(hProv, nil, nil, PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT) then
		exit;

	hStoreHandle := CertOpenSystemStore(hProv, 'MY');
	if (hStoreHandle = nil) then
	begin
		ErrText := 'ErrorOpenStore';
		exit;
	end;

	for i := 0 to AEncCerts.Count - 1 do
	begin
		try
			encCert := GetCertContent(FileToStr(AEncCerts.Strings[i]));
		except
			ErrText := 'ErrorCertLoad';
			Continue;
		end;

		pCertContext := jwawincrypt.CertCreateCertificateContext(MYTYPE, encCert.pbData, encCert.cbData);
		pCertContext := jwawincrypt.CertFindCertificateInStore(hStoreHandle, MYTYPE, 0, CERT_FIND_EXISTING, pCertContext, nil);
		if (pCertContext = nil) then
		begin
			ErrText := 'ErrorCertInStoreNotFound';
			Continue;
		end;
		Certificates[i] := pCertContext;
	end;

	encCert := GetCertContent(FileToStr(ASignCertContent));
	// Открываем хранилище сертификатов
	pSignerCert := nil;
	pSignerCert := jwawincrypt.CertCreateCertificateContext(MYTYPE, encCert.pbData, encCert.cbData);
	pSignerCert := jwawincrypt.CertFindCertificateInStore(hStoreHandle, MYTYPE, 0, CERT_FIND_EXISTING, pSignerCert, nil);
	if (pSignerCert = nil) then
	begin
		exit;
	end;

	with TMemoryStream.Create do
		try
			LoadFromFile(FileName);
			try
				try
					// Инициализация структуры, необходимой для цифровой подписи
					pszObjId := szOID_RSA_MD5; // получение алгоритма сертификата
					FillChar(SigParams, Sizeof(CRYPT_SIGN_MESSAGE_PARA), #0);
					SigParams.cbSize := Sizeof(CRYPT_SIGN_MESSAGE_PARA);
					SigParams.dwMsgEncodingType := MYTYPE;
					SigParams.pSigningCert := pSignerCert;
					SigParams.HashAlgorithm.pszObjId := pszObjId;
					// для Сигнал - Com szOID_RSA_MD5;//  1.2.643.2.2.21
					SigParams.HashAlgorithm.Parameters.cbData := 0;
					SigParams.cMsgCert := 1;
					SigParams.rgpMsgCert := @pSignerCert;
					SigParams.cAuthAttr := 0;
					SigParams.dwInnerContentType := 0;
					SigParams.cMsgCrl := 0;
					SigParams.cUnauthAttr := 0;
					SigParams.dwFlags := 0;
					SigParams.pvHashAuxInfo := nil;
					SigParams.rgAuthAttr := nil;

					ZeroMemory(@EncParams, Sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
					EncParams.cbSize := Sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
					EncParams.dwMsgEncodingType := MYTYPE;
					EncParams.HCRYPTPROV := hProv;
					EncParams.ContentEncryptionAlgorithm.pszObjId := szOID_CP_GOST_28147;
					// Алгоритм шифрования ГОСТ 28147-89 1.2.643.2.2.21
					if CryptSignAndEncryptMessage(@SigParams, @EncParams, AEncCerts.Count, @Certificates, Memory, Size, nil, cbEncrypted) then
					begin
						Stream := TMemoryStream.Create;
						try
							Stream.SetSize(cbEncrypted);
							if CryptSignAndEncryptMessage(@SigParams, @EncParams, AEncCerts.Count, @Certificates, Memory, Size, Stream.Memory, cbEncrypted) then
							begin
								Stream.SetSize(cbEncrypted);
								Stream.SaveToFile(OutFileName);
								Result := True;
							end
							else
								ErrText := SysErrorMessage(GetLastError);
						finally
							FreeAndNil(Stream);
						end;
					end
					else
						ErrText := SysErrorMessage(GetLastError);
				except
					ErrText := SysErrorMessage(GetLastError);
				end;
			finally
				CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
			end;
		finally
			Free;
		end;
end;
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы