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

Python Fernet报密钥需为32位url安全base64编码字节错误修复

Fernet密钥格式报错修复

错误触发场景

程序执行解密逻辑

raw_pass = Fernet(key_de).decrypt(data["password"])
时抛出异常:Fernet key must be 32 url-safe base64-encoded bytes,已尝试对key_de做utf-8编码、base64编码处理仍无法解决。

根本原因

  • 核心错误出在密钥输出环节:Fernet.generate_key()返回值是bytes类型,注册流程中直接用str(key_en)将密钥转为字符串打印时,输出结果会自带b'前缀和末尾的'包裹符。例如真实密钥为b'XyZ123...abc=',str转换后打印给用户的内容是字面量b'XyZ123...abc=',用户复制该内容作为解密密钥输入时,会把多余的b'、'字符一并带入,最终编码后的字节长度、格式均不符合Fernet的32位url-safe base64要求。
  • 存在隐藏空值bug:查询存储的密码时,如果输入的rapass不存在,find_one()会返回None,直接访问data["_id"]会触发空对象访问错误。
  • 冗余校验逻辑:按_id=rapass查询到的返回结果,_id字段必然等于输入的rapass,额外做相等判断无意义,还会放大空值报错概率。

修复步骤

1. 修正注册环节的密钥输出逻辑

将原代码中直接str转换打印密钥的逻辑,改为对bytes类型密钥做utf-8解码后输出,保证打印给用户的密钥是纯base64字符串,无多余字符:

# 原错误代码
# print('SecurePass : ' + str(key_en))
# 修正后
print('SecurePass : ' + key_en.decode('utf-8'))

2. 重构查看密码环节的逻辑

增加空值判断、输入前后空格过滤、解密异常捕获,去掉冗余校验:

elif startMenu == 2:
    clear()
    print("Enter rapass:")
    rapass = input().strip()
    data = pass_collection.find_one({"_id" : rapass})

    if not data:
        print("Invalid credentials.")
        input()
        clear()
        continue

    print("Enter SecurePass")
    key_de = input().strip()
    try:
        key_de_bytes = key_de.encode('utf-8')
        cipher = Fernet(key_de_bytes)
        raw_pass = cipher.decrypt(data["password"]).decode('utf-8')
        print("Stored password: ", raw_pass)
    except:
        print("SecurePass incorrect or invalid format. Please try again.")
    input()
    clear()

验证方式

重新走新建密码流程,此时打印的SecurePass不会带有b'前缀,复制该密钥后走查看密码流程,输入对应rapass和复制的SecurePass即可正常解密,不会再触发密钥格式错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:57:17