17.12.2005 8:28:26Шифрование по паролю при помощи Крипто-Про Как указать алгоритм шифрования? Ответов: 2
Степанов Павел
Есть пример, котрорый работает для провайдера Микрософт
Пытаюсь переделать для Крипто-Про:

procedure CryptoPRO_Test_Encrypt_by_password;
var err: string;
hProv: HCRYPTPROV; //контекст криптопровайдера
hash: HCRYPTHASH; //дескриптор хеш-объекта
key: HCRYPTKEY; //дескриптор ключа
parol : string;
i: integer;
l: DWORD;
data: PByte;
inFile, outFile: file;
plaintext, ciphertext: string;
begin
//Получаем контекст провайдера
//Crypto-Pro GOST R 34.10-94 Cryptographic Service Provider //тип 75
//if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
if not CryptAcquireContext(@hProv, nil, nil, 75, CRYPT_VERIFYCONTEXT) 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: err := '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: err := 'NTE_SIGNATURE_FILE_BAD';
else err := 'Unknown error';
end;
MessageDlg('Error of CryptAcquireContext: '+err,
mtError, [mbOK], 0);
exit;
end;

//Создаем дескриптор хеш-объекта который будет работать по алгоритму SHA
if not CryptCreateHash(hProv, CALG_SHA, 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 err := 'Unknown error';
end;
MessageDlg('Error of CryptCreateHash: '+err,
mtError, [mbOK], 0);
exit;
end;

parol := 'angara';
//Создаем хеш пароля
if not CryptHashData(hash, @parol[1], length(parol), 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('Error of CryptHashData: '+err,
mtError, [mbOK], 0);
exit;
end;

До этого места работает

//Создаем ключ по хеш-у пароля
//для алгортима RC4 ???? - здесь очевидно надо указать
//шифрование по ГОСТ - КАК ЭТО СДЕЛАТЬ, КАКИМ ИЗ ТРЕХ ПРОВАЙДЕРОВ КРИПТО_ПРО лучше пользоваться?
if not CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key) 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('Error of CryptDestroyHash: '+err,
mtError, [mbOK], 0);
exit;
end;

//Осталось зашифровать файл

MainForm.SaveDialog1.Title := 'Куда сохранить зашифрованные данные?';
MainForm.SaveDialog1.Filter := 'Все файлы (*.*)|*.*|Зашифрованные файлы (*.enc)|*.enc';
MainForm.SaveDialog1.DefaultExt := 'enc';

if MainForm.SaveDialog1.Execute then
begin
ciphertext := MainForm.SaveDialog1.FileName;
AssignFile(inFile, plaintext);
AssignFile(outFile, ciphertext);
reset(inFile, 1); { Record size = 1 }
rewrite(outFile, 1); { Record size = 1 }
GetMem(data, 512);

while not eof(inFile) do
begin
BlockRead(inFile, data^, 512, l); //читаем блок, в l - сколько реально считано
//шифруем блок ключом из key
if not CryptEncrypt(key,
0, //хеш не считаем
eof(inFile), //последний ли блок шифруем?
0, //????
data, //данные
@l, //размер данных
l) // размер буфера
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_DATA: err := 'NTE_BAD_DATA';
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_DOUBLE_ENCRYPT: err := 'NTE_DOUBLE_ENCRYPT';
NTE_FAIL: err := 'NTE_FAIL';
NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
else err := 'Unknown error';
end;
MessageDlg('Error of ncrypt: '+err,
mtError, [mbOK], 0);
exit;
end;
BlockWrite(outFile, data^, l);
end;

FreeMem(data, 512);

CloseFile(inFile);
CloseFile(outFile);
//FileMemo.Lines.Clear;
plaintext := '';
ciphertext := '';
//EncryptItem.Enabled := false;
end;

//освобождаем контекст крипто-провайдера
if not CryptReleaseContext(hProv, 0) 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_FLAGS: err := 'NTE_BAD_FLAGS';
NTE_BAD_UID: err := 'NTE_BAD_UID';
else err := 'Unknown error';
end;
MessageDlg('Error of CryptReleaseContext: '+err,
mtError, [mbOK], 0);
end;


end;
 
Ответы:
19.12.2005 15:33:56maxdm
//Создаем ключ по хеш-у пароля
//для алгортима RC4 ???? - здесь очевидно надо указать
//шифрование по ГОСТ - КАК ЭТО СДЕЛАТЬ, КАКИМ ИЗ ТРЕХ ПРОВАЙДЕРОВ КРИПТО_ПРО лучше пользоваться?
if not CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key) then
Для ГОСТ должно быть так CryptDeriveKey(hProv, CALG_G28147, hash, 0, @key)
А алгоритм шифрования выбирается по алгоритму ключа
19.12.2005 15:35:05maxdm
Также CryptCreateHash нужно вызывать с CALG_GR3411