3

好的,所以我的问题是我有字符串 '\222\222\223\225',它在数据库中存储为 latin-1。我从 django 得到的(通过打印它)是以下字符串,'ââââ¢' 我认为它是它的 UTF 转换。现在我需要将字符串传递给执行此操作的函数:

strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

我收到此错误:

chr() arg 不在范围内 (256)

如果我首先尝试将字符串编码为 latin-1,则会收到此错误:

'latin-1' 编解码器无法对位置 0-3 中的字符进行编码:序数不在范围内(256)

我已经阅读了很多关于字符编码如何工作的内容,但我缺少一些东西,因为我只是不明白!

4

3 回答 3

4

您的第一个错误 'chr() arg not in range(256)' 可能意味着您已下溢该值,因为 chr 不能采用负数。我不知道当 inputcounter + 33 大于实际字符表示时加密算法应该做什么,你必须检查在这种情况下该怎么做。

关于第二个错误。您必须对常规字符串对象进行 decode() 而不是 encode() 才能获得数据的正确表示。encode() 接受一个 unicode 对象(以 u' 开头的对象)并生成一个常规字符串以输出或写入文件。decode() 接受一个字符串对象并生成一个带有相应代码点的 unicode 对象。当从字符串对象生成时,这是通过 unicode() 调用完成的,您也可以改为调用 a.decode('latin-1') 。

>>> a = '\222\222\223\225'
>>> u = unicode(a,'latin-1')
>>> u
u'\x92\x92\x93\x95'
>>> print u.encode('utf-8')
ÂÂÂÂ
>>> print u.encode('utf-16')
ÿþ
>>> print u.encode('latin-1')

>>> for c in u:
...   print chr(ord(c) - 3 - 0 -30)
...
q
q
r
t
>>> for c in u:
...   print chr(ord(c) - 3 -200 -30)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: chr() arg not in range(256)
于 2008-11-08T05:29:37.937 回答
2

正如 Vinko 所指出的,Latin-1 或 ISO 8859-1 没有您引用的八进制字符串的可打印字符。根据我对 8859-1 的注释,“C1 控件 (0x80 - 0x9F) 来自 ISO/IEC 6429:1992。它没有定义 80、81 或 99 的名称”。代码点名称与 Vinko 列出的一样:

\222 = 0x92 => PRIVATE USE TWO
\223 = 0x93 => SET TRANSMIT STATE
\225 = 0x95 => MESSAGE WAITING

正确的 UTF-8 编码是(Unicode、二进制、十六进制):

U+0092 = %11000010 %10010010 = 0xC2 0x92
U+0093 = %11000010 %10010011 = 0xC2 0x93
U+0095 = %11000010 %10010101 = 0xC2 0x95

带有 CIRCUMFLEX 的拉丁文小写字母 A 是 ISO 8859-1 代码 0xE2,因此是 Unicode U+00E2;在 UTF-8 中,即 %11000011 %10100010 或 0xC3 0xA2。

CENT SIGN 是 ISO 8859-1 代码 0xA2,因此是 Unicode U+00A2;在 UTF-8 中,即 %11000011 %10000010 或 0xC3 0x82。

因此,无论您看到什么,您似乎都没有看到 ISO 8859-1 的 UTF-8 编码。除此以外,您只看到 5 个字节,而您必须看到 8 个字节。

补充:答案的前一部分解决了“UTF-8 编码”声明,但忽略了问题的其余部分,其中说:

Now I need to pass the string into a function that does this operation:

    strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

I get this error: chr() arg not in range(256).  If I try to encode the
string as Latin-1 first I get this error: 'latin-1' codec can't encode
characters in position 0-3: ordinal not in range(256).

您实际上并没有向我们展示 intCounter 是如何定义的,但是如果它每个字符缓慢递增,迟早 ' ord(c) - 3 - intCounter - 30' 将是负数(顺便说一下,为什么不结合常量并使用 ' ord(c) - intCounter - 33'?),在哪一点,chr()很可能会抱怨。如果值为负,则需要添加 256,或使用模运算确保您有一个介于 0 和 255 之间的正值传递给chr(). 由于我们看不到 intCounter 是如何递增的,因此我们无法判断它是从 0 循环到 255 还是单调递增。如果是后者,那么您需要一个表达式,例如:

chr(mod(ord(c) - mod(intCounter, 255) + 479, 255))

其中 256 - 33 = 223,当然,479 = 256 + 223。这保证了传递给的值chr()是正数,并且对于任何输入字符 c 和任何 intCounter 值都在 0..255 范围内(并且,因为mod()函数永远不会得到否定的论点,不管mod()它的论点是否定的时行为如何,它也可以工作)。

于 2008-11-08T06:08:07.047 回答
0

好吧,因为它是用一些糟糕的方案加密的,只是通过一些请求改变了字符的 ord(),所以从数据库中出来的字符串已经被加密,这会解密它。您在上面提供的内容似乎不起作用。在数据库中它是 latin-1,django 将其转换为 unicode,但我无法将其作为 unicode 传递给函数,但是当我尝试将其编码为 latin-1 时,我看到了该错误。

于 2008-11-08T05:42:00.173 回答