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
相关产品推荐
相关产品推荐

