MySQL неправильно хранит зашифрованный текст, созданный из библиотеки PyCrypto - PullRequest
1 голос
/ 15 декабря 2011

Я создаю приложение в web.py, но у меня возникают проблемы с хранением зашифрованных данных в MySQL.

PyCrypto создает зашифрованный текст, который выглядит следующим образом: '\x06\x7f\x81\xa0\xf4d\x00H\xef\xd0\x18[c\x18Z\xf8', который при печати отображается как "ôdHïÐ[cZø"

Однако MySQL хранит его как: ???d H??[cZ? Я храню это следующим образом:

query_string = "INSERT INTO %s (%s) VALUES (\"%s\")" % (table, column, value) 

Я пытался использовать "SET character_set_connection=utf8" после подключения к базе данных, но это не дало никаких изменений в результатах.

Я явно упускаю что-то очень важное. Есть мысли?

Ответы [ 2 ]

3 голосов
/ 17 декабря 2011

MySQL пытается сохранить вашу байтовую строку в символьном столбце.Поскольку для набора символов соединения используется UTF-8, а строка байтов не представляет допустимую последовательность UTF-8, она искажается.

Чтобы правильно загрузить необработанные байты в базу данных, вам необходимо:

  1. делает столбец типом BINARY (или обычно символьным типом с двоичным сопоставлением), а

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

Вы должны использовать параметризованные запросы в любом случае, потому что интерполяция строк, которую вы используете сейчас, без экранированияуязвим для инъекций SQL.В файле web.py это может выглядеть следующим образом:

query_string= 'INSERT INTO %s (%s) VALUES ($value)' % (table, column)
db.query(query_string, vars= {'value': value})

(при условии, что значения table и column известны как хорошие.)

Выполнение этого также означает, что вы неНе нужно беспокоиться о знаке доллара.

Другой подход - использовать обычную символьную строку, кодирующую байты, не входящие в ASCII.Вы делаете это с помощью uucode в своем текущем обходном пути, но base64 будет более распространенной альтернативой, к которой проще обратиться в Python (ciphertext.encode('base64')).Шестнадцатеричное кодирование (.encode('hex')) наиболее распространено в случае хэша.

0 голосов
/ 16 декабря 2011

Я нашел решение. Я не уверен, насколько это элегантно, но это было лучшее, что я мог понять.

КОДИРОВАНИЕ:

1) import binascii

2) ciphertext = cipher.encrypt(plaintext)

3) asciitext = binascii.b2a_uu(ciphertext)

4) webpy_workaround = asciitext.replace('$', 'DOLLARSIGN') //if there are dollar signs in the text, webpy will try to use anything afterward, and will complain at you.

5) Сохраните webpy_workaround в sql.

РАСШИФРОВКА:

1) Получить значение из SQL

2) asciitext = sql_value.replace('DOLLARSIGN', '$')

3) ciphertext = binascii.a2b_uu(asciitext)

4) plaintext = cipher.decrypt(ciphertext)

...