Статус: Участник
Группы: Участники
Зарегистрирован: 02.12.2014(UTC) Сообщений: 25 Откуда: Воронеж Сказал(а) «Спасибо»: 1 раз
|
Здравствуйте, помогите разобраться, пишу уже от безысходности. Стоит задача создавать отсоединенную ЭЦП pdf-файлов. Для этого были написаны 2 функции (благодаря этому форуму) на выбор, которые прекрасно справлялись с задачей. 1. CreateSignFromPDF Код:
function TMainForm.CreateSignFromPDF(serial, param: string; FNt: TFileName): TFileName;
var
cert: PCCERT_CONTEXT;
SigParams: CRYPT_SIGN_MESSAGE_PARA;
cbSignedMessageBlob, len: DWORD;
pStreamIn, pStreamOut, pStreamEncode: TMemoryStream;
temp: TFileName;
begin
result:='';
cert:=nil;
cert:=FindCertFromSerial(serial);
pStreamIn := TMemoryStream.Create;
try
pStreamOut := TMemoryStream.Create;
try
pStreamIn.LoadFromFile(FNt);
len:=dword(pStreamIn.Size);
ZeroMemory(@SigParams, SizeOf(CRYPT_SIGN_MESSAGE_PARA));
SigParams.cbSize := SizeOF(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType := PKCS_7_ASN_ENCODING;
SigParams.pSigningCert := cert;
if (cert^.PCertInfo^.SubjectPublicKeyInfo.Algorithm.pszObjId=szOID_CP_GOST_R3410_12_256) then SigParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411_12_256;
if (cert^.PCertInfo^.SubjectPublicKeyInfo.Algorithm.pszObjId=szOID_CP_GOST_R3410_12_512) then SigParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411_12_512;
SigParams.HashAlgorithm.Parameters.cbData := 0;
SigParams.cAuthAttr := 0;
SigParams.dwInnerContentType := 0;
SigParams.cUnauthAttr := 0;
SigParams.dwFlags := 0;
SigParams.cMsgCert := 1;
SigParams.rgpMsgCert := @cert;
cbSignedMessageBlob := 0;
if (not Win32Check(CryptSignMessage(@SigParams,
true,
1,
@pStreamIn.Memory,
@len,
nil,
cbSignedMessageBlob))) then
begin
InLog('Ошибка1: ' + SysErrorMessage(GetLastError) + ' - ' + IntToStr(GetLastError));
pStreamOut.Free;
pStreamIn.Free;
CertFreeCertificateContext(cert);
Exit;
end;
pStreamOut.SetSize(cbSignedMessageBlob);
if (not Win32Check(CryptSignMessage(@SigParams,
true,
1,
@pStreamIn.Memory,
@len,
pStreamOut.Memory,
cbSignedMessageBlob))) then
begin
InLog('Ошибка2: ' + SysErrorMessage(GetLastError) + ' - ' + IntToStr(GetLastError));
pStreamOut.Free;
pStreamIn.Free;
CertFreeCertificateContext(cert);
Exit;
end;
pStreamOut.SetSize(cbSignedMessageBlob);
pStreamEncode:=TMemoryStream.Create;
EncodeStream(pStreamOut, pStreamEncode);
if param='doc' then temp:=ExtractFilePath(FNt)+Copy(ExtractFileName(FNt), 1, Length(ExtractFileName(FNt))-4)+'_doc.sig';
if param='mo' then temp:=ExtractFilePath(FNt)+Copy(ExtractFileName(FNt), 1, Length(ExtractFileName(FNt))-4)+'_mo.sig';
pStreamEncode.SaveToFile(temp);
pStreamEncode.Free;
result:=temp;
finally
pStreamOut.Free;
end;
finally
pStreamIn.Free;
end;
CertFreeCertificateContext(cert);
end;
2. CreateCapicomSignFromPDF Код:
function TMainForm.CreateCapicomSignFromPDF(serial, param: string; FNt: TFileName): TFileName;
var
oSigner: Olevariant;
outCTR: Olevariant;
oSignedData: OleVariant;
sSignedData: OleVariant;
Buffer: WideString;
FileStm: TFileStream;
list: TStringList;
temp: TFileName;
begin
FileStm := TFileStream.Create(FNt, fmOpenRead or fmShareDenyWrite);
try
Pointer(Buffer) := ActiveX.SysAllocStringByteLen(nil, FileStm.Size);
FileStm.ReadBuffer(Pointer(Buffer)^, FileStm.Size);
finally
FileStm.Free;
end;
oSigner := COMOBJ.CreateOleObject('CAdESCOM.CPSigner');
if GetSignerCertificate(serial, outCTR) then
begin
oSigner.Certificate := outCTR; {}
oSignedData := COMOBJ.CreateOleObject('CAdESCOM.CadesSignedData'); {}
oSignedData.ContentEncoding := 0; // или 1; {}
oSignedData.Content := Buffer; // или при ContentEncoding кодировать => 'U29tZSBEYXRhLg==';
sSignedData := oSignedData.SignCades(oSigner, {CADES_BES}1, true, {CAPICOM_ENCODE_BASE64}0); {получаем подписанные данные}
list:=TStringList.Create;
list.Add(sSignedData);
if param='doc' then temp:=ExtractFilePath(FN)+Copy(ExtractFileName(FN), 1, Length(ExtractFileName(FN))-4)+'_doc.sig';
if param='mo' then temp:=ExtractFilePath(FN)+Copy(ExtractFileName(FN), 1, Length(ExtractFileName(FN))-4)+'_mo.sig';
list.SaveToFile(temp);
list.Free;
end;
result:=temp;
end;
Несколько месяцев все работало, сейчас начали возникать плавающие ошибки, т.е. прога может отработать корректно, а при следующем запуске вываливает ошибку: Если используем CreateSignFromPDF, то ошибка EOSError: System Error. Code: -2146893792. Внутренняя ошибка. Если используем CreateCapicomSignFromPDF, то ошибка EOleException: Указан неправильный алгоритм. Ошибка одновременная, то есть если начала сбоить, то полетели ошибки на обоих функциях, если работает, то работают обе функции. Гугление приводит только к некорректной работе криптопровайдера, но переустановка КриптоПро или ЭЦП плагина не помогают, даже с полной очисткой через утилиту. На другой схожей машине пока все работает, но боюсь, что она тоже заразиться. Подскажите, как лечить?
|