1

我正在 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”,但结果没有产生任何变化。

我显然错过了一些非常重要的东西。有什么想法吗?

4

2 回答 2

3

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})

(假设tablecolumn值是已知良好的。)

这样做也意味着您不必担心美元符号。

另一种方法是使用普通字符串,编码掉非 ASCII 字节。ciphertext.encode('base64')您在当前的解决方法中使用 uucode 执行此操作,但 base64 将是一种更常见的替代方法,在 Python ( )中更容易使用。十六进制编码 ( .encode('hex')) 最常见于散列的情况。

于 2011-12-17T16:39:02.833 回答
0

我想出了一个解决办法。我不确定它有多优雅,但这是我能想到的最好的。

编码:

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)

于 2011-12-16T14:55:39.357 回答