0

0

Fernet密钥格式错误:必须为32字节的URL安全Base64编码字符串

霞舞

霞舞

发布时间:2025-12-27 13:38:11

|

219人浏览过

|

来源于php中文网

原创

Fernet密钥格式错误:必须为32字节的URL安全Base64编码字符串

django后端使用fernet解密时抛出“valueerror: fernet key must be 32 url-safe base64-encoded bytes”,根本原因是前端传入的密钥字符串未正确格式化——它既不是32字节原始二进制数据,也未经url安全base64编码,而是直接将python字节字面量(如b'...')作为字符串硬编码使用。

Fernet是PyCA Cryptography库提供的对称加密方案,其密钥有严格要求:必须是恰好32字节(256位)的随机密钥,并且以URL安全的Base64编码格式(即base64.urlsafe_b64encode)表示为ASCII字符串。而你当前使用的密钥:

"b'VFRkU0hHSEZORFN2dWx1b3VNT213SVE4OTJkLWFiYU1CQU5TdjVGWjhiST0'"

是一个包含引号和前缀b'的普通Python字节对象字符串表示,长度远超32字符,且未经Base64解码,因此Fernet初始化失败。

✅ 正确做法是:统一在服务端生成并安全分发一个合规密钥。推荐流程如下:

  1. 生成合规密钥(服务端一次执行)
    在Python中运行以下代码生成真正可用的密钥:

    import base64
    import os
    
    # 生成32字节加密安全随机数
    raw_key = os.urandom(32)
    # URL安全Base64编码 → 得到44字符ASCII字符串
    fernet_key = base64.urlsafe_b64encode(raw_key).decode()
    print(fernet_key)  # 示例输出:Xv8aQz7GtKl9mNpR2sYjFbWcVdEiHnOqUxZrTgMvP5LsIyJkA4B6C8D0E2F7G9
  2. 前后端共用该密钥字符串

    • 前端(React)中不再拼接b'',直接使用生成的纯字符串:

      const ENCRYPTION_SECRET_KEY = "Xv8aQz7GtKl9mNpR2sYjFbWcVdEiHnOqUxZrTgMvP5LsIyJkA4B6C8D0E2F7G9";
      
      const encryptedPassword = CryptoJS.AES.encrypt(
        formData.password,
        ENCRYPTION_SECRET_KEY
      ).toString();
      
      // 注意:CryptoJS.AES.encrypt(...).toString() 返回的是OpenSSL格式的Base64密文,
      // 而Fernet期望的是原始密文字节 —— 这里存在协议不匹配!见下方关键说明 ⚠️
    • 后端(Django)中同样使用该字符串初始化Fernet:

      Tome
      Tome

      先进的AI智能PPT制作工具

      下载
      from cryptography.fernet import Fernet
      
      FERNET_KEY = b"Xv8aQz7GtKl9mNpR2sYjFbWcVdEiHnOqUxZrTgMvP5LsIyJkA4B6C8D0E2F7G9"
      cipher_suite = Fernet(FERNET_KEY)  # 注意:Fernet接收bytes类型密钥

⚠️ 重要兼容性警告
CryptoJS.AES.encrypt(...).toString() 默认输出 OpenSSL 兼容格式(含盐值、IV 和密文),而 Fernet 是一种封装了AES-CBC+HMAC+盐值+时间戳的高层协议,二者不兼容。直接混用会导致解密失败或安全漏洞。

✅ 推荐解决方案(二选一):

  • 方案A(推荐):前后端均改用Fernet协议
    前端使用支持Fernet的JS库(如 fernet-js):

    npm install fernet-js
    import { Fernet } from 'fernet-js';
    
    const key = new Fernet("Xv8aQz7GtKl9mNpR2sYjFbWcVdEiHnOqUxZrTgMvP5LsIyJkA4B6C8D0E2F7G9");
    const encryptedPassword = key.encrypt(formData.password); // 返回base64字符串
  • 方案B:后端改用AES-CBC解密(需同步IV)
    若坚持用CryptoJS,前端需显式导出IV并传输:

    const iv = CryptoJS.lib.WordArray.random(16);
    const encrypted = CryptoJS.AES.encrypt(formData.password, ENCRYPTION_SECRET_KEY, { iv });
    const encryptedPassword = encrypted.toString();
    const ivBase64 = iv.toString(CryptoJS.enc.Base64);
    // 发送 encryptedPassword 和 ivBase64 到后端

    后端用pycryptodome解密:

    from Crypto.Cipher import AES
    from Crypto.Util.Padding import unpad
    import base64
    
    key = base64.urlsafe_b64decode(ENCRYPTION_SECRET_KEY)
    iv = base64.b64decode(iv_base64)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted = unpad(cipher.decrypt(base64.b64decode(encrypted_data)), AES.block_size)

? 额外注意事项

  • 密钥严禁硬编码在前端源码中(易被逆向获取);生产环境应通过安全API动态获取,或采用HTTPS+Token认证后端加密。
  • request.data["pasword2"] 存在拼写错误(应为password2),会导致字段丢失。
  • Django REST Framework中,修改request.data需先调用.copy()(因默认为只读QueryDict):
    mutable_data = request.data.copy()
    mutable_data["password"] = decrypted_password
    serializer = UserSerializer(data=mutable_data)

综上,修复核心步骤:① 用os.urandom(32) + base64.urlsafe_b64encode生成合规密钥;② 前后端统一加密协议(强烈建议切换至Fernet JS库);③ 修正密钥类型(bytes)、字段名拼写及request.data可变性问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

166

2026.02.04

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6609

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

842

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1092

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

2187

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号