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;