Хобрук: Ваш путь к мастерству в программировании

Расшифровать строку в C #, зашифрованную в PHP (Blowfish)

Я изо всех сил пытаюсь расшифровать некоторые значения на C #, зашифрованные в PHP. Шифрование в PHP выполняется следующим образом:

function encrypt($pure_string, $encryption_key) {
  $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  $iv = 'fÔdñá1f¦';
  $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
  $encrypted_string = base64_encode($encrypted_string);
  return $encrypted_string;
}

Поскольку режим ECB используется IV, вероятно, он не используется, но все же это не помогает. Самая большая проблема заключается в том, что документация PHP настолько бедна и не указывает, какую кодировку используют функции! Передаваемая строка имеет разные байтовые значения в зависимости от кодировки, и в конечном итоге шифрование (в данном случае Blowfish) имеет дело с байтами.

Не зная кодировки, я просто пробую разные кодировки в своем коде C #, но безуспешно. Где-то я читал, что PHP использует внутреннюю кодировку "iso-8859-1", но даже при этом не работает.

Кому-нибудь удалось расшифровать на C # какое-то значение, зашифрованное в PHP с помощью глупой функции mcrypt_encrypt ()?

Обновить

Я сделал пример на PHP. Код:

define("ENCRYPTION_KEY", "1234asdf");
define("IV", "1#^ÊÁñÔ0");

$clearText = "abc";

function encrypt($pure_string, $encryption_key, $iv) {
  $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
  $encrypted_string = base64_encode($encrypted_string);
  return $encrypted_string;
}

$encrypted_string = encrypt($clearText, ENCRYPTION_KEY, IV);

echo "Key:" . ENCRYPTION_KEY . "<br />";
echo "IV:" . IV . "<br />";
echo "Clear Text:" . $clearText . "<br />";
echo "Encrypted Text:" . $encrypted_string . "<br />";

и результат:

Key:1234asdf
IV:1#^ÊÁñÔ0
Clear Text:abc
Encrypted Text:OiZ6QIdhXYk=

Также я подтвердил, что IV не используется, любое значение, которое я передаю, будет таким же.


  • Поскольку mcrypt устарел из-за того, что он был удален в PHP 7.2, я бы, вероятно, отказался от этого и начал бы заново ... 08.11.2017
  • Похоже, эта ветка могла бы вам помочь! stackoverflow.com/questions/18681526/php-mcrypt-encrypt -в сети 08.11.2017
  • Не могли бы вы добавить полный пример (зашифрованный текст в формате base64, пароль и исходный простой текст)? 08.11.2017
  • Многие люди добились успеха - я вижу варианты этого вопроса, по крайней мере, пару раз в неделю (не специально). 08.11.2017
  • @ CD001 У меня нет выбора, что используется на стороне PHP. Я могу контролировать только сторону C # 09.11.2017
  • @ZarX, который занимается шифрованием на C #, аналогично PHP. Я нашел вот этот stackoverflow.com/questions/4329260/, который может помочь (хотя это считается само собой разумеющимся, что кодировка PHP в UTF8). Все различные примеры не решают сути проблемы, а именно, какую кодировку использует PHP? 09.11.2017
  • @Michael У меня есть несколько примеров, но они с настоящим ключом, поэтому я не могу им поделиться. 09.11.2017
  • @Michael Затем запустите php-функцию с выбранным вами ключом, чтобы создать образец, которым вы можете поделиться. Без выборочных данных я (и, возможно, другие тоже) ничего не могу для вас сделать ... 09.11.2017
  • @Michael Обновил вопрос, включив в него тест, который я сделал на PHP. 09.11.2017
  • Лучше не использовать PHP mcrypt, это заброшенное программное обеспечение, не обновлялось годами и не поддерживает стандартное заполнение PKCS # 7 (урожденное PKCS # 5), только нестандартное нулевое заполнение, которое даже не может использоваться с двоичным кодом. данные. mcrypt имеет много выдающихся ошибок, относящихся к 2003 году. Расширение mcrypt устарело и будет удалено в PHP 7.2. Вместо этого рассмотрите возможность использования defuse или RNCryptor, они предоставляют полное решение, поддерживаются и являются правильными. 09.11.2017
  • @zaph Как я уже сказал, у меня нет контроля над частью PHP 09.11.2017

Ответы:


1

Что ж, проблема в вашем случае не в части дешифрования blowfish в C #, а в части шифрования в php. И нет, речь идет не об использовании mcrypt_encrypt, это ошибка вызывать utf8_encode для уже закодированной строки utf8 ...

Созданная мной функция дешифрования использует BouncyCastle. Есть две зашифрованные строки, первая была создана с помощью функции php, которую вы опубликовали, для второй я удалил вызов utf8_encode внутри mbcrypt_encrypt.

В первом примере используется (плохая) строка php_utf8_encoded, нам нужно преобразовать расшифрованный массив байтов туда и обратно, чтобы получить правильный результат.

Отладьте второй вызов функции дешифрования C # и посмотрите на результат первого str1, созданного Encoding.UTF8.GetBytes. Это правильно, без возвратно-поступательного преобразования кодировки.

public static string BlowfishDecrypt(string encrypted, string key)
{
    var cipher = new BufferedBlockCipher(new BlowfishEngine());
    var k = new KeyParameter(Encoding.UTF8.GetBytes(key));
    cipher.Init(false, k);

    var input = Convert.FromBase64String(encrypted);
    var length = cipher.GetOutputSize(input.Length);
    var block = new byte[length];
    var len = cipher.ProcessBytes(input, 0, input.Length, block, 0);
    var output = cipher.DoFinal(block, len);

    // dont know how we get the real length of the content here... but this will do it. But I am sure there is a better way...
    var idx = Array.IndexOf(block, (byte)0);
    var str1 = Encoding.UTF8.GetString(block, 0, idx);
    var raw1 = Encoding.GetEncoding("iso-8859-1").GetBytes(str1);
    var str2 = Encoding.UTF8.GetString(raw1);

    return str2;
}

static string original = "@€~>|";
static string encrypted_with_utf8_encode = "7+XyF+QGcA8lz5AQlLf1FA==";
static string encrypted_without = "3oWsAOEF+Kc=";
static string key = "t0ps3cr3t";

public static void Main()
{
    var decrypted1 = BlowfishDecrypt(encrypted_with_utf8_encode, key);
    var decrypted2 = BlowfishDecrypt(encrypted_without, key);
    var same = original.Equals(decrypted1);
    Debugger.Break();
}
09.11.2017
  • Собственно вызов utf8_encode () ничего не меняет. Я протестировал это на PHP, и результат был таким же, как с этим вызовом, так и без него. И, как я уже сказал, я НЕ контролирую часть php. 10.11.2017
  • @Albert Что ж, в моей тестовой среде с удалением utf8_encode я смог расшифровать данные без этого танца кодирования (utf8 - ›iso8859-1 -› utf8). Это будет иметь эффект только в том случае, если данные для шифрования содержат более высокие символы, такие как знак евро «€» в моем примере. И да, я знаю, что вы НЕ контролируете часть php (вы говорили не раз;)), я только хотел показать, что это не ваша вина или проблема с криптобиблиотекой, которая расшифровывает данные так сложно, поскольку процесс шифрования мог быть лучше ... 10.11.2017
  • Это не моя вина, но мне пришлось решать вопрос. Согласитесь, что шифрование могло быть лучше, но также верно и то, что некоторые из библиотек, которые я пробовал, плохи и имеют проблемы (по крайней мере, они неправильно используют строки в криптографических библиотеках). 10.11.2017
  • В качестве пояснения (что в моем ответе ниже): - Будьте осторожны с библиотекой, которую вы выбираете. Я использовал github.com/b1thunt3r/blowfish-csharp - если библиотека работает напрямую со строками это наверное плохой. В любом случае используйте только перегрузки, которые работают с байтами. - Имея дело с разными платформами, попытайтесь убедить другую сторону использовать кодировку base64. 10.11.2017

  • 2

    В конце концов удалось это сделать. Несколько указателей:

    • Некоторые библиотеки Blowfish на C # плохо реализованы. Правильно работал https://github.com/b1thunt3r/blowfish-csharp.

    • Никогда не используйте методы, которые напрямую работают со строками. Это глупо в первую очередь предлагать в любой библиотеке (даже в той, что выше, есть перегрузки, которые работают со строками, и она «предполагает», что строки находятся в Юникоде!)

    • Имея дело с разными платформами, попробуйте убедить другую сторону использовать кодировку base64.

    В конце концов, я поражен тем, почему так много разработчиков (даже те, которые разрабатывают криптографические библиотеки) не понимают, что работа со строками без указания кодировки глупа и не имеет никакого смысла!

    09.11.2017
  • 1. Не используйте PHP mcrypt, он устарел и не поддерживает стандартные методы заполнения. 2. Не используйте Blowfish в новом коде, он не особенно безопасен и обратите внимание, что автор не использует его, а использует AES. 3. Многие процессоры имеют инструкции (AES-NI), которые напрямую поддерживают AES. 09.11.2017
  • @zaph Несколько раз объяснял, что я не контролирую часть PHP. Мне нужно расшифровать то, что я получаю в .NET 09.11.2017
  • Решает проблему? Кажется. Зная настоящую причину, что случилось? Возможно. Но я не знаю хорошей библиотеки шифрования / дешифрования, которая принимает строки в качестве параметров. Ни BouncyCastle, ни Microsoft не делают. 09.11.2017
  • Я проголосовал против из-за необоснованного утверждения: некоторые библиотеки Blowfish на C #, кажется, имеют плохую реализацию. 1. Некоторые из них расплывчаты и бесполезны. 2. кажется, что у них плохая реализация, расплывчата, и лучше всего предположить, что вы не смогли заставить их работать в вашей ситуации. 3. Нет описания того, какая проблема была решена. 4. Помимо этого, в ответе есть несколько хороших моментов. 5. Фактический ответ - это ссылка на реализацию, которая сработала для вас. 6. Информация против использования mcrypt и Blowfish предназначена для будущих читателей. 09.11.2017
  • @ LW001 Сначала я должен быть аккуратным, а потом вежливым. В любом случае точка взята 10.11.2017
  • @Michael Тот факт, что вы не знаете, не означает, что их нет. Поищите в Google шифрование blowfish на C #, и вы увидите. И я назвал причину: некоторые из них работают со строками без учета кодировки. 10.11.2017
  • @zaph Возможно, вы сначала могли бы правильно прочитать вопрос, а затем сами дать лучший ответ 10.11.2017
  • @Albert Вы правы, но криптографическая библиотека, которая принимает строки в качестве аргументов, (имхо) не является хорошей криптобиблиотекой. Криптобиблиотеки Microsoft должны подходить для ~ 70% нормальных сценариев использования, и я почти уверен, что большинство других вариантов использования можно решить с помощью BouncyCastle. 10.11.2017
  • @Michael Это верный момент, с которым я согласен. К сожалению, если вы не знакомы с крипто-библиотеками и не проводите поиск, большинство из них не подходят. 10.11.2017
  • Новые материалы

    Учебные заметки JavaScript Object Oriented Labs
    Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

    Разбор строк запроса в vue.js
    Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

    Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
    «Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..