Delphi и Windows API для защиты секретов

var hProv: HCRYPTPROV; KeyExchKey, SessionKey:


procedure TMainForm.BitBtn1Click (Sender: TObject); var hProv: HCRYPTPROV; KeyExchKey, SessionKey: HCRYPTKEY; flag, keyLen: DWORD; infile, outfile: file; tmp: PBYTE; buf: array [0..511] of byte; alg: ALG_ID; stream: boolean; begin … подключение к криптопровайдеру … if ActionRadioGroup.ItemIndex = 0 {шифрование} then begin OpenDlg.Title:= 'Укажите файл для шифрования'; if OpenDlg.Execute then AssignFile (infile, OpenDlg.FileName) else exit; OpenDlg.Title:= 'Укажите файл с открытым ключом обмена ключами получателя'; if OpenDlg.Execute then begin AssignFile (outfile, OpenDlg.FileName); reset (outfile, 1); keyLen:= FileSize (outfile); GetMem (tmp, keyLen); BlockRead (outfile, tmp^, keyLen); CloseFile (outfile); end else exit; CryptImportKey (hProv, tmp, keyLen, 0, 0, @KeyExchKey); FreeMem (tmp, keyLen); SaveDlg.Title:= 'Задайте имя файла для зашифрованных данных'; if SaveDlg.Execute then AssignFile (outfile, SaveDlg.FileName) else exit; rewrite (outfile, 1); case AlgRadioGroup.ItemIndex of {установка алгоритма шифрования} 0: begin alg:= CALG_RC2; {алгоритм RC2} stream:= false; {блочный шифр} end; 1: begin alg:= CALG_RC4; {алгоритм RC4} stream:= true; {поточный шифр} end; end; CryptGenKey (hProv, alg, CRYPT_EXPORTABLE or CRYPT_CREATE_SALT, @SessionKey); {создание сеансового ключа} keyLen:= 128; {размер буфера "с запасом"} GetMem (tmp, keyLen); CryptExportKey (SessionKey, KeyExchKey, SIMPLEBLOB, 0, tmp, @keyLen); BlockWrite (outfile, keyLen, 4); {запись в файл размера ключа} BlockWrite (outfile, tmp^, keyLen); {и самого зашифрованного ключа} CryptDestroyKey (KeyExchKey); keyLen:= 512; {размер буфера "с запасом"} CryptGetKeyParam (SessionKey, KP_SALT, @buf, @keyLen, 0); BlockWrite (outfile, keyLen, 4); {запись в файл размера солта} BlockWrite (outfile, buf, keyLen); {и самого солт-значения} if not stream then {если шифр - блочный} begin //генерируем IV keyLen:= 512; {размер буфера "с запасом"} // запрос IV ради выяснения его размера CryptGetKeyParam (SessionKey, KP_IV, @buf, @keyLen, 0); CryptGenRandom (hProv, keyLen, @buf); {генерация IV} CryptSetKeyParam (SessionKey, KP_IV, @buf, 0); BlockWrite (outfile, keyLen, 4); {запись в файл размера IV} BlockWrite (outfile, buf, keyLen); {и самого IV} end; reset (infile, 1); while not eof (infile) do begin {собственно шифрование и запись в файл} BlockRead (infile, buf, 496, keyLen); CryptEncrypt (SessionKey, 0, eof (infile), 0, @buf, @keyLen, 512); BlockWrite (outfile, buf, keyLen); end; CloseFile (infile); CloseFile (outfile); CryptDestroyKey (SessionKey); end else {расшифровывание} begin {получаем дескриптор своего ключа обмена ключами} CryptGetUserKey (hProv, AT_KEYEXCHANGE, @KeyExchKey); OpenDlg.Title:= 'Укажите файл с зашифрованными данными'; if OpenDlg.Execute then AssignFile (infile, OpenDlg.FileName) else exit; reset (infile, 1); BlockRead (infile, keyLen, 4); {читаем размер ключа} GetMem (tmp, keyLen); BlockRead (infile, tmp^, keyLen); {читаем сам ключ} CryptImportKey (hProv, tmp, keyLen, KeyExchKey, 0, @SessionKey); FreeMem (tmp, keyLen); CryptDestroyKey (KeyExchKey); BlockRead (infile, keyLen, 4); {читаем солт-значение} BlockRead (infile, buf, keyLen); CryptSetKeyParam (SessionKey, KP_SALT, @buf, 0); keyLen:= 4; {выясняем алгоритм шифрования} CryptGetKeyParam (SessionKey, KP_ALGID, @alg, @keyLen, 0); case alg of CALG_RC2: stream:= false; CALG_RC4: stream:= true; end; if not stream then {если шифр - блочный} begin //читаем и устанавливаем IV BlockRead (infile, keyLen, 4); BlockRead (infile, buf, keyLen); CryptSetKeyParam (SessionKey, KP_IV, @buf, 0); end; SaveDlg.Title:= 'Задайте имя файла для расшифрованных данных'; if SaveDlg.Execute then begin AssignFile (outfile, SaveDlg.FileName); rewrite (outfile, 1); while not eof (infile) do begin {собственно расшифровывание} BlockRead (infile, buf, 512, keyLen); CryptDecrypt (SessionKey, 0, eof (infile), 0, @buf, @keyLen); BlockWrite (outfile, buf, keyLen); end; CloseFile (outfile); end; CloseFile (infile); CryptDestroyKey (SessionKey); end; CryptReleaseContext (hProv, 0); end;


Содержание раздела