Хеширование MD5 в Delphi 2009

В Borland delphi 7 и даже в delphi 2007 все работало, но в delphi 2009 он просто возвращает неправильный хеш!

Я использую скрипт wcrypt2 (http://pastebin.com/m2f015cfd)

Вы только посмотрите:

строка: "123456"

хеш:

Delphi 7: «e10adc3949ba59abbe56e057f20f883e» - настоящий хеш.
Delphi 2007: "e10adc3949ba59abbe56e057f20f883e" - тоже настоящий хеш. А также... Delphi 2009: "5fa285e1bebe0a6623e33afc04a1fbd5" - WTF ??

Я пробовал много сценариев md5, но delphi 2009 делает то же самое со всеми из них. Любая помощь? Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
13 968
7

Ответы 7

Возможно, вы преобразуете общую строку (которая в Delphi 2009 является UnicodeString) в PAnsiChar и передаете ее в хеш-функцию? Это не будет работать. Сначала вы должны преобразовать строку в AnsiString, а затем преобразовать ее в PAnsiChar, а-ля:

PAnsiChar(AnsiString('123456'))

Также попробуйте использовать RawByteString вместо AnsiString, как предлагает dmajkic. Избегайте использования UTF8String, поскольку это не AnsiString, и любые символы вне диапазона ASCII (0..127) могут быть переинтерпретированы в многобайтовые символы.

Вы проверили, правильно ли обновлена ​​ваша библиотека для D2009 и юникодификации? Я как бы сомневаюсь, что один и тот же код подойдет для D7 / D2007 и D2009 для такого рода вещей.

Очевидно, что ваша библиотека не поддерживает Unicode.

Преобразуйте свою строку в AnsiString, RawByteString или UTF8String, объявив временную строку AnsiString и назначив ей свою строку униода.

Обратите внимание: если вы используете символы, специфичные для Unicode, которые нельзя преобразовать в одну кодовую страницу, вам следует преобразовать свою строку в UTF8.

Затем вызовите MD5 (PAnsiChar (YourTempString)).

Убедитесь, что в вашей библиотеке есть объявления PWideChar или UNICODE, чтобы пропустить это.

Ваша библиотека не поддерживает Unicode. Просто передать ему AnsiString будет недостаточно, потому что он, вероятно, использует строки для хранения данных внутри.

Вы можете попробовать обновить эту библиотеку, подождать, пока автор обновит ее, или просто использовать MessageDigest_5.pas, который поставляется с Delphi 2009. Он находится в папке источник \ Win32 \ мыло \ wsdlimporter, которую вам нужно будет либо добавить в свой путь, либо явно включить в ваш проект.

Вот пример кода, использующего его в Delphi 2009:

uses Types, MessageDigest_5;

procedure TForm16.Edit1Change(Sender: TObject);
var
  MD5: IMD5;
begin
  MD5 := GetMD5;
  MD5.Init;
  MD5.Update(TByteDynArray(RawByteString(Edit1.Text)), Length(Edit1.Text));
  Edit2.Text := LowerCase(MD5.AsString);
end;

А вы в деле:

MD5(123456) = e10adc3949ba59abbe56e057f20f883e

Вы можете обернуть это простым вызовом функции, если хотите. Важно, чтобы вы выполняли преобразование в RawByteString перед преобразованием в TByteDynArray, поскольку преобразование RawByteString удаляет все лишние символы Unicode. Допустим, если редактирование содержит символы Unicode, вы можете получить неверные данные.

Имейте в виду, что GetMD5 возвращает интерфейс, поэтому он подсчитывается по ссылкам и т. д.

Счастливого Рождества!

Броски здесь полностью фальшивые. Вы не можете разумно преобразовать UnicodeString в RawByteString. И вы абсолютно не можете преобразовать RawByteString в байтовый массив. Этот ответ настолько ошибочен и проголосован за него так ошибочно, что его следует просто удалить. Правильное решение использует TEncoding.GetBytes.

David Heffernan 09.12.2014 10:22

В ответ Джима:

если мы изменим

MD5.Update (TByteDynArray (RawByteString (Edit1.Text)), Length (Edit1.Text));

к

MD5.Update (TByteDynArray (RawByteString (Edit1.Text)), Length (RawByteString (Edit1.Text)));

будет лучше поддерживать, пока существуют китайские иероглифы.

Прежде чем кто-то сможет прокомментировать алгоритмы хеширования, полезно иметь хотя бы фундаментальное понимание лежащих в основе концепций и принципов. Все ответы, которые до сих пор были сосредоточены на бесконечном приведении типов, полностью избыточны, но, что еще хуже, приведут к ненадежным результатам, если строка Юникода хешируется.

Первое, что вам нужно понять, это то, что алгоритмы хеширования и шифрования работают на байтовом уровне. Это означает, что им все равно, что вы хэшируете или шифруете. Вы можете хэшировать целые числа, символы, простой ASCII, полный юникод, байты, длинные слова и т. д. И т. Д. Алгоритм не заботится.

При работе со строками ЕДИНСТВЕННОЕ, что вы должны гарантировать, - это то, что внутренняя функция вашей библиотеки хеширования возвращает AnsiString в функции, которая выводит полученный вами хэш. Вот и все. Это все, что имеет значение.

Ваш фактический код для ВАШЕГО проекта может (и должен) быть основан на обычном вводе строки, который отображается в unicodestring в Delphi 2009. Вы не должны приводить какие-либо типы к ansistring или rawbytestring. Поступая таким образом, вы немедленно создаете неработающий хеш, если и когда пользователь пытается хешировать что-либо, выходящее за рамки набора символов ANSI. А в мире хеширования сломанный хеш одновременно и ненадежен, и небезопасен.

Спасибо за голос разума. +1.

mghie 10.04.2009 23:11

Если у вас wcrypt2.pas, воспользуйтесь этой функцией.

function md5ansi(const Input: AnsiString): AnsiString;
var
  hCryptProvider: HCRYPTPROV;
  hHash: HCRYPTHASH;
  bHash: array[0..$7f] of Byte;
  dwHashBytes: Cardinal;
  pbContent: PByte;
  i: Integer;
begin
  dwHashBytes := 16;
  pbContent := Pointer(PAnsiChar(Input));
  Result := '';

  if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT or CRYPT_MACHINE_KEYSET) then
  begin
    if CryptCreateHash(hCryptProvider, CALG_MD5, 0, 0, @hHash) then
    begin
      if CryptHashData(hHash, pbContent, Length(Input) * sizeof(AnsiChar), 0) then
      begin
        if CryptGetHashParam(hHash, HP_HASHVAL, @bHash[0], @dwHashBytes, 0) then
        begin
          for i := 0 to dwHashBytes - 1 do
          begin
            Result := Result + AnsiString(Format('%.2x', [bHash[i]]));
          end;
        end;
      end;
      CryptDestroyHash(hHash);
    end;
    CryptReleaseContext(hCryptProvider, 0);
  end;

  Result := AnsiString(AnsiLowerCase(String(Result)));
end;

@JW Ким, добро пожаловать в StackOverflow. Пожалуйста, уделите время чтению Часто задаваемые вопросы. Если у вас есть предыдущий опыт работы с форумами или новостными группами, вы заметите, что сайт работает по-другому. Вы отвечаете на довольно старый вопрос принятым ответом, поэтому он действителен, он не используется. Чтобы опубликовать исходный код, вы должны сделать отступ в 4 символа пробела, чтобы он выглядел как исходный код. :)

jachguate 28.12.2010 18:33

Другие вопросы по теме