0

0

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

霞舞

霞舞

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

|

199人浏览过

|

来源于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:

      Looka
      Looka

      AI辅助Logo和品牌设计工具

      下载
      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可变性问题。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

708

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

625

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

736

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

616

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1234

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

573

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

695

2023.08.11

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

27

2025.12.26

热门下载

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

精品课程

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

共58课时 | 3万人学习

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

共12课时 | 0.9万人学习

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

共12课时 | 1万人学习

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

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