如何在 Dart 中创建 Fernet 加密算法

How to create a Fernet encryption algorithm in Dart

提问人:Zak345 提问时间:11/16/2023 更新时间:11/17/2023 访问量:44

问:

我需要帮助在 dart 中创建 Fernet 加密函数,这是我制作的代码:

import 'package:encrypt/encrypt.dart' as encrypt_package;


String encryptFernet(String text) {
  final encrypt_package.Key key = encrypt_package.Key.fromUtf8('c1563NcXz90uGYpMqpfm_k10rOLVF5Q37AY6D016n_4=');
  final encrypt_package.Fernet fernet = encrypt_package.Fernet(key);

  final encrypt_package.Encrypter encrypter = encrypt_package.Encrypter(fernet);

  final encrypt_package.Encrypted encrypted = encrypter.encrypt(text);
  return encrypted.base64;
}

我希望此代码与此 python 代码匹配:

def encrypt_fernet(text):
    key_fernet = b'c1563NcXz90uGYpMqpfm_k10rOLVF5Q37AY6D016n_4='
    fernet = Fernet(key_fernet)
    encrypted = fernet.encrypt(text.encode())
    return encrypted

但是我收到此错误Exception has occurred. StateError (Bad state: Fernet key must be 32 url-safe base64-encoded bytes.)

DART 加密

评论

1赞 Topaco 11/16/2023
错误消息已经指出,缺少 Base64url 解码,尝试(显然不仅可以解码标准 Base64,还可以解码 Base64url 数据)。在我的机器上工作。key = encrypt_package.Key.fromBase64('c1563NcXz90uGYpMqpfm_k10rOLVF5Q37AY6D016n_4=')
1赞 President James K. Polk 11/16/2023
这可能看起来很简单,但我认为值得回答,@Topaco。

答:

0赞 Topaco 11/17/2023 #1

Fernet 密钥是 Base64url 编码的 32 字节密钥(根据 RFC 4648 第 5 节)。错误消息:错误状态:Fernet 密钥必须是 32 个 url 安全的 base64 编码字节也指出了这一点。您发布的示例密钥与此规范相对应。

Base64url 编码的密钥必须使用 Key.fromBase64() 导入(您执行 UTF-8 编码的方法 Key.fromUtf8() 执行 UTF-8 编码,这在这种情况下是错误的)。请注意,它同时支持 Base64 和 Base64url,并且在这两种情况下都必须使用 paddig (with )。Key.fromBase64()=

另一个小问题是,您的代码会生成一个 Base64 编码的令牌,但 Fernet 也指定 Base64url 作为令牌的编码。Base64url 编码的令牌(带填充)可以从 Base64 编码的令牌(带填充)生成,只需将 和 替换为 (s. Base64)。+-/_

完整代码:

import 'package:encrypt/encrypt.dart' as encrypt_package;

...

String encryptFernet(String text) {
  final encrypt_package.Key key = encrypt_package.Key.fromBase64('c1563NcXz90uGYpMqpfm_k10rOLVF5Q37AY6D016n_4=');   // import Fernet key (32 bytes, Base64url encoded)
  final encrypt_package.Fernet fernet = encrypt_package.Fernet(key);
  final encrypt_package.Encrypter encrypter = encrypt_package.Encrypter(fernet);
  final encrypt_package.Encrypted encrypted = encrypter.encrypt(text);
  return encrypted.base64.replaceAll("+","-").replaceAll("/", "_");                                                 // Base64url encode
}