30.10.2007 17:53:26eToken, вторая подпись - ошибка!!! Ответов: 2
Стас
Есть текстовый файл и есть два eToken.
Подписываю первой подписью - всё ОК. Далее подписываю второй подписью (см. функцию) - сваливается с ошибкой 0х80090016 на функции CryptMsgControl(... , CMSG_CTRL_ADD_SIGNER, ...).
В чем проблема?

function TfrMain.CosignMessage(pSignedMessageBlob: CRYPT_DATA_BLOB;
pCosignedMessageBlob: CRYPT_DATA_BLOB;
hCertStoreHandle: HCERTSTORE;
pCosignerCert: PCCERT_CONTEXT
): CRYPT_DATA_BLOB;
var
fReturn: boolean;
hMsg: HCRYPTMSG;
hProv: HCRYPTPROV;
cbCosignedMessageBlob: DWORD;
pbCosignedMessageBlob: PBYTE;
CosignerInfo: CMSG_SIGNER_ENCODE_INFO;
CosignCertBlob: CERT_BLOB;
dwKeySpec: DWORD;
err: String;
SignKey: PHCRYPTKEY;

cablob: CRYPT_ATTR_BLOB;
ca: CRYPT_ATTRIBUTE;
pbAuth: PBYTE;
cbAuth: DWORD;
fileTime: TFILETIME;
systemTime: TSYSTEMTIME;
begin
fReturn := false;
hMsg := nil;
hProv:= 0;

// Initialize the output pointer.
pCosignedMessageBlob.cbData := 0;
pCosignedMessageBlob.pbData := nil;

if not CryptAcquireCertificatePrivateKey(pCosignerCert, 0, nil, @hProv, dwKeySpec, nil) then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('CryptAcquireCertificatePrivateKey ' + err), nil, MB_ICONERROR);
exit;
end;

// Open a message for decoding.
hMsg := CryptMsgOpenToDecode(MY_ENCODING_TYPE, 0, 0, 0, nil, nil);
if hMsg = nil then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('CryptMsgOpenToDecode ' + err), nil, MB_ICONERROR);
exit;
end;

// Update the message with the encoded BLOB.
if not CryptMsgUpdate(hMsg, pSignedMessageBlob.pbData, pSignedMessageBlob.cbData, TRUE) then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('CryptMsgUpdate ' + err), nil, MB_ICONERROR);
exit;
end;

// Initialize the CMSG_SIGNER_ENCODE_INFO structure for the cosigner.
FillChar(CosignerInfo, SizeOf(CMSG_SIGNER_ENCODE_INFO), #0 );
CosignerInfo.cbSize := sizeof(CMSG_SIGNER_ENCODE_INFO);
CosignerInfo.pCertInfo := pCosignerCert.pCertInfo;
CosignerInfo.hCryptProv := hProv;
CosignerInfo.dwKeySpec := AT_SIGNATURE;
CosignerInfo.HashAlgorithm.pszObjId := szOID_RSA_SHA1RSA;

GetSystemTime(systemTime);
SystemTimeToFileTime(systemTime, fileTime);

// Îïðåäåëèì òðåáóåìóþ äëèíó äëÿ õðàíåíèÿ âðåìåíè*/
CryptEncodeObject(MY_ENCODING_TYPE, szOID_RSA_signingTime, @fileTime, nil, @cbAuth);

GetMem(pbAuth,cbAuth);

// Êîäèðîâàíèå âðåìåíè â àòðèáóò òèïà szOID_RSA_signingTime */
CryptEncodeObject(MY_ENCODING_TYPE, szOID_RSA_signingTime, @fileTime, pbAuth, @cbAuth);

cablob.cbData := cbAuth;
cablob.pbData := pbAuth;

ca.pszObjId := szOID_RSA_signingTime;
ca.cValue := 1;
ca.rgValue := @cablob;

CosignerInfo.cAuthAttr := 1;
CosignerInfo.rgAuthAttr := @ca;

// Add the cosigner to the message.
if not CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, @CosignerInfo) then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('CryptMsgControl CMSG_CTRL_ADD_SIGNER ' + err), nil, MB_ICONERROR);
exit;
end;

// Add the cosigner's certificate to the message.
CosignCertBlob.cbData := pCosignerCert.cbCertEncoded;
CosignCertBlob.pbData := pCosignerCert.pbCertEncoded;

if not CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, @CosignCertBlob) then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('CryptMsgControl CMSG_CTRL_ADD_CERT ' + err), nil, MB_ICONERROR);
exit;
end;

// Get the size of the cosigned BLOB.
if not CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, nil, @cbCosignedMessageBlob) then
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('Get the size of the cosigned BLOB error-' + err), nil, MB_ICONERROR);
exit;
end;

// Allocate memory for the cosigned BLOB.
GetMem(pbCosignedMessageBlob, cbCosignedMessageBlob);

// Get the cosigned message BLOB.
if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, pbCosignedMessageBlob, @cbCosignedMessageBlob)) then
begin
// pbSignedMessageBlob now contains the signed BLOB.
fReturn := true;
end
else
begin
err := IntToStr(GetLastError);
Application.MessageBox(PChar('Get the cosigned message BLOB error-' + err), nil, MB_ICONERROR);
exit;
end;

// Clean up and free memory as needed.

if hMsg <> nil then CryptMsgClose(hMsg);
if hProv <> 0 then
begin
CryptReleaseContext(hProv, 0);
hProv := 0;
end;

// Only free the cosigned message if a failure occurred.
if not fReturn then
begin
if pbCosignedMessageBlob <> nil then
begin
Freemem(pbCosignedMessageBlob);
pbCosignedMessageBlob := nil;
end;
end;
if pbCosignedMessageBlob <> nil then
begin
pCosignedMessageBlob.cbData := cbCosignedMessageBlob;
pCosignedMessageBlob.pbData := pbCosignedMessageBlob;
end;

result := pCosignedMessageBlob;
end;
 
Ответы:
31.10.2007 14:20:34Стас
Кстати, если в качестве носителя использовать дискету, то этот код работает. Не уж то есть разница с какого носителя вести чтение?
08.11.2007 2:30:15maxdm
CosignerInfo.dwKeySpec := AT_SIGNATURE;
CosignerInfo.HashAlgorithm.pszObjId := szOID_RSA_SHA1RSA;
Первая строка - допущение, вторая - не должна использоваться с Крипто-Про CSP, да и вообще это не алгоритм хэширования