Там есть несколько вещей:
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.
Но тогда вам все же придется рассмотреть возможность повторения таких жетонов, захват токенов, ... вы видите, это не так просто.
Вы понимаете, что зашифрованные данные являются, по существу, двоичным варваром? Он становится «читаемым», если вы делаете что-то вроде кодировки base-64. –