Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с CryptoDecrypt (Crypto API) 
V
    Опции темы
ShPROTT
  Дата 25.4.2006, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 25.4.2006

Репутация: нет
Всего: нет



Приветствую всех!
Пишу универсальный менеджер криптопровайдеров Windows.
Возникает ошибка NTE_BAD_DATA при вызове CryptDecrypt для блочного шифра,
а для поточного расшифрование происходит ни с первого раза, т.е. необходимо
функцию Decrypt вызывать несколько раз. 
Помогите кто-нибудь, горит курсовой проект!!!
ICQ#: 283-816-077 
[email protected]

Шифрую следующим образом:
Код

procedure Encrypt(in_,out_:TFileName;CPROV:CurrentPar;PassWD:String);
var inp_file,out_file:file;
    pbBuffer:PByte;
    dwBlockLen:DWORD;
    dwBufferLen:DWORD;
    dwCount:DWORD;
    hash: DWORD;
    hKey :DWORD;
begin
            CryptCreateHash(CPROV.cProvContext, CPROV.cAlg_HS.aiAlgid, 0, 0, @hash);
            CryptHashData(hash, @passWD, length(PassWD), 0);
            CryptDeriveKey(CPROV.cProvContext, CPROV.cAlg_EN.aiAlgid, hash, 0, @hkey);

            AssignFile(inp_file,in_);
            AssignFile(out_file,out_);
            Reset(inp_file,1);
            Rewrite(out_file,1);
            dwBlockLen:=1000 - 1000 mod ENCRYPT_BLOCK_SIZE;
            if AlgTypeToStr(CurPar.cAlg_EN.aiAlgid)<>'поточный' then
            dwBufferLen:=dwBlockLen+ENCRYPT_BLOCK_SIZE else
            dwBufferLen:=dwBlockLen;
            GetMem(pbBuffer,dwBufferLen);
            while not Eof(inp_file) do
              begin
              BlockRead(inp_file,pbBuffer^,dwBlockLen,dwCount);
              if CryptEncrypt(hkey,0,eof(inp_file),0,pbBuffer,@dwCount,dwBufferLen) then
              BlockWrite(out_file,pbBuffer^,dwCount) else
              ShowErrorMes(GetLastError);
              end;
             FreeMem(pbBuffer);
             CloseFile(inp_file);
             CloseFile(out_file);
             CryptDestroyKey(hkey);
             CryptDestroyHash(hash);

end;

Расшифрование:
 
Код

procedure Decrypt(in_,out_:TFileName;CPROV:CurrentPar;PassWD:String);
var inp_file,out_file:file;
    pbBuffer:PByte;
    dwBlockLen:DWORD;
    dwBufferLen:DWORD;
    dwCount:DWORD;
    hash: DWORD;
    hKey :DWORD;
begin
            CryptCreateHash(CPROV.cProvContext, CPROV.cAlg_HS.aiAlgid, 0, 0, @hash);
            CryptHashData(hash, @passWD, length(PassWD), 0);
            CryptDeriveKey(CPROV.cProvContext, CPROV.cAlg_EN.aiAlgid, hash, 0, @hkey);

            AssignFile(inp_file,in_);
            AssignFile(out_file,out_);
            Reset(inp_file,1);
            Rewrite(out_file,1);
            dwBlockLen:=1000 - 1000 mod ENCRYPT_BLOCK_SIZE;
            dwBufferLen:=dwBlockLen;
            GetMem(pbBuffer,dwBufferLen);
            while not Eof(inp_file) do
              begin
              BlockRead(inp_file,pbBuffer^,dwBlockLen,dwCount);
              if CryptDecrypt(hkey,0,eof(inp_file),0,pbBuffer,@dwCount) then
              BlockWrite(out_file,pbBuffer^,dwCount) else
              ShowErrorMes(GetLastError);
              end;
             FreeMem(pbBuffer);
             CloseFile(inp_file);
             CloseFile(out_file);
             CryptDestroyKey(hkey);
             CryptDestroyHash(hash);
end;
end.

 smile  smile  smile

 
PM MAIL   Вверх
Snowy
Дата 26.4.2006, 12:12 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Как-то не нравится мне этот код.
Вот. Я написал свой. Ему все равно - поточный или блочный алгоритм.
И работает культурно - со стримами.
Код
unit crypter;

interface

uses Windows, SysUtils, Classes, WinCrypt;

type
  TCrypter = class
  private
    hProv: HCRYPTPROV;   // криптопровайдер
    hSKey: HCRYPTKEY;    // сессионный ключ
    FAlg:  ALG_ID;       // алгоритм
    function FileOp(SrcFile, DstFile: string; en: boolean): boolean;
  public
    function EncryptFile(SrcFile, DstFile: string): boolean;
    {* Шифровать файл }
    function DecryptFile(SrcFile, DstFile: string): boolean;
    {* Расшифровать файл }
    procedure Encrypt(Buf: PByte; var BufLen: DWORD);
    {* Шифрует данные }
    procedure Decrypt(Buf: PByte; var BufLen: dword);
    {* Дешифрует данные }
    constructor Create(Alg: ALG_ID; pass: string);
    {* Конструктор. На входе алгоритм и ключ }
  end;

implementation

const BufSize = $10000;

constructor TCrypter.Create(Alg: ALG_ID; pass: string);
var
  hash: HCRYPTHASH;
begin
  inherited Create;
  FAlg := Alg;
  CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
  CryptHashData(hash, pointer(pass), length(pass), 0);
  CryptDeriveKey(hProv, Alg, hash, 0, @hSKey);
  CryptDestroyHash(hash);
end;

function TCrypter.FileOp(SrcFile, DstFile: string; en: boolean): boolean;
var
  fs, fd: TFileStream;
  p:      PByte;
  sz:     dword;
begin
  result := false;
  if not FileExists(SrcFile) then Exit;
  try fs := TFileStream.Create(SrcFile, fmOpenRead or fmShareDenyWrite);
    try fd := TFileStream.Create(DstFile, fmCreate or fmShareDenyWrite);
      try GetMem(p, BufSize);
        try
          repeat
            sz := BufSize; sz := fs.Read(p^, sz);
            if en then Encrypt(p, sz) else Decrypt(p,sz);
            fd.Write(p^, sz);
          until sz < BufSize;
          result := true;
        finally FreeMem(p, BufSize) end;
      finally fd.Free; end;
    finally fs.Free; end;
  except end;
end;

function TCrypter.EncryptFile(SrcFile, DstFile: string): boolean;
begin
  result := FileOp(SrcFile, DstFile, true);
end;

function TCrypter.DecryptFile(SrcFile, DstFile: string): boolean;
begin
  result := FileOp(SrcFile, DstFile, false);
end;

procedure TCrypter.Encrypt(Buf: PByte; var BufLen: DWORD);
begin
  if BufLen > 0 then
    AssErt(CryptEncrypt(hSKey, 0, true, 0, Buf, @BufLen, BufSize));
end;

procedure TCrypter.Decrypt(Buf: PByte; var BufLen: dword);
begin
  if BufLen > 0 then
    AssErt(CryptDecrypt(hSKey, 0, true, 0, Buf, @BufLen), 'Decrypt Error');
end;

end.


Пример использования:
Код
uses Crypter, WinCrypt;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TCrypter.Create(CALG_RC2, 'Top Secret') do
  begin
    if not EncryptFile('C:\1.txt', 'C:\1.enc') then
      ShowMessage('Encryption Error');
    Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  with TCrypter.Create(CALG_RC2, 'Top Secret') do
  begin
    if not DecryptFile('C:\1.enc', 'C:\1.txt') then
      ShowMessage('Decryption Error');
    Free;
  end;
end;


Добавлено @ 12:17 
Если кому-то нужен модуль WinCrypt. Приклеиваю. 

Присоединённый файл ( Кол-во скачиваний: 79 )
Присоединённый файл  Wincrypt.zip 4,00 Kb
PM MAIL   Вверх
ShPROTT
Дата 26.4.2006, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 25.4.2006

Репутация: нет
Всего: нет



Спасибо! Нужно попробовать! 
PM MAIL   Вверх
ShPROTT
  Дата 27.4.2006, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 25.4.2006

Репутация: нет
Всего: нет



ОТЛИЧНО! smile
Всё получилось!!!
Осталось сделать хэширование, подпись, её проверку и распределение ключей...
Уважаемый товарищ Snowy, Вам огромный респект!!!
Чувствую, я к Вам ещё обращусь!
  
PM MAIL   Вверх
Snowy
Дата 28.4.2006, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Всегда пожалуйста.
Заходите еще... 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1194 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.