无效的连续字节保存密码

时间:2014-11-18 17:53:28

标签: python unicode

我有以下功能来创建密文然后保存:

def create_credential(self):
    des = DES.new(CIPHER_N, DES.MODE_ECB)
    text = str(uuid.uuid4()).replace('-','')[:16]
    cipher_text = des.encrypt(text)
    return cipher_text      

def decrypt_credential(self, text):
    des = DES.new(CIPHER_N, DES.MODE_ECB)
    return des.decrypt(text)

def update_access_credentials(self):
    self.access_key = self.create_credential()
    print repr(self.access_key) # "\xf9\xad\xfbO\xc1lJ'\xb3\xda\x7f\x84\x10\xbbv&"
    self.access_password = self.create_credential()
    self.save()

我会打电话给:

>>> from main.models import *
>>> u=User.objects.all()[0]
>>> u.update_access_credentials()

这是我得到的堆栈跟踪:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/deemarklit/Desktop/Example/Django/Example/main/models.py", line 747, in update_access_credentials
    self.save()
  File "/Users/deemarklit/Desktop/Example/Django/Example/main/models.py", line 731, in save
    super(User, self).save(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/django/db/models/base.py", line 546, in save
    force_update=force_update, update_fields=update_fields)
  File "/Library/Python/2.7/site-packages/django/db/models/base.py", line 626, in save_base
    rows = manager.using(using).filter(pk=pk_val)._update(values)
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 603, in _update
    return query.get_compiler(self.db).execute_sql(None)
  File "/Library/Python/2.7/site-packages/django/db/models/sql/compiler.py", line 1014, in execute_sql
    cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
  File "/Library/Python/2.7/site-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
    cursor.execute(sql, params)
  File "/Library/Python/2.7/site-packages/django/db/backends/util.py", line 45, in execute
    sql = self.db.ops.last_executed_query(self.cursor, sql, params)
  File "/Library/Python/2.7/site-packages/django/db/backends/mysql/base.py", line 243, in last_executed_query
    return cursor._last_executed.decode('utf-8')
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xf5 in position 738: invalid start byte

为什么会发生这种情况?我将如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

之所以发生这种情况,是因为您尝试在文本字段中保存非文本数据。改为使用非文本字段,或者通过例如文本将数据编码为文本。 Base-64编码。

答案 1 :(得分:1)

您正在将字节字符串存储到Unicode数据库字段中,因此它将尝试解码为Unicode。

使用可以存储不透明二进制数据的数据库字段,显式解码为Unicode(latin-1将字节一对一地映射到Unicode代码点)或将数据包装成可以存储为文本的表示。

对于Django 1.6及更高版本,请使用BinaryField。对于早期版本,使用二进制到文本转换(例如Base64)优于解码到Latin-1;后者的结果不会给你有意义的文本数据,但Django可能会尝试显示它(例如在管理界面中)。

答案 2 :(得分:0)

在此处使用base64编码和解码修复了此问题:

import base64

def create_credential(self):
    des = DES.new(CIPHER_N, DES.MODE_ECB)
    text = str(uuid.uuid4()).replace('-','')[:16]
    cipher_text = des.encrypt(text)
    base64_encrypted_message = base64.b64encode(cipher_text)
    return base64_encrypted_message     

def decrypt_credential(self, text):
    text = base64.b64decode(text)
    des = DES.new(CIPHER_N, DES.MODE_ECB)
    message = des.decrypt(text)
    return message