MySQL没有正确存储从PyCrypto库生成的密文

时间:2011-12-15 18:28:41

标签: mysql unicode web.py pycrypto

我正在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 个答案:

答案 0 :(得分:3)

MySQL正在尝试将您的字节字符串存储在字符列中。因为连接字符集是UTF-8但字节字符串不代表有效的UTF-8序列,所以它会受到损坏。

要正确地将原始字节输入数据库,您需要:

  1. 使列成为BINARY类型(或通常是带二进制排序规则的字符类型),

  2. 使用参数化查询将数据导入数据库,而不是将它们插入到查询字符串中,在那里它们可能与非二进制(Unicode)内容混合。

  3. 你应该使用参数化查询,因为你现在使用的字符串插值没有转义,容易受到SQL注入的攻击。在web.py中可能看起来像:

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

    (假设tablecolumn值已知良好。)

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

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

答案 1 :(得分:0)

我找到了解决方案。我不确定它有多优雅,但它是我能想到的最好的。

ENCODING:

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)