在App Engine上使用PyCrypto时遇到Python UnicodeEncodeError

2 投票
2 回答
2471 浏览
提问于 2025-04-17 06:11

我正在尝试将一个加密的查询字符串传递到另一个网址。

下面的代码让我遇到了这个错误:

Unicode编码错误:'ascii'编码无法在位置7编码字符u'\u04b7':序号不在范围内(128)

我使用的加密模块是 PyCrypto

我在App Engine上运行的是Python 2.5.2

页面A

    import Crypto
    from Crypto.Cipher import ARC4

    obj=ARC4.new('stackoverflow')
    msg = 'This is my secret msg'
    encrypted = obj.encrypt(msg);

    self.redirect('/pageb?' + urllib.urlencode({'q': encrypted}))

页面B

    import Crypto
    from Crypto.Cipher import ARC4

    encrypted = self.request.get('q')
    obj=ARC4.new('stackoverflow')
    decrypted = obj.decrypt(encrypted)

    get_data = cgi.parse_qs(decrypted)

    self.response.out.write(decrypted)
    self.response.out.write(pprint.pprint(get_data))

错误追踪信息

Traceback (most recent call last):
  File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\_webapp25.py", line 701, in __call__
    handler.get(*groups)
  File "C:\Program Files\Google\google_appengine\demos\guestbook\guestbook.py", line 47, in get
    decrypted = obj.decrypt(encrypted)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u04b7' in position 7: ordinal not in range(128)

2 个回答

1

从现有的信息来看,可以推测出某个地方需要一个字节串(bytestring),但是你给它提供了一个包含Unicode字符U+04B7(西里尔字母小写字母CHE带下行)的unicode对象……这显然无法用ASCII编码(默认编码)表示,所以才会出现错误信息。

目前最好的建议是:别这么做。

更新 1:你还是没有问问题。不过:

这里的“某个地方”指的是某个加密工具的decrypt方法。这个方法肯定需要一个str对象。你可以用print repr(encrypted)来查看一下。如果它看起来像是随机的垃圾数据(加密的数据应该是这样的),那么它在某个地方被从str对象转换成了unicode对象。你需要回头查查是怎么发生的。如果encrypted看起来像是有意义的文本,那说明你的加密过程出了问题。

第一步:先用一些已知的明文,进行加密,然后在GAE的环境外再解密一次。每一步都用print repr()来检查,这样你对下一步的预期就会合理一些。

第二步:在GAE中重复第一步,检查每一段数据的类型和内容。

更新 2:看起来你在页面A中有一个urlencode,但在页面B中没有对应的urldecode;这是不是问题的一部分?

6

一般来说,在你的加密内容中加入base64编码和解码的步骤。

import base64

base64_encrypted_message = base64.b64encode(encrypted_message)
// send your message via POST as GET can be seen on system logs

encrypted_message = base64.b64decode(base64_encrypted_message)
// decrypt your message

至于另一个错误,建议你了解一下unicode和utf-8对非ascii字符的编码。在把内容传给加密或解密函数之前,你需要先进行这一步。

撰写回答