You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Unicode字符池加密报list index out of range错误修复

字符池加解密程序IndexError报错修复

问题复现

程序流程为先选择选项1生成密钥保存至genkey.txt,再选择选项2执行加密,运行到取密钥数组元素的逻辑时抛出错误:

Exception has occurred: IndexError
list index out of range, line 58, in b = keyarray[a]
将Unicode字符池替换为少量纯英文字符组成的小字符池时,加密流程可正常运行,使用预设Unicode范围字符池时必现该报错。

根因分析

  • 核心原因是密钥数组长度和字符池长度不匹配:代码中字符池取range(32,123)的Unicode字符,总长度为91,索引范围090;但生成密钥时仅循环生成20个字符存入`keyarray`,数组有效索引仅为019。加密时通过a = pool.index(i)取明文字符在字符池中的索引,只要输入字符对应的索引≥20,访问keyarray[a]就会触发越界。
  • 生成密钥的随机索引范围写死为random.randint(0,57),最大仅覆盖到字符池索引57的位置,对应字符为大写Y,后续索引58~90对应的Z、小写字母、特殊符号等完全没有对应的密钥映射,输入包含这类字符时必然越界。
  • 存在隐藏逻辑缺陷:keyarray、encryptedarray等临时数组定义在主循环外,多次操作会持续追加历史数据,导致密钥、密文被污染;文件读写未做异常捕获,若genkey.txt不存在会直接抛出文件不存在错误。

修复代码

直接替换原有代码即可,修复后已补全解密逻辑、输入校验、异常处理:

import random
import os

while True:
    # 每次循环重置临时数组,避免历史数据污染
    encryptedarray = []
    decryptedarray = []
    keyarray = []
    keygen = ""
    # 构建字符池
    pool = []
    for i in range(32, 123):
        pool.append(chr(i))
    pool_len = len(pool)
    
    print("Encryption / Decryption")
    print("")
    print("1. Generate Key")
    print("2. Encrypt")
    print("3. Decrypt")
    print("4. Quit")
    print("NOTE: Key must be generated before selecting Encryption / Decryption")
    print("")
    
    try:
        option = int(input("Enter the number corresponding to the option: "))
    except ValueError:
        print("Please enter a valid option number\n")
        continue

    if option == 1:
        # 生成和字符池等长的密钥,随机范围覆盖全部字符池索引
        temp_pool = pool.copy()
        random.shuffle(temp_pool)
        keyarray = temp_pool
        keygen = "".join(keyarray)
        print("Your generated key is:", keygen)
        print("")
        print("(Make sure you have generated a key before typing 'yes')")
        writebool = input("Do you want to save the file to your computer? ")
        if writebool == "yes":
            # 存在旧密钥文件时先删除再写入
            if os.path.exists("genkey.txt"):
                os.remove("genkey.txt")
            with open("genkey.txt", "w", encoding="utf-8") as keyfile:
                keyfile.write(keygen)
            print("File saved to genkey.txt successfully\n")
        elif writebool == "no":
            print("ok\n")
        else:
            print("Type yes or no\n")

    elif option == 2:
        # 校验密钥文件是否存在
        if not os.path.exists("genkey.txt"):
            print("Please generate key first!\n")
            continue
        msg = input("Enter the message to be encrypted: ")
        with open("genkey.txt", "r", encoding="utf-8") as genkeyf:
            genkeydata = genkeyf.read()
        # 校验输入字符合法性
        invalid_char = False
        for char in msg:
            if char not in pool:
                print(f"Character '{char}' is not supported in current character pool\n")
                invalid_char = True
                break
        if invalid_char:
            continue
        # 执行加密
        if len(genkeydata) == pool_len:
            print("File VALID")
            keyarray = list(genkeydata)
            for i in msg:
                a = pool.index(i)
                b = keyarray[a]
                encryptedarray.append(b)
            print("")
            print("Your encrypted string is: ")
            print("".join(encryptedarray), "\n")
        else:
            print("File INVALID")
            print("Please check if the genkey.txt file matches the current character pool.\n")

    elif option == 3:
        # 补全解密逻辑
        if not os.path.exists("genkey.txt"):
            print("Please generate key first!\n")
            continue
        encrypt_msg = input("Enter the message to be decrypted: ")
        with open("genkey.txt", "r", encoding="utf-8") as genkeyf:
            genkeydata = genkeyf.read()
        if len(genkeydata) != pool_len:
            print("File INVALID")
            print("Please check if the genkey.txt file matches the current character pool.\n")
            continue
        print("File VALID")
        keyarray = list(genkeydata)
        for i in encrypt_msg:
            a = keyarray.index(i)
            b = pool[a]
            decryptedarray.append(b)
        print("")
        print("Your decrypted string is: ")
        print("".join(decryptedarray), "\n")

    elif option == 4:
        print("Exit program")
        break
    else:
        print("Please enter option number between 1-4\n")

修改说明

  • 生成密钥时采用洗牌算法打乱字符池生成等长映射表,密钥长度和字符池完全一致,从根源解决索引越界问题
  • 所有临时数组移至循环内部初始化,避免多次操作时历史数据残留
  • 增加文件存在校验、输入字符合法性校验、输入格式校验,避免非预期报错
  • 用with上下文管理器处理文件读写,自动释放文件句柄,避免文件损坏
  • 补全原代码缺失的解密功能,形成完整的加解密闭环

内容的提问来源于stack exchange,提问作者12345so

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:51:44