07.05.2007 17:36:15CryptGetUserKey и ошибка Key does not exist. Ответов: 5
slow
Выполняю код:

function TCrypter.Sign(data: TStream; rslt: TStream; alg_id: dword): boolean;
var hHash: HCRYPTHASH;
hExchKey: HCRYPTKEY;
cbHash, dwBufferLen, dwSigLen: DWORD;
pbHash, pbBuffer, pbSignature: Pointer;
s: pchar;
begin
result := false;
try
//--- Создание объекта функции хеширования.
if not CryptCreateHash(CryptContext.Provider, alg_id, 0, 0, @hHash) then
raise TCryptException.Create(ceOtherCryptError);//Exception.Create('Hash object was NOT created '+INtToStr(getlasterror));

s := stralloc(5000);

cbHash := 0;

//--- Определение размера BLOBа и распределение памяти.
if not CryptGetHashParam(hHash, HP_OID, nil, @cbHash, 0) then
begin
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
nil, getlasterror, 0, @s, 0, nil);
raise Exception.Create('Error computing BLOB length '+s);
end;

try
GetMem(pbHash, cbHash);
except
raise Exception.Create('Memory was NOT allocated');
end;



//--- Заполняем буфер и заносим его длину
dwBufferLen := data.Size - data.Position;
GetMem(pbBuffer, dwBufferLen);
data.ReadBuffer(pbBuffer^, dwBufferLen);

if not(CryptGetHashParam(hHash,
HP_OID,
pbHash,
@cbHash,
0)) then
raise TCryptException.Create(ceOtherCryptError);

//--- Вычисление криптографического хеша буфера.
if not CryptHashData(hHash, pbBuffer, dwBufferLen, 0) then
raise Exception.Create('Error during CryptHashData');

//if not CryptGetUserKey(CryptContext.Provider,AT_KEYEXCHANGE, @hExchKey) then
// raise TCryptException.Create(ceOtherCryptError);


//--- Определение размера подписи и распределение памяти.
dwSigLen := 0;
if not CryptSignHash(hHash, AT_KEYEXCHANGE, nil, 0, nil, @dwSigLen) then
begin
raise Exception.Create('Size of sign was NOT determined, error='+inttostr(getlasterror));
end;

//--- Распределение памяти под буфер подписи.
GetMem(pbSignature, dwSigLen);

//--- Подпись объекта функции хеширования.
if not CryptSignHash(hHash, AT_KEYEXCHANGE, nil, 0, pbSignature, @dwSigLen) then
//******** ТУТ ВЫПАДАЕТ С ОШИБКОЙ Key Does Not Exist.
raise TCryptException.Create(ceOtherCryptError);


//--- Запись результата в поток
rslt.WriteBuffer(pbSignature^, dwSigLen);

Result := true;
finally
//--- Уничтожение объекта функции хеширования.
if hHash <> 0 then CryptDestroyHash(hHash);

//--- Освобождение памяти
FreeMem(pbSignature);
FreeMem(pbBuffer);
FreeMem(pbHash);
end;

end;

Имя контейнера передаю в дружественном формате.
Если передаю уникальное имя, валится на CryptAcquireContext.

Вызов делается так:

//--- create key container
if not CryptAcquireContext(@hProv,pszContainerName,pszProviderName,dwProviderType, 0) then
if not CryptAcquireContext(@hProv,pszContainerName,pszProviderName,dwProviderType, CRYPT_NEWKEYSET) then
raise TCryptException.Create(ceCryptContextNotAcquired);

параметры

'FAT12\34743A3F\RaUser-9.000\AC083',
CP_GR3410_2001_PROV_A,PROV_GOST_2001_DH
 
Ответы:
07.05.2007 17:46:03slow
Если передаю уникальное имя контейнера, CryptAcquireContext выдает ошибку Keyset as registered is Invalid.

Если передаю дружественное имя контейнера, ошибка возникает при вызове CryptSignHash - Key does not exist.

Вызов CryptGetUserKey вываливается с ошибкой Key does not exist.

Почему? Весь мозг сломал. Единственное, что приходит в голову - повреждение контейнера или дисковода
08.05.2007 0:42:37maxdm
попробуйте с ключом в реестре
08.05.2007 10:18:53slow
Дело в том, что если я создаю контейнер сам, то все работает ок. проблема только с ключевой дискетой, сгенерированной для меня центром сертификации
08.05.2007 10:19:27Василий
В контейнере может не быть ключа AT_KEYEXCHANGE.
Вместо него может быть AT_SIGNATURE.
08.05.2007 11:50:13slow
Спасибо, проверялись оба типа ключей. Впрочем, вопрос решен. Попросил сделать еще одну дискету, с ней все ок. Видимо, дискеты запорол.