2012-05-26 5 views
1

Мне нужно связаться с API, который требует, чтобы запрос был закодирован в Blowfish и Base64.Blowfish зашифрованная строка становится тарабарщиной

В моей пользовательской библиотеке я начинаю с:

# encoding: utf-8 
require "base64" 
require 'crypt/blowfish' 

создать экземпляр:

@blowfish_key = '1234567887654321' 
@blowfish  = Crypt::Blowfish.new(@blowfish_key) 

И далее вниз создать зашифрованную строку (или «билет» как API называют)

@string_to_encrypt = "#{@partnerid},#{user.id},#{exam_id},#{return_url},#{time_stamp}" 
@enc    = @blowfish.encrypt_string(@string_to_encrypt) 

В консоли Rails можно дешифровать с @blowfish.decrypt_string(@enc) без каких-либо проблем. Но API дает мне бред:

Invalid ticket: 
Decrypted String :)IŠkó}*Ogû…xÃË-ÖÐHé%q‹×ÎmªÇjEê !©†xRðá=Ͳ [À}=»ïN)'sïƒJJ=:›õ)¦$ô1X¢ 

Кроме того, когда я зашифровать что-то простое в консоли, как «Hello», и кормить зашифрованную строку в онлайн Blowfish декодер, как http://webnet77.com/cgi-bin/helpers/blowfish.pl, я получаю тот же тарабарщину беспорядок назад.

Это похоже на шифрование Ruby blowfish, которое не используется нигде.

Примечание:

В моем реальном приложении я посылаю зашифрованную строку через поле формы в Webservice. Зашифрованная строка кодируется Base64 и имеет префикс «a».

@enc = Base64.encode64(@enc) 
@enc = 'a' + CGI::escape(@enc) 

Это объясняется в их документации:

Формат билета:

t=’a’ + URL_Encode (
Base64_Encode (
Blowfish_Encrypt (‘partnerid,user_id,test_id,URL_Encode(return_URL),ticket_timestamp’, ‘blowfish_key’) 
    ) 
) 

Примечание выше, что функция принимает два Blowfish_Encrypt parameters- 1) строку шифровать и 2) шестнадцатеричный ключ. Также обратите внимание, что билет имеет с префиксом «a» (ASCII 97).

Пример того, что форма HTML будет выглядеть следующим образом:

<form method=”POST” action=”http://www.expertrating.com/partner_site_name/”> 
<input type=”hidden” name=”t” value=”adfinoidfhdfnsdfnoihoweirhqwdnd2394yuhealsnkxc234rwef45324fvsdf2” /> 
<input type=”submit” name=”submit” value=”Proceed to take the Test” /> 
</form> 

Я потерял, где же я ошибся?

+0

Вы понимаете, что зашифрованные данные являются, по существу, двоичным варваром? Он становится «читаемым», если вы делаете что-то вроде кодировки base-64. –

ответ

1

Там есть несколько вещей:

1) Как уже было сказано в комментариях, если вы печатаете зашифрованные строки, то это почти всегда вызывает проблемы, потому что зашифрованные строки, весьма вероятно, содержат не-ASCII символы это будет либо непечатаемо, либо в представлении, которое не понимается другими. Лучший способ получить представление, которое широко понимается, - это кодировать результат с использованием кодировки Base64 или Hex, поэтому кодировка Base64, применяемая в вашем приложении, подходит для этого.

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

hex = encrypted.unpack("H*")[0].upcase 

3) Но все-таки не повезло с приложением Perl. Одной из причин является это (взято из источников Crypt):

def encrypt_stream(plainStream, cryptStream) 
    initVector = generate_initialization_vector(block_size()/4) 
    chain = encrypt_block(initVector) 
    cryptStream.write(chain) 

Что это означает, что Crypt пишет IV в качестве первого блока зашифрованного сообщения. Это совершенно нормально, но большинство современных криптографических библиотек, которые я знаю, не будут дополнять IV, а скорее предполагают, что он обменивается как внеполосная информация между двумя сообщающимися сторонами.

4) Но даже зная это, вам все равно не повезет с приложением Perl. Причина в том, что приложение Perl использует шифрование в режиме ECB, где камень Crypt использует режим CBC. Режим CBC использует IV, поэтому даже одноблочные сообщения не будут совпадать, если вы используете ноль IV. Но использование all-zero IV (или любого другого детерминированного IV) - это bad practice (и Crypt этого не делает). Это позволяет отличать первый блок от случайного и открывает вам атаки, такие как BEAST. Использование ECB - это плохая практика, за исключением случаев с совершенно редким краем. Поэтому давайте забудем об этом приложении Perl и сосредоточимся на вещах.

5) Я, естественно, в пользу использования Ruby OpenSSL, но в этом случае я думаю, что я не субъективен, если скажу вам, что лучше использовать общую безопасность вместо драгоценного камня Crypt. Просто говорю вам, это было бы неточным, так вот две причины:

  • Crypt создает свои капельницы, используя предсказуемый генератор случайных чисел (комбинации srand и rand), но это не достаточно хорошо. Это должен быть криптографически безопасный случайный генератор.

  • Склеп, кажется, больше не поддерживается, и между тем произошли некоторые вещи, которые либо были неизвестны в то время, либо никогда не были в рамках этого проекта. Например, OpenSSL начинает работать с криптографией, устойчивой к утечке, чтобы предотвратить атаки побочных каналов, которые нацелены на синхронизацию, пропуски кэша и т. Д. Это, вероятно, никогда не было целью Crypt, но такие атаки представляют реальную угрозу в реальной жизни.

6) Если моя проповедь убедила вас, чтобы сделать изменения, то я мог бы продолжать и спросить вас, действительно ли это быть Blowfish. Сам алгоритм, несомненно, выдающийся, но в настоящее время существуют лучшие, еще более безопасные варианты, такие как AES, например. Если это абсолютно должно быть Blowfish, она поддерживается рубинового OpenSSL, а также:

cipher = OpenSSL::Cipher.new('bf-cbc') 

7) Если ваш ключ производства выглядит так, как в примере, то есть еще слабое место. В таких струнах не хватает энтропии. Что вы должны сделать, это снова использовать криптографически безопасный генератор случайных чисел для генерации ключа, который довольно легко в Руби OpenSSL:

key = cipher.random_key 

Хорошая вещь он автоматически выбирает соответствующую длину ключа в зависимости от алгоритма шифрования для использоваться.

8) Наконец, правильно ли я предполагаю, что вы используете этот зашифрованный результат в качестве какой-либо формы токена аутентификации? Как вы добавляете его в HTML-файл, ожидаете, чтобы его вернуть в каком-то запросе POST и сравнить полученный токен с оригиналом, чтобы аутентифицировать какое-то действие? Если это так, то это снова будет плохой практикой. На этот раз даже больше.Здесь вы не используете аутентифицированное шифрование, а это значит, что ваш зашифрованный текст - подаваемый. Это подразумевает, что злоумышленник может относительно легко подделывать содержимое этого токена, не зная, что ваш ключ шифрования. Это приводит ко всем видам атак, даже приводя к полному компромиссу, связанному с ключевым восстановлением.

должен использовать либо аутентифицированные режимы шифрования (GCM, CCM, EAX ...), либо использовать код аутентификации сообщения, чтобы определить, были ли изменены зашифрованные тексты. Еще лучше, не используйте шифрование вообще и не генерируйте свои билеты, используя безопасную хэш-функцию. Ключевым моментом здесь является вычисление хэша достоверно рандомизированного значения, в противном случае снова можно предсказать результат. Временной метки, используемой в вашем примере, недостаточно. Это должно быть криптографически безопасное nonce, вероятно, генерируемое SecureRandom.

Но тогда вам все же придется рассмотреть возможность повторения таких жетонов, захват токенов, ... вы видите, это не так просто.

+0

Ничего себе, это какой-то ответ. Спасибо вам за это. Как вы, возможно, догадались, у меня нет опыта, который, очевидно, использует методы шифрования. Поэтому я ценю помощь. Билет должен быть Blowfish и Base64. Я отправляю билет в виде скрытого поля формы для онлайн-тестирования, Webservice расшифровывает его, что дает им необходимую информацию, позволяющую пользователю выполнить онлайн-тест. После теста пользователь перенаправляется обратно на мой сайт - URL-адрес возврата, идентификатор пользователя, идентификатор теста и т. Д. Находятся в зашифрованном билете. –

+0

Дело в том, что они сообщают вам, что АБСОЛЮТНО обязательно использовать Blowfish и создавать билет в соответствии со своими спецификациями. Они также дают вам ключ Blowfish, поэтому я не могу сам выбирать ключ. Вы действительно можете проверить шифрование через свой сайт - http://dev.expertrating.com/blowfish/BlowfishDemo.asp –

+0

Хе-хе, да, я знаю ситуацию. Так что, вы должны использовать то, что они вам дают, я не был уверен, оказал ли вы влияние на алгоритмы ... Хорошо, тогда пусть это будет их проблемой :) Я бы по-прежнему рекомендовал использовать OpenSSL, потому что Crypt также использует меньше общей схемы заполнения, которую они, вероятно, не понимают. Есть ли спецификация для точных параметров, которые они используют? – emboss

Смежные вопросы