Статус: Участник
Группы: Участники
Зарегистрирован: 12.07.2012(UTC) Сообщений: 16 Откуда: Томск
|
Добрый день! Возможно задам глупый вопрос, но никак не могу победить ошибку этой функции - NTE_BAD_KEY_STATE. Также может вылезти ошибка NTE_BAD_KEY. Уже перелопатил все, что можно и в интернете и на форуме, но так и не понял, что нужно предпринять для её утранения и причину то вроде понял - Контейнер создаваемый почему то не разрешает экспортировать содержащийся в нем ключ, хотя при прохождении теста контейнера - Интерфейс КриптоПро показывает, что все необходимые разрешения установленны. Скрин теста: Скрин теста контейнераЗабыл сказать - пишу программу на Delphi с использованием JwaWinCrypt.pas. Работаю с консультацией со стороны SDK. Контейнер хранится в реестре. Контейнер создаю следующим образом: Код:procedure TCryptCrypTo.Button1Click(Sender: TObject);
Var
hProv: HCRYPTPROV;
ContName, err: string;
cont: PChar;
KeyExchKey, SignKey: HCRYPTKEY;
KeySave: TmemoryStream;
CryptMessagA: TMemoryStream;
Crypter: TMemoryStream;
MessagA: ShortString;
infile, outfile: file;
tmp: PBYTE;
SessionKey: HCRYPTKEY;
stream: boolean;
alg: ALG_ID;
buf: array [0..511] of byte;
keyLen, flag: DWord;
Password: string;
hash: HCRYPTHASH;
expKey: HCRYPTKEY;
key: HCRYPTKEY;
pbuf: PBYTE;
buflen: DWORD;
begin
ContName:='Diagngostic+';
cont:=StrAlloc(Length(ContName)+1);
StrPCopy(cont, ContName);
//проверяю, есть ли такой контейнер :) Если его нет, то создаю и генерирую ключики ;).
if not CryptAcquireContext(hProv, cont, nil, PROV_GOST_2001_DH, 0)
then
begin
case int64(GetLastError) of
{.........................................................}
end;
if err = 'NTE_BAD_KEYSET' then //Нету контейнера ==>> создаю его
begin
if not CryptAcquireContext(hProv, cont, nil, PROV_GOST_2001_DH, CRYPT_NEWKEYSET)
then
begin
case int64(GetLastError) of
{.............................}
end;
MessageDlg('Ошибка создания контейнера: ' + ContName, mtError, [mbOK], 0);
exit;
end
else MessageDlg('Создан контейнер с именем ' + ContName, mtInformation, [mbOK], 0);
//===============================================================================================================================
//Контейнера не было ==> генерирую ключевые пары_
keyLen := StrToInt('512');
flag := keyLen shl 16;
if not CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, KeyExchKey) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_FAIL: err := 'NTE_FAIL';
else err := 'Unknown error';
end;
MessageDlg('Ошибка создания ключа обмена ключами: ' + err,
mtError, [mbOK], 0);
end
else
begin
flag := 4;
if not CryptGetKeyParam(KeyExchKey, KP_KEYLEN, @keyLen, flag, 0) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_NO_KEY: err := 'NTE_NO_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения длины ключа: ' + err,
mtError, [mbOK], 0);
end;
flag := 4;
if not CryptGetKeyParam(KeyExchKey, KP_ALGID, @keyLen, flag, 0) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_NO_KEY: err := 'NTE_NO_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения длины ключа: ' + err,
mtError, [mbOK], 0);
end;
end;
//Работаю с Хешем данных
Password:= 'cjhjr xthys[ j,tpmzy d ;jge ceyekb ,fyfy';
if not CryptCreateHash(hProv, CALG_GR3411, 0, 0, hash) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
else ContName := 'Unknown error';
end;
MessageDlg('Ошибка создания хеш-объекта: ' + err, mtError, [mbOK], 0);
exit;
end;
if not CryptHashData(hash, @(Password[1]), length(Password), 0) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_HASH: err := 'NTE_BAD_HASH';
NTE_BAD_HASH_STATE: err := 'NTE_BAD_HASH_STATE';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_LEN: err := 'NTE_BAD_LEN';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_FAIL: err := 'NTE_FAIL';
NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка при хешировании: ' + err, mtError, [mbOK], 0);
exit;
end;
{if not CryptDeriveKey(hProv, , hash, 0, expKey) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_HASH: err := 'NTE_BAD_HASH';
NTE_BAD_HASH_STATE: err := 'NTE_BAD_HASH_STATE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_FAIL: err := 'NTE_FAIL';
else err := 'Unknown error';
end;
MessageDlg('Error of CryptHashData: '+err,
mtError, [mbOK], 0);
exit;
end; }
if not CryptDestroyHash(hash) then
begin
case int64(GetLastError) of
ERROR_BUSY: err := 'ERROR_BUSY';
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_HASH: err := 'NTE_BAD_HASH';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка при уничтожения хеша: ' + err, mtError, [mbOK], 0);
end;
//Генерирую ключ цифровой подписи
if not CryptGenKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, SignKey) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_FAIL: err := 'NTE_FAIL';
else err := 'Unknown error';
end;
MessageDlg('Ошибка создания ключа подписи: ' + err,
mtError, [mbOK], 0);
end
else
begin
flag := 4;
if not CryptGetKeyParam(SignKey, KP_KEYLEN, @keyLen, flag, 0) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_NO_KEY: err := 'NTE_NO_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения длины ключа: ' + err,
mtError, [mbOK], 0);
end;
flag := 4;
if not CryptGetKeyParam(SignKey, KP_ALGID, @keyLen, flag, 0) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_NO_KEY: err := 'NTE_NO_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения длины ключа: ' + err,
mtError, [mbOK], 0);
end;
end;
//Получаю ключ обмена ключами_
if not CryptGetUserKey(hProv, AT_KEYEXCHANGE, key) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения ключа обмена ключами: ' + err, mtError, [mbOK], 0);
end;
//Сохраняю ключ обмена ключами в файл
if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, nil, bufLen) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_KEY_STATE: err := 'NTE_BAD_KEY_STATE';
NTE_BAD_PUBLIC_KEY: err := 'NTE_BAD_PUBLIC_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения размера BLOB''а ключа обмена ключами: ' + err,
mtError, [mbOK], 0);
end;
GetMem(pbuf, bufLen);
if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pbuf, bufLen) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_KEY_STATE: err := 'NTE_BAD_KEY_STATE';
NTE_BAD_PUBLIC_KEY: err := 'NTE_BAD_PUBLIC_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка экспорта ключа обмена ключами: ' + err,
mtError, [mbOK], 0);
end;
if not CryptDestroyKey(key) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка освобождения дескриптора ключа обмена ключами: ' + err,
mtError, [mbOK], 0);
end;
//Сохраняю ключ обмена ключами в файлик_
KeySave:=TMemoryStream.Create;
KeySave.Write(pbuf^, bufLen);
KeySave.Position:=0;
KeySave.SaveToFile(ExtractFilePath(application.ExeName) + 'Keychange.txt');
KeySave.Free;
//Сохраняю ключевую пару в файл
if not CryptGetUserKey(hProv, AT_SIGNATURE, key) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения ключа подписи: ' + ContName,
mtError, [mbOK], 0);
end;
{$B-}
if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, nil, bufLen) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_KEY_STATE: err := 'NTE_BAD_KEY_STATE';
NTE_BAD_PUBLIC_KEY: err := 'NTE_BAD_PUBLIC_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка получения размера BLOB''а ключа подписи: ' + ContName,
mtError, [mbOK], 0);
end;
GetMem(pbuf, bufLen);
if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pbuf, bufLen) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_KEY_STATE: err := 'NTE_BAD_KEY_STATE';
NTE_BAD_PUBLIC_KEY: err := 'NTE_BAD_PUBLIC_KEY';
NTE_BAD_TYPE: err := 'NTE_BAD_TYPE';
NTE_BAD_UID: err := 'NTE_BAD_UID';
NTE_NO_KEY: err := 'NTE_NO_KEY';
else err := 'Unknown error';
end;
MessageDlg('Ошибка экспорта ключа подписи: ' + err,
mtError, [mbOK], 0);
end;
if not CryptDestroyKey(key) then
begin
case int64(GetLastError) of
ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
NTE_BAD_KEY: err := 'NTE_BAD_KEY';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Ошибка освобождения дескриптора ключа подписи: ' + err,
mtError, [mbOK], 0);
end;
KeySave:= TMemoryStream.Create;
KeySave.Write(pbuf^, bufLen);
KeySave.SaveToFile(ExtractFilePath(application.ExeName) + 'KeyDescr.txt');
KeySave.Free;
//=====================================================================================
//Закончил создавать ключи___
//======================================================================================
end;
end
else MessageDlg('Контейнер с именем ' + ContName + ' успешно открыт', mtInformation, [mbOK], 0);
end;
Далее цепляюсь к нему и пытаюсь получить необходимые для работы ключи: Код:procedure TCryptCrypTo.Button2Click(Sender: TObject);
Var
hProv: HCRYPTPROV;
ContName, err: string;
cont: PChar;
MessagA: ShortString;
Crypter,CryptMessagA: TMemoryStream;
KeyExchKey: HCRYPTKEY;
SessionKey: HCRYPTKEY;
infile, outfile: file;
tmp: PBYTE;
buf: array [0..511] of byte;
stream: boolean;
alg: ALG_ID;
keyLen: DWORD;
begin
ContName:='Diagngostic+';
cont:=StrAlloc(Length(ContName)+1);
StrPCopy(cont, ContName);
if not CryptAcquireContext(hProv, cont, nil, PROV_GOST_2001_DH, 0)
then
begin
case int64(GetLastError) of
ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY';
NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_KEYSET: err := 'NTE_BAD_KEYSET';
NTE_BAD_KEYSET_PARAM: err := 'NTE_BAD_KEYSET_PARAM';
NTE_BAD_PROV_TYPE: err := 'NTE_BAD_PROV_TYPE';
NTE_BAD_SIGNATURE: err := 'NTE_BAD_SIGNATURE';
NTE_EXISTS: err := 'NTE_EXISTS';
NTE_KEYSET_ENTRY_BAD: err := 'NTE_KEYSET_ENTRY_BAD';
NTE_KEYSET_NOT_DEF: err := 'NTE_KEYSET_NOT_DEF';
NTE_NO_MEMORY: ContName := 'NTE_NO_MEMORY';
NTE_PROV_DLL_NOT_FOUND: err := 'NTE_PROV_DLL_NOT_FOUND';
NTE_PROV_TYPE_ENTRY_BAD: err := 'NTE_PROV_TYPE_ENTRY_BAD';
NTE_PROV_TYPE_NO_MATCH: err := 'NTE_PROV_TYPE_NO_MATCH';
NTE_PROV_TYPE_NOT_DEF: err := 'NTE_PROV_TYPE_NOT_DEF';
NTE_PROVIDER_DLL_FAIL: err := 'NTE_PROVIDER_DLL_FAIL';
NTE_SIGNATURE_FILE_BAD: ContName := 'NTE_SIGNATURE_FILE_BAD';
else err := 'Unknown error';
end;
if err = 'NTE_BAD_KEYSET' then //Нету контейнера ==>> создаю его
MessageDlg('Не найден контейнер с именем: ' + ContName, mtInformation, [mbOK], 0);
end
else MessageDlg('Контейнер с именем ' + ContName + ' открыт', mtInformation, [mbOK], 0);
//Теперь приступаю к шифрации сообщения_
MessagA:=Edit1.Text;
CryptMessagA:=TMemoryStream.Create;
CryptMessagA.Write(Messaga,SizeOf(MessagA));
CryptMessagA.Position:=0;
AssignFile(outfile,ExtractFilePath(application.ExeName) +'KeyChange.txt');//Открываем ключ_
reset(outfile, 1);
keyLen := FileSize(outfile);
GetMem(tmp, keyLen);
BlockRead(outfile, tmp^, keyLen);
CloseFile(outfile);
if not CryptImportKey(hProv, tmp, keyLen, 0, 0, KeyExchKey) then
begin
MessageDlg('Ошибка импорта ключа: ' + ErrToStr(GetLastError),
mtError, [mbOK], 0);
exit;
end;
FreeMem(tmp, keyLen);
Crypter:= TMemoryStream.Create;
alg:=CALG_DH_EL_SF;
stream := true;
if not CryptGenKey(hProv, alg, CRYPT_EXPORTABLE or CRYPT_CREATE_SALT,
SessionKey) then
begin
MessageDlg('Ошибка генерации ключа: ' + ErrToStr(GetLastError),
mtError, [mbOK], 0);
exit;
end;
keyLen := 128;
GetMem(tmp, keyLen);
if not CryptExportKey(SessionKey, KeyExchKey, PUBLICKEYBLOB, 0, tmp, keyLen) then
begin
MessageDlg('Ошибка экспорта ключа: ' + ErrToStr(GetLastError),
mtError, [mbOK], 0);
exit;
end;
{.............................}
Соответственно здесь и вылетает ошибка. Обработчик ошибок вставил для своего удобства, чтобы понять, в чем проблемы и куда копать. Очень буду рад, если кто-нибудь направит меня на путь истинный и поможет с решением моей проблемы. + Еще один вопрос - никак не могу понять как обойтись без датчика случайных чисел и программно задать пароль контейнеру. Заранее спасибо за ответы и советы. Отредактировано пользователем 12 июля 2012 г. 17:27:38(UTC)
| Причина: Не указана
|