我正在从 React Native 迁移到 Flutter/Dart。 我有来自 React Native typescript 的以下代码片段:
import CryptoJS from 'crypto-js';
export const decryptSessionKey = (randomKey: string, cipher: string) => {
const iv = randomKey ? randomKey.slice(0, 16) : '';
const decrypted = CryptoJS.AES.decrypt(
cipher,
CryptoJS.enc.Utf8.parse(randomKey),
{
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.NoPadding,
},
);
return decrypted.toString(CryptoJS.enc.Utf8);
};
我将这些代码移动到 flutter/dart 中,如下所示:
import 'dart:math';
import 'package:encrypt/encrypt.dart';
String decryptSessionKey(String randomKey, String cipher) {
final encrypter = Encrypter(AES(Key.fromUtf8(randomKey), mode: AESMode.ctr, padding: null));
var iv = randomKey.substring(0, 16);
final decrypted =
encrypter.decrypt(Encrypted.fromUtf8(cipher), iv: IV.fromUtf8(iv));
return decrypted.toString();
}
给定随 secret 钥为 0QaOUmxpugtnRUTZ6yOSxQeZq47Akiqf
,密码为 piMgUF2ISUl/g7ns2/gZyaWQm6Rdv7x500GD7lMLYxhy14Tg+Bizibvz
。我将在 Typescript 中解密为 54387c3b38150d2a7a1c545167736e701629382648
。
但是,在 Flutter 中,我得到了一个不可读的字符串,例如 ��ʋ�ͻh�0�M��R�Z���YInCXTI*��!�\��-S�f��/�SU��'
我有什么遗漏的吗?预先感谢您!
最佳答案
在 Dart 代码中,密文必须经过 Base64 解码,而不是 UTF8 编码:
final decrypted = encrypter.decrypt(Encrypted.from64(cipher), iv: IV.fromUtf8(iv)); // fromBase64() works also
这在 JavaScript 代码中不是必需的,其中 CryptoJS.AES.decrypt()
隐式将 Base64 编码的密文转换为 CipherParams
对象。
如果这个问题得到解决,解密就可以了!
请注意以下漏洞:在这两个代码中,32 字节 key 的前 16 字节也用作 IV。如果多次应用相同的 key ,则会自动导致 key /IV 对的重复。特别是对于 CRT,这是不安全的,请参阅 Why must IV/key-pairs not be reused in CTR mode?
通常每次加密都会生成一个随机 IV。 IV 不是 secret 的,并且与密文一起发送(通常是串联的)。在解密端,IV被剥离并用于解密。
关于javascript - Dart "encrypt"库在加密后给出不可读的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68849820/