На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
  
> Алгоритм АЕS шифрование, расшифрование , Алгоритм АЕS шифрование, расшифрование
    Подскажите пожалуйста кто сталкивался, если необходимо шифрование алгоритмом AES с помощью CryptoAPI, где именно нужно указывать, что шифрование будет именно этим алгоритмом (необходимо определенный криптопровайдер или определенный тип?)
    ExpandedWrap disabled
      CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)

    Заранее очень благодарен!
    Сообщение отредактировано: mawa -
      насколько я помню то по умолчанию в винде нет провайдера который работает с AES
        Цитата mawa @
        где именно нужно указывать, что шифрование будет именно этим алгоритмом (необходимо определенный криптопровайдер или определенный тип?)

        Конкретный алгоритм указывается при создании ключа шифрования, а в CryptAcquireContext нужно указывать имя\тип провайдера, поддерживающего данный алгоритм. Судя по мсдн, AES поддерживается в WinXP и выше провайдером: тип = PROV_RSA_AES, имя = MS_ENH_RSA_AES_PROV
          Спасибо!

          Добавлено
          Я обращаюсь через библиотеку wcrypt2.pas, но в ней нет - PROV_RSA_AES, имеется PROV_RSA_FULL и др. Что делать?
            Объяви сам эту константу. Она равна 24
              ExpandedWrap disabled
                  public
                    { Public declarations }
                    hProv: HCRYPTPROV;
                    key: HCRYPTKEY;
                    encrypt: boolean;
                  end;
                ....
                var hProv: HCRYPTPROV;
                    hash: HCRYPTHASH;
                    key: HCRYPTKEY;
                    data: PByte;
                    l: DWORD;
                    fl:boolean;
                    i:integer;
                    err,login,cript_rez: string;
                    cript_temp_1:array[0..65535] of char;
                    cript_temp_2:string[255];
                Const PROV_RSA_AES=24;
                ....
                {получаем контекст криптопровайдера}
                CryptAcquireContext(@hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
                 
                {создаем хеш-объект}
                CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
                 
                {хешируем пароль}
                CryptHashData(hash, @password[1], length(password), 0);
                 
                {создаем ключ на основании пароля для потокового шифра RC4}
                CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key);
                 
                {уничтожаем хеш-объект}
                CryptDestroyHash(hash);
                 
                {выделяем место для буфера}
                    GetMem(data, 512);
                      {шифруем данные}
                      login:=text; //данные
                      fl:=true;
                      l:=length(login);
                      for i:=1 to length(login) do
                      begin
                      data^:=ord(login[i]);
                      CryptEncrypt(key, 0, fl, 0, data, @l, l);
                 
                      cript_temp_1[i]:=chr(data^);
                      cript_temp_2[i]:=cript_temp_1[i];
                      login[i]:=cript_temp_2[i];   //рез-т шифрования
                    end;
                    {освобождаем место и закрываем файлы}
                    FreeMem(data, 512);
                    {освобождаем контекст криптопровайдера}
                    CryptReleaseContext(hProv, 0);

              Данный код реализован был для шифра RC4, а как для AES сделать? :wall:

              Добавлено
              Необходимо указать алгоритм - AES или CALG_AES, а там нет что делать?
              ExpandedWrap disabled
                CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key)
                Цитата mawa @
                а там нет что делать?


                Прогуляться по MSDN. Тебе выше ссылку дали. Вот я кликаю по ней, в ней есть еще одна, которая ведет сюда:
                http://msdn.microsoft.com/en-us/library/aa375545(VS.85).aspx
                Теперь твоя очередь покликать ;)

                ЗЫ: Если снова константа не будет объявлена - объявляй сам. Значение узнать можно в гугле. По запросу "define+имя_константы" находится код, по которому значение и узнается.
                  ExpandedWrap disabled
                      CALG_AES_256      = $6610;


                  Список
                  Сообщение отредактировано: CodeMonkey -
                    Спасибо!
                    А вот когда зашифровываю текст, то выдается ошибка 'Unknown error', в чем может быть причина?
                    ExpandedWrap disabled
                      {получаем контекст криптопровайдера}
                      CryptAcquireContext(@hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
                       {создаем хеш-объект}
                      CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
                        {хешируем пароль}
                      CryptHashData(hash, @password[1], length(password), 0);
                        {создаем ключ на основании пароля для AES_256}
                      CryptDeriveKey(hProv,CALG_AES_256,hash,0,@key);
                      ..
                      {выделяем место для буфера}
                          GetMem(data, 512);
                          {шифруем данные}
                            login:=text; //данные
                            fl:=true;
                            l:=length(login);
                            for i:=1 to length(login) do
                            begin
                            data^:=ord(login[i]);
                            if not CryptEncrypt(key, 0, fl, 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 CryptEncrypt: '+err,
                                               mtError, [mbOK], 0);
                                  exit;
                                  end;
                            cript_temp_1[i]:=chr(data^);
                            cript_temp_2[i]:=cript_temp_1[i];
                            login[i]:=cript_temp_2[i];   //рез-т шифрования
                      Попробуй получить описание ошибки через FormatMessage
                      ExpandedWrap disabled
                        var
                          e:cardinal;
                          mbuf:array[0..511] of char;
                        begin
                          ...
                          e:=GetLastError;
                          case e of
                          ...
                          else
                          begin
                            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,nil,e,0,mbuf,sizeof(mbuf),nil);
                            err:=IntToStr(e)+#13#10+mbuf;
                          end;
                        ExpandedWrap disabled
                          else err := 'Unknown error';

                        заменить на
                        ExpandedWrap disabled
                          else RaiseLastOSError;
                          ERROR CRYPTENCRYPT -- Unknown error

                          Добавлено
                          CodeMonkey
                          System Error. Code:234.
                          Имеются дополнительные данные. Process stopped/ Use step or run to continue/

                          Добавлено
                          leo
                          Error of CryptEncrypt : 21
                          Устройство не готово
                          Сообщение отредактировано: mawa -
                            Цитата mawa @
                            Имеются дополнительные данные.

                            Значит 512 - мало.

                            Добавлено
                            По идее, надо как-то так:

                            ExpandedWrap disabled
                              var
                                login: String;
                                X, Y: Integer;
                              ...
                                // вход: login - данные для шифрования
                               
                                // Шаг 1: определяем, сколько надо байт для хранения зашифрованного текста
                                X := Length(login);
                                if not CryptEncrypt(key, 0, True, 0, Pointer(login), X, Length(login)) then
                                  if GetLastError <> ERROR_MORE_DATA then
                                    RaiseLastOSError;
                                // Шаг 2: выделили буфер (уже не 512, а ровно, сколько надо)
                                Y := Length(login);
                                SetLength(login, X);
                                // Шаг 3: шифрование
                                if not CryptEncrypt(key, 0, True, 0, Pointer(login), Y, Length(login)) then
                                  RaiseLastOSError;
                                SetLength(login, Y);
                               
                                // выход: login - зашифрованные данные


                            Писал на коленке, могут быть описки.
                              Шифрование вроде работает, по крайней мере получается билиберда, но нужно было :
                              ExpandedWrap disabled
                                if not CryptEncrypt(key, 0, True, 0, Pointer(login), @X, Length(login)) then        //@X

                              А вот на расшифровывание ругается, пишит плохие данные :
                              ExpandedWrap disabled
                                  login:=z_text;
                                 
                                  X := Length(login);
                                  if not CryptDecrypt(key, 0, True, 0, Pointer(login), @X) then
                                    if GetLastError <> ERROR_MORE_DATA then
                                      RaiseLastOSError;
                                 
                                  Y := Length(login);
                                  SetLength(login, X);
                                 
                                  if not CryptDecrypt(key, 0, True, 0, Pointer(login), @Y) then
                                    RaiseLastOSError;
                                  SetLength(login, Y);
                              Сообщение отредактировано: mawa -
                                А дешифровка делается в один шаг. Не надо узнавать размер буфера: исходный текст всегда меньше размером. А вы в своём коде просто откусили от зашифрованного текста кусок и удивляетесь, а чего ж это он ругается на неполные данные.
                                  Шифровку тоже надо бы подправить, т.к. код #13 предполагает, что длина зашифрованного текста всегда будет больше длины исходного. Лучше сделать так:
                                  ExpandedWrap disabled
                                      X:=Length(login);
                                      if CryptEncrypt(key, 0, True, 0, nil, @X, X) then //при pbData=Nil просто в X возвращается требуемая длина
                                      begin
                                        if X > Length(login) then
                                          SetLength(login, X)
                                        else
                                          UniqueString(login);
                                        if not CryptEncrypt(key, 0, True, 0, Pointer(login), @X, X) then
                                          RaiseLastOSError
                                        else
                                        if X <> Length(login) then SetLength(login, X);
                                      end
                                      else
                                        RaiseLastOSError;
                                  Сообщение отредактировано: leo -
                                    CodeMonkey Подскажи запутался все равно ругается!
                                    ExpandedWrap disabled
                                      login:=z_text;
                                      X := Length(login);
                                      if not CryptDecrypt(key, 0, True, 0, Pointer(login), @X) then
                                         RaiseLastOSError;


                                    Добавлено
                                    Спасибо!
                                    Расшифровывает, но только в конце слова не понятные символы доставляет!?
                                      Цитата mawa @
                                      Расшифровывает, но только в конце слова не понятные символы доставляет!?

                                      При дешифровке длина текста уменьшается, добавь коррекцию длины:
                                      ExpandedWrap disabled
                                        if not CryptDecrypt(key, 0, True, 0, Pointer(login), @X) then
                                           RaiseLastOSError
                                        else
                                        if X <> length(login) then SetLength(login,X);
                                        _________________________
                                        Пример:
                                        Исходное : qweqweqweqwe27@

                                        Расшифрованное :
                                        qweqweqweqwe27@

                                        Добавлено
                                        Все работает !!!!
                                        leo Спасибо Большое !!!!!!!! respect!
                                          Цитата mawa @
                                          login:=z_text;

                                          Учти, что при этом после CryptDecrypt строка z_text тоже изменится. Чтобы не изменялась нужно либо добавить
                                          UniqueString(login);
                                          либо сразу вместо присваивания сделать
                                          SetString(login,pChar(z_text),Length(z_text));
                                            Вопрос, если пароль не правильный выдает плохие данные, тогда необходимо использовать связку : try - exsept ?
                                              Да, если нужно вывести сообщение или еще что-то сделать.
                                              Плюс закрытие всех хэндлов лучше делать в try\finally

                                              PS: странно, что у тебя FormatMessage не ту ошибку выдал, т.к. RaiseLastOSError использует тот же механизм
                                              Сообщение отредактировано: leo -
                                                leo
                                                А зачем сохранять
                                                ExpandedWrap disabled
                                                  login:=z_text;


                                                Все итак нормально работает?
                                                  Работать то работает, но при присваивании login:=z_text может копироваться только указатель на строку, в итоге login и z_text будут указывать на один и тот же текст и соотв-но изменение login в Decript приведет также и к изменению z_text. Если это не важно, то тогда вроде и незачем присвоение login:=z_text делать - можно сразу с z_text работать. Если же z_text не должна меняться, то нужно сделать UniqueString(login)

                                                  Добавлено
                                                  Кстати вместо FormatMessage можно использовать SysErrorMessage из SysUtils
                                                  ExpandedWrap disabled
                                                      e:=GetLastError;
                                                      ShowMessage('Error '+IntToStr(e)+'. '+SysErrorMessage(e));

                                                  PS: Это если вместо генерации исключения просто выдавать сообщение об ошибке
                                                  Сообщение отредактировано: leo -
                                                    leo спасибо за помощь! Очень помоГ!
                                                      mawa, тебе тоже спс - за интересный вопрос ;)
                                                        Цитата leo @
                                                        PS: странно, что у тебя FormatMessage не ту ошибку выдал, т.к. RaiseLastOSError использует тот же механизм

                                                        Я не удивлюсь, если авто вопроса напутал и с вызовом FormatMessage - поэтому FormatMessage возвращал не столько описание ошибки, сколько ошибку при вызове себя или что-то вроде этого. Похоже, автор вопроса больше действует методом научного тыка, слабо понимая, что же вообще он пишет.
                                                          CodeMonkey
                                                          А где я напутал - вызов FormatMessage?
                                                          Я в прошлом году делал лабу по алгоритму RC4, там все было ок, и литературы хватало. А вот с AES, сам не справился!
                                                          Еще раз спасибо!
                                                            А почему некоторые слова шифруется, но не расшифровываются (p.s. пароль ввожу верно)? Пишит - плохие данные!
                                                            Шифрование
                                                            ExpandedWrap disabled
                                                                login:=text;
                                                                // вход: login - данные для шифрования
                                                                // Шаг 1: определяем, сколько надо байт для хранения зашифрованного текста
                                                                X := Length(login);
                                                                if not CryptEncrypt(key, 0, True, 0, Pointer(login), @X, Length(login)) then
                                                                  if GetLastError <> ERROR_MORE_DATA then
                                                                    RaiseLastOSError;
                                                                // Шаг 2: выделили буфер (уже не 512, а ровно, сколько надо)
                                                                Y := Length(login);
                                                                SetLength(login, X);
                                                                // Шаг 3: шифрование
                                                                if not CryptEncrypt(key, 0, True, 0, Pointer(login), @Y, Length(login)) then
                                                                  RaiseLastOSError;
                                                                SetLength(login, Y);
                                                                {освобождаем контекст криптопровайдера}
                                                                CryptReleaseContext(hProv, 0);

                                                            Расшифрование
                                                            ExpandedWrap disabled
                                                                login:=z_text;
                                                                X := Length(login);
                                                                if not CryptDecrypt(key, 0, True, 0, Pointer(login), @X) then
                                                                 RaiseLastOSError
                                                                  else
                                                                if X <> length(login) then
                                                                 SetLength(login,X);
                                                                {освобождаем контекст криптопровайдера}
                                                                CryptReleaseContext(hProv, 0);
                                                              Частный случай:
                                                              Проблема в том что когда шифруется слово получается длина 32 символа, затем это слово записуется в файлик. А при расшифровании считывается из файлика, но считывается 8 символов!! Что делать?
                                                              Зашифр.
                                                              ExpandedWrap disabled
                                                                //созд.файла
                                                                  AssignFile(f,Edit3.Text+'.txt');
                                                                  Rewrite(f);
                                                                  CloseFile(f);
                                                                  //открытие на до запись
                                                                  AssignFile(f,Edit3.Text+'.txt');
                                                                  Append(f);
                                                                  //шифрование
                                                                  login:=login+'|@@|'+pass;
                                                                  str:=Zawufrovat(password,login);
                                                                  writeln(f,str);
                                                                  CloseFile(f);

                                                              расшифр
                                                              ExpandedWrap disabled
                                                                //открытие файла
                                                                  t:=OpenDialog1.FileName;
                                                                  try
                                                                    AssignFile(f,t);
                                                                    reset(f);
                                                                  except;
                                                                   ShowMessage('Ошибка чтения файла !');
                                                                   Exit;
                                                                  end;
                                                                  //читаем логин+пароль+конст
                                                                  readln(f,str);
                                                                  ShowMessage(IntToStr(length(str))+'  '+str[length(str)]);
                                                                  password:=MaskEdit1.Text+p_const;
                                                                  //расшифрование
                                                                  try
                                                                    str:=Raswufrovat(password,str);
                                                                  except;
                                                                   ShowMessage('Не верный пароль 1!');
                                                                   memo2.Lines.Add(password);
                                                                   Exit;
                                                                  end;
                                                              Сообщение отредактировано: mawa -
                                                                Писать и читать файл как двоичный.
                                                                  Цитата mawa @
                                                                  А где я напутал - вызов FormatMessage?

                                                                  Видимо вызвал GetLastError повторно после вызова другой функции (например RaiseLastOSError или ShowMessage), хотя в #10 я тебе показывал как надо делать - вызвать один раз сразу после ошибки и сохранить значение в переменной для последующих манипуляций.

                                                                  Цитата mawa @
                                                                  Проблема в том что когда шифруется слово получается длина 32 символа, затем это слово записуется в файлик. А при расшифровании считывается из файлика, но считывается 8 символов!! Что делать?

                                                                  Мда, чудак ты, брат ;)
                                                                  С чего ты взял, что после шифрования твой текст останется вообще читабельным текстом, да еще и однострочным. Все стандартные алгоритмы шифрования - двоичные, а не символьные, поэтому в результате шифрования в строке могут оказаться служебные символы, например перевода строки $13, $10 и даже $0 - признак конца текста. Поэтому записывать\читать зашифрованные данные нужно в двоичный файл, а не в текстовый
                                                                  ExpandedWrap disabled
                                                                    var
                                                                      f:file;
                                                                    begin
                                                                      ...
                                                                      AssignFile(f,FileName);
                                                                      //запись строки str в файл
                                                                      try
                                                                        rewrite(f,1);
                                                                        blockwrite(f,str[1],Length(str));
                                                                      finally
                                                                        CloseFile(f);
                                                                      end;
                                                                      ...
                                                                      //чтение строки str из файла
                                                                      try
                                                                        reset(f,1);
                                                                        SetLength(str,FileSize(f)); //задаем размер строки = размеру файла
                                                                        blockread(f,str[1],Length(str)); //читаем весь файл
                                                                      finally
                                                                        CloseFile(f);
                                                                      end;


                                                                  Добавлено
                                                                  mawa
                                                                  И еще, несмотря на мое замечание #16, ты продолжаешь использовать вариант шифрования #29, предполагающий что длина зашифрованного текста всегда больше исходной. Ты уверен, что это так ? Я не уверен. Ясно, что AES блочный шифр, поэтому длина входного текста выравнивается вверх на 16 или 32 байта. Но если длина твоего login уже равна 16 или 32, то длина может и не измениться и в итоге алгоритм #29 зашифрует строку дважды.
                                                                  Правда я в #16 тоже накосячил с длинами, поэтому правильный вариант должен быть такой:
                                                                  ExpandedWrap disabled
                                                                      X:=Length(login);
                                                                      if CryptEncrypt(key, 0, True, 0, nil, @X, X) then //при pbData=Nil просто в X возвращается требуемая длина
                                                                      begin
                                                                        Y:=Length(login);
                                                                        if X > Y then
                                                                          SetLength(login, X)
                                                                        else
                                                                          UniqueString(login);
                                                                        if not CryptEncrypt(key, 0, True, 0, Pointer(login), @Y, X) then
                                                                          RaiseLastOSError
                                                                        else
                                                                        if Y <> Length(login) then SetLength(login, Y);
                                                                      end
                                                                      else
                                                                        RaiseLastOSError;
                                                                  Сообщение отредактировано: leo -
                                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                  0 пользователей:


                                                                  Рейтинг@Mail.ru
                                                                  [ Script execution time: 0,0832 ]   [ 16 queries used ]   [ Generated: 30.07.25, 00:21 GMT ]