AES-шифрование с помощью Crypto (node-js) / дешифрование с помощью Pycrypto (python)
Я пишу этот вопрос + ответ, потому что я много боролся (возможно, из-за отсутствия опыта), заблудился во многих различных способах шифрования/дешифрования вещей с помощью node или python.
Я подумал, может быть, мой случай может помочь людям в будущем.
что нужно делать:
- получить данные из формы, зашифровать их с помощью Crypto (node-js)
- передайте зашифрованные данные в Python и расшифруйте их с помощью PyCrypto.
Я решил использовать шифрование AES.
вот как я начал (я не собираюсь проходить через все, что я пробовал):
-
я последовал примеру в конце на этой странице
который дал в моем случае:
(это может быть очень плохое сочетание javascript и coffeescript)
crypto = require "crypto" [...] key = "mykeywhatever" cipher = crypto.createCipher('aes192', key) cipher.update('string i want to encode', 'binary', 'hex') encoded_string = cipher.final('hex') [...]
это сработало довольно хорошо, чтобы кодировать мою строку.
-
Затем Я написал мой скрипт python для расшифровки этой строки, используя readme on страница GitHub от PyCrypto:
from Crypto.Cipher import AES [...] my_string = data_coming_from_rabbitmq obj = AES.new('mykeywhatever', AES.MODE_CBC) obj.decrypt(ciphertext) [...]
это, очевидно,не сработало: в readme есть IV, но поскольку я не дал его в скрипте узла, зачем мне давать его в python?
после более googling, я узнал, что крипто узел использует OpenSSL, в то время как PyCrypto, по-видимому, нет. Так что я просмотрел это и нашел те страницы:
- как я могу расшифровать что-то с помощью PyCrypto, которое было зашифровано с помощью OpenSSL?
- AES то же самое в библиотеках PyCrypto & Node.JS Crypto
- и многое другое...
Итак, все усложнилось, никто не делает то же самое для расшифровки данных, я заблудился и попросил о помощи.
ответ-это то, что мой коллега и я придумали (Ну, в основном мой corworker).
2 ответов
Итак, мы начали с "как я могу расшифровать... OpenSSL " ответ.
-
нам нужно было изменить сценарий шифрования, который дал:
crypto = require "crypto" [...] var iv = new Buffer('asdfasdfasdfasdf') var key = new Buffer('asdfasdfasdfasdfasdfasdfasdfasdf') var cipher = crypto.createCipheriv('aes-256-cbc', key, iv); cipher.update(new Buffer("mystring")); var enc = cipher.final('base64'); [...]
iv должен быть длиной 16 байт,ключ это 32bytes. И мы изменились!--2--> to
createCipheriv
. -
вернемся к скрипту расшифровки python:
процесс просто читал документацию PyCrypto и сравнивал С кодом, который мы начали от.
тогда мы решили просто придерживайтесь API, и начинать с нуля. И он дал:
from base64 import b64decode from Crypto.Cipher import AES [...] iv = 'asdfasdfasdfasdf' key = 'asdfasdfasdfasdfasdfasdfasdfasdf' encoded = b64decode('my_encrypted_string') dec = AES.new(key=key, mode=AES.MODE_CBC, IV=iv) value = dec.decrypt(encoded)
и это было так просто... Надеюсь, это поможет некоторым из вас!
обновление:
как писал Персеид в комментариях к своему ответу, IV должен быть случайным и различным для каждого сообщения
система, которую вы строите, вероятно небезопасной
за исключением хранения вы в основном никогда не хотите просто зашифровать свои данные, но и аутентифицировать его. Аутентификация в этом контексте означает, что допустимое сообщение может быть создано только тем, кто знает ключ. Широко используемая схема аутентификации HMAC.
Если вы не в подлинности Вашего сообщения кто-нибудь может передавать данные в службу. Злоумышленник может быть не в состоянии полностью контролировать результат после расшифровки, но он/она все еще может быть очень опасно. Например, если вы используете CBC (что вы и делаете) и наиболее распространенные схемы заполнения (AES является блочным шифром и может шифровать только 128-битные блоки данных), и злоумышленник может различать ошибку заполнения и любую другую ошибку, то все ваши сообщения могут быть расшифрованы злоумышленником. Это называется дополнение oracle attack и далеко слишком общего.
в защиты от данного класса атак, вы можете использовать аутентифицированного шифрования,, например,GCM режим blockcipher.
Также вы должны защищать против replay атаки. Рассмотрите банковское приложение,и данные, которые вы передаете, являются банковским переводом. Запрет на любой загар злоумышленник может записать предыдущую транзакцию и воспроизвести эту транзакцию в вашей службе снова и снова, передавая несколько деньги клиент изначально хотел.
является ли форма, которую вы получаете данные, передаваемые по HTTPS? Если нет: Может ли ключ быть подслушан злоумышленником? Как пользователь знает, что он получил форму от вас, а не от кого-либо другого (SSL/TLS-это столько же аутентификация, сколько конфиденциальность).
вероятно, я забыл некоторые другие векторы атаки простые предложения CBC-шифрования.
варианты
вероятно, самый простой способ защита от этих атак заключается в передаче данных формы по HTTPS. SSL / TLS был разработан для предотвращения всех вышеперечисленных атак, и реализации на стороне клиента и сервера должны были долго созревать.