Dart "encrypt" 库在加密后给出不可读的字符串
Dart "encrypt" library gives unreadable string after encryption
我正从 React Native 转向 Flutter/Dart。
我有以下来自 React Native 打字稿的代码片段:
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();
}
给定随机密钥 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 字节密钥的前 16 字节也用作 IV。如果多次应用相同的密钥,这将自动导致重复 key/IV 对。特别是对于 CRT,这是不安全的,请参阅 Why must IV/key-pairs not be reused in CTR mode?
通常每次加密都会生成一个随机 IV。 IV 不是秘密的并且与密文一起发送(通常是串联的)。在解密端,IV被剥离并用于解密。
我正从 React Native 转向 Flutter/Dart。 我有以下来自 React Native 打字稿的代码片段:
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();
}
给定随机密钥 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 字节密钥的前 16 字节也用作 IV。如果多次应用相同的密钥,这将自动导致重复 key/IV 对。特别是对于 CRT,这是不安全的,请参阅 Why must IV/key-pairs not be reused in CTR mode?
通常每次加密都会生成一个随机 IV。 IV 不是秘密的并且与密文一起发送(通常是串联的)。在解密端,IV被剥离并用于解密。