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被剥离并用于解密。