Fernet密钥格式错误求助:Django解密时提示需32位URL安全Base64字节
解决Fernet解密时的
ValueError: Fernet key must be 32 url-safe base64-encoded bytes错误 问题场景
在Django项目中解密经Fernet加密的内容时,持续触发错误:
ValueError at / Fernet key must be 32 url-safe base64-encoded bytes
密钥通过Django模板的输入框传入,获取输入值后用于解密时始终报错。
相关代码
Django模板代码
<form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} <h3>Welcome to Encryption, Decryption and Compression program using Python</h3> {% for field in form %} <div>{{ field }} </div> {% endfor %} <select name="choices" id="choices"> <option>Encryption</option> <option>Decryption</option> <option>Encryption and Compression</option> <option>Decryption and Compression</option> <option>Compression</option> </select> <input type="text" name="dkey" id="dkey" placeholder="Enter Decryption Key"> <button >Proceed</button> </form>
views.py代码(原错误版本)
def decryption(self, key): key = base64.urlsafe_b64encode(bytes(key, encoding="utf-8")) f = Fernet(key) def post(self, request): m_file = request.FILES['file'] opt = request.POST.get('choices') if opt == "Decryption": dkey = request.POST.get('dkey') decrypted = self.decryption(dkey)
加密方法代码
def encryption(self, content): key = Fernet.generate_key() cipher_suite = Fernet(key) cipher_text = cipher_suite.encrypt(bytes(str(content), encoding='utf-8')) return cipher_text, key
用户输入的Fernet密钥
Pl85l36CA7TJe48jv8nWYFD4SWIhIJNFQL8CyyLlXR4=
错误原因
加密时Fernet.generate_key()生成的密钥已经是URL-safe的base64编码字节串,用户输入的密钥就是该字节串解码后的字符串。但当前decryption方法中,对用户输入的密钥做了多余的base64二次编码,导致密钥长度远超Fernet要求的32字节,触发了ValueError。
修复方案
- 移除
decryption方法中多余的base64.urlsafe_b64encode操作,直接将用户输入的密钥字符串转为字节。 - 增加输入清洗,去除密钥可能带有的多余字符(比如示例中的
**)。
修复后的代码
views.py修改后
import base64 from cryptography.fernet import Fernet def decryption(self, key, encrypted_data): # 清洗输入:去除首尾多余字符(如空格、**) cleaned_key = key.strip().strip('*') # 直接转成字节,无需二次编码 key_bytes = bytes(cleaned_key, encoding="utf-8") f = Fernet(key_bytes) # 补充解密逻辑 decrypted_data = f.decrypt(encrypted_data) return decrypted_data def post(self, request): m_file = request.FILES['file'] opt = request.POST.get('choices') if opt == "Decryption": dkey = request.POST.get('dkey') if dkey: # 读取上传文件中的加密内容 encrypted_data = m_file.read() decrypted = self.decryption(dkey, encrypted_data) else: # 处理密钥为空的情况 pass
额外注意事项
- 确保用户输入的密钥与加密时生成的密钥完全一致,避免输入错误(如大小写、多余空格)。
- 原
decryption方法缺失实际的解密逻辑(读取加密内容、调用decrypt方法),需补充完整才能完成解密流程。
内容的提问来源于stack exchange,提问作者Zubairu
相关产品推荐
相关产品推荐

