为什么当我尝试使用 utf-8 时,我的代码会返回“ascii 编解码器”错误?

Why is my code returning an "ascii codec" error when I'm trying to use utf-8?

提问人:nalthea 提问时间:10/12/2023 最后编辑:nalthea 更新时间:10/12/2023 访问量:104

问:

我是 Python 的新手,刚刚开始将其用作 CTF 挑战的一部分(我是一名网络安全专业的学生)。我得到了一个大部分预先构建的“解码器”脚本,任务是完成它。所以,我把我的单词列表作为列表变量导入到脚本中,我有一个 while 循环贯穿每个单词,这一切都很棒......除非单词列表中出现非 ASCII 字符(在这种情况下是单词“Français”),否则我会收到以下错误:

Traceback (most recent call last):
  File "dict.py", line 32, in <module>
    cipher = AES.new(secret + (BLOCK_SIZE - len(codecs.encode(secret, 'utf-8' )) % BLOCK_SIZE) * PADDING, AES.MODE_ECB)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

如果代码没有指定 utf-8 编码,这将是有道理的,而且当我在终端中得到......不是 ASCII!echo $LANGen_GB.UTF-8

作为参考,这是我收到的原始代码:

# pip install pycryptodome
from Crypto.Cipher import AES
import base64

BLOCK_SIZE = 32

PADDING = '{'

# Encrypted text to decrypt
encrypted = "9l21XiUohS1j9kUx02KJNAkjw51pupGgiMlCkuVNEMo="

def decode_aes(c, e):
    return c.decrypt(base64.b64decode(e)).decode('latin-1').rstrip(PADDING)

secret = "password"

if secret[-1:] == "\n":
    print("Error, new line character at the end of the string. This will not match!")
elif len(secret.encode('utf-8')) >= 32:
    print("Error, string too long. Must be less than 32 bytes.")
else:
    # create a cipher object using the secret
    cipher = AES.new(secret + (BLOCK_SIZE - len(secret.encode('utf-8')) % BLOCK_SIZE) * PADDING, AES.MODE_ECB)

    # decode the encoded string
    decoded = decode_aes(cipher, encrypted)

    if decoded.startswith('FLAG:'):
        print("\n")
        print("Success: "+secret+"\n")
        print(decoded+"\n")
    else:
        print('Wrong password')

这是我修改它之后(省略了未更改的部分):



with open('words.txt', 'r') as f:
    words = f.readlines()

i = 0

while i < len(words):

    secret = words[i][0:-1]
    print(secret)

    if secret[-1:] == "\n":
        print("Error, new line character at the end of the string. This will not match!")
    elif len(secret.encode('utf-8')) >= 32:
        print("Error, string too long. Must be less than 32 bytes.")
    else:
        # create a cipher object using the secret
        cipher = AES.new(secret + (BLOCK_SIZE - len(secret.encode('utf-8')) % BLOCK_SIZE) * PADDING, AES.MODE_ECB)

        # decode the encoded string
        decoded = decode_aes(cipher, encrypted)

        if decoded.startswith('FLAG:'):
            print("\n")
            print("Success: "+secret+"\n")
            print(decoded+"\n")
            break
        else:
            print('Wrong password')
            print(i)
            i += 1
           

这一直持续到“Français”。

我在 Python 2.7 中运行它。我尝试在 python3 中运行它,但是 Crypto.Cipher 的导入不起作用,而且我对 Python 的了解真的不够,无法解决这个问题。我也尝试安装编解码器模块并替换为,但我遇到了同样的错误。(ModuleNotFoundError: No module named 'Crypto')secret.encode('utf-8')codecs.encode(secret,'utf-8')

我不需要任何人为我解决剩下的任务。如果有其他原因导致我的代码无法正常工作,请不要告诉我,我会想办法的。但是这个编码的东西似乎真的不是挑战的一部分,我对下一步该怎么做感到困惑。为什么它使用 ASCII 作为默认编码,尽管有相反的参数,我该如何解决它?

Python UTF-8 编码 非 ASCII 字符

评论

0赞 deceze 10/12/2023
请发布完整的错误消息,包括回溯,以便清楚它的来源。
6赞 deceze 10/12/2023
如果您错误地混合了字节和字符串,Python 2 会进行大量隐式编码和解码。问题可能源于类似的事情。话虽如此,Python 2 已经古老而死了。你不应该在 Python 2 中编写任何新代码,也不应该学习 Python 2 及其陷阱。使用 Python 3 并在那里解决您的模块错误,然后从那里开始。
2赞 Mark Tolonen 10/12/2023
secret可能已编码。它的类型在 Python 2 中,相当于在 Python 3 中。在 Python 2 中,隐式将用于转换为类型(因此会产生错误),因此是可能的。这些语句是 Python 3 样式的,因此您可能应该使用 Python 3,并且只需要安装 using .strbytes.decode('ascii')secretunicodesecret.encode('utf-8')printpycryptodomepip
1赞 Mark Tolonen 10/12/2023
@MarkRansom这不是我们第一次没有可重复的例子。
1赞 nalthea 10/12/2023
@MarkRansom实际上,这是我的错,上面的编码也会触发错误。我忘了我在发布错误消息时注释了长度检查行,看看这是否可以解决问题。感谢大家的建议,我将改用 Python 3!

答: 暂无答案