Frxcrypt

mvbmvb Казань
отредактировано November 2009 Раздел: FastReport 4.0
Здравствуйте! Д2009, fr4_8_21_d12.
Пытаюсь сделать функции по шифрованию и сжатию файлов с использованием функций из модулей frxCrypt и frxGZip.
const
  CryptKey = ansistring('криптоключ');

function mvbDecryptFile(const FileName: string): string;
var fs: TFileStream;
    dst, src: TStringStream;
begin
     fs := TFileStream.Create(FileName, fmOpenRead);
     dst := TStringStream.Create;
     src := TStringStream.Create;
     try
       frxDecryptStream(fs, src, CryptKey);
       //src.CopyFrom(fs, fs.Size);
       src.Position := 0;
       frxDecompressStream(src, dst);
       Result := dst.DataString;
     finally
       dst.Free;
       src.Free;
       fs.Free;
     end;
end;

function mvbEncryptFile(const Data, FileName: string): boolean;
var fs: TFileStream;
    src, dst: TStringStream;
begin
     fs := TFileStream.Create(FileName, fmCreate);
     src := TStringStream.Create;
     dst := TStringStream.Create;
     try
       src.WriteString(Data);
       src.Position := 0;
       frxCompressStream(src, dst, gzMax, ExtractFileName(FileName));
       frxCryptStream(dst, fs, CryptKey);
       {dst.Position := 0;
       fs.CopyFrom(dst, dst.Size);}
     finally
       src.Free;
       dst.Free;
       fs.Free;
     end;
     Result := FileExists(FileName);
end;
Если исключить криптование (и раскомментировать прямое копирование данных), то все работает, если делать как хочется (выше) - то после расшифровки вылетает "data error" на frxDecompressStream(src, dst). Делал наоборот - сжатие, потом криптование - работает как надо, но коэффициент сжатия при этом практически нулевой. Подскажите, что я не так делаю?

Комментарии

  • mvbmvb Казань
    отредактировано 05:17
    в функции frxDecompressStream строка
    if (header[0] = $1f) and (header[1] = $8b) and (header[2] = $8) then
    
    не выполняется, т.е. имеем на входе некорректно дешифрованный текст.
  • отредактировано 05:17
    логичнее было бы сначала сжимать , а потом криптовать. Т.к. после криптования сжатие будет уже заметно хуже и экономия на памяти при криптовании хоть и небольшая :)

    Ошибка у Вас в типе, String начиная с Delphi 2009 по умолчанию 2-х байтовый WideString. TStringStream доже по умолчанию создает 2-х байтовый стринг стрим.


    нужно сделать так:
    1. Заменить у mvbDecryptFile возвращаемый тип на AnsiString и у mvbEncryptFile Data тоже AnsiString.
    2. TStringStream нужно создавать так TStringStream.Create('', TEncoding.ASCII) или так TStringStream.Create('', TEncoding.UTF8) , в зависимости от требований.
  • mvbmvb Казань
    отредактировано 05:17
    написал: »
    логичнее было бы сначала сжимать , а потом криптовать. Т.к. после криптования сжатие будет уже заметно хуже и экономия на памяти при криптовании хоть и небольшая :)
    у меня вообще-то так и есть:
           frxCompressStream(src, dst, gzMax, ExtractFileName(FileName));
           frxCryptStream(dst, fs, CryptKey);
    
    я даже писал, что
    написал: »
    Делал наоборот - сжатие, потом криптование - работает как надо, но коэффициент сжатия при этом практически нулевой.
    написал: »
    Ошибка у Вас в типе, String начиная с Delphi 2009 по умолчанию 2-х байтовый WideString. TStringStream доже по умолчанию создает 2-х байтовый стринг стрим.
    нужно сделать так:
    1. Заменить у mvbDecryptFile возвращаемый тип на AnsiString и у mvbEncryptFile Data тоже AnsiString.
    2. TStringStream нужно создавать так TStringStream.Create('', TEncoding.ASCII) или так TStringStream.Create('', TEncoding.UTF8) , в зависимости от требований.
    вот как сделал:
    function mvbDecryptFile(const FileName: string): string;
    var fs: TFileStream;
        dst, src: TStringStream;
    begin
         fs := TFileStream.Create(FileName, fmOpenRead);
         dst := TStringStream.Create('', TEncoding.ASCII);
         src := TStringStream.Create('', TEncoding.ASCII);
         try
           frxDecryptStream(fs, src, CryptKey);
           src.Position := 0;
           frxDecompressStream(src, dst);
           Result := dst.DataString;
         finally
           dst.Free;
           src.Free;
           fs.Free;
         end;
    end;
    
    function mvbEncryptFile(const Data, FileName: string): boolean;
    var fs: TFileStream;
        src, dst: TStringStream;
        s: AnsiString;
    begin
         s := _UnicodeToAnsi(Data, RUSSIAN_CHARSET, CP_ACP);
         fs := TFileStream.Create(FileName, fmCreate);
         src := TStringStream.Create(s, TEncoding.ASCII);
         //src := TStringStream.Create(AnsiString(Data), TEncoding.ASCII);
         dst := TStringStream.Create('', TEncoding.ASCII);
         try
           src.Position := 0;
           frxCompressStream(src, dst, gzMax, ExtractFileName(FileName));
           frxCryptStream(dst, fs, CryptKey);
         finally
           src.Free;
           dst.Free;
           fs.Free;
         end;
         Result := FileExists(FileName);
    end;
    
    Все ровно то же самое....
    Функция _UnicodeToAnsi из вашего же модуля frxUnicodeUtils. Закомментирован еще один нерабочий вариант.
  • отредактировано 05:17
    И опять не правильно ....

    function mvbDecryptFile(const FileName: string): string;

    Тип должен быть AnsiString ... криптование возвращает набор байтов , а Вы его не явно конвертируете в юникод.
  • mvbmvb Казань
    отредактировано 05:17
    написал: »
    Тип должен быть AnsiString ... криптование возвращает набор байтов , а Вы его не явно конвертируете в юникод.
    то, о чем вы говорите, влияет только на результат в строке
    Result := dst.DataString;
    
    , но мы пока до нее добраться не можем, т.к. данные ломаются уже на строке:
    frxDecryptStream(fs, src, CryptKey);
    
    Вернее, эта строка возвращает неверные данные, на которых затем спотыкается декомпрессор:
    frxDecompressStream(src, dst);
    
  • отредактировано 05:17
    Сам писал как правильней делать, но забыл, что используем блочный алгоритм криптования :
    Т.е. чтобы заполнить блок до конца добавляются пробелы, а после декриптования они убиваются вместе со спец символами.
    Можно конечно сделать свой аналог trim без удаления управляющих символов, только нет гарантии, что стрим не заканчивался пробелом $20.

    Поэтому придется делать все наоборот: криптовать , а потом сжимать.
    Ну и конечно правильно конвертировать, т.е. если нужно криптовать строку юникода, конвертировать ее в utf8.

    const
      CryptKey = ansistring('криптоключ');
    
    function mvbDecryptFile(const FileName: string): string;
    var fs: TFileStream;
        dst, src: TStringStream;
        Sig: array[0..1] of Byte;
    begin
         fs := TFileStream.Create(FileName, fmOpenRead);
         dst := TStringStream.Create('', TEncoding.UTF8);
         src := TStringStream.Create('', TEncoding.ASCII);
         try
           frxDecompressStream(fs, src);
           src.Position := 0;
           frxDecryptStream(src, dst, CryptKey);
           Result := dst.DataString;
         finally
           dst.Free;
           src.Free;
           fs.Free;
         end;
    end;
    
    function mvbEncryptFile(const Data, FileName: string): boolean;
    var fs: TFileStream;
        src, dst: TStringStream;
        s: AnsiString;
    
    begin
         fs := TFileStream.Create(FileName, fmCreate);
         src := TStringStream.Create(Data, TEncoding.UTF8);
         dst := TStringStream.Create('', TEncoding.ASCII);
         try
           src.Position := 0;
           frxCryptStream(src, dst, CryptKey);
           frxCompressStream(dst, fs, gzMax, ExtractFileName(FileName));
    
         finally
           src.Free;
           dst.Free;
           fs.Free;
         end;
         Result := FileExists(FileName);
    end;
    
  • mvbmvb Казань
    отредактировано 05:17
    если я вас правильно понял, то произвольная строка, зашифрованная с пом. frxCryptStream не всегда правильно расшифровывается при пом. frxDecryptStream?
  • mvbmvb Казань
    отредактировано 05:17
    ответ будет?
  • отредактировано November 2009
    Расшифрует всегда, а вот после, для приведения строки в исходный вид(удаление пробелов из не заполненного блока), удаляются все символы <=$20 через trim.
  • mvbmvb Казань
    отредактировано 05:17
    вы имеете ввиду этот trim?
    result:= AnsiString(trim(String(sres)));
    
    из rc_Crypt.DeCryptString
  • отредактировано 05:17
    mvb написал: »
    вы имеете ввиду этот trim?
    result:= AnsiString(trim(String(sres)));
    
    из rc_Crypt.DeCryptString

    Да, именно этот.
    Лучший вариант это записывать размер исходной строки в криптованный стрим, но алгоритм не наш и пока менять его не хочется.

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.