AES 128 CFB解密Flutter/dart

0kjbasz6  于 2023-10-13  发布在  Flutter
关注(0)|答案(1)|浏览(203)

我有一个AES 128 CFB加密字符串,需要解密它。
加密字符串:NpevHdSNWoXzXXzndH4WgRnM6QChqPwI8wguZ3iCOzGo4sG1RtHRiGGMkPcR2EaHOqJ22LQUcTM2BLKe6rQAdHJ58E/E/OpCY5wV45AYqJIgB2Yx4GbfeNeo0Do0AGhfVdbFFTybSElpJoLVdX5a4KWQVifKrw
密钥:bKxh 4vz 1 WpDnMlK 7
我有JavaScript函数,可以使用crypto-js库成功解密

  1. const decryptURL = src => {
  2. var key = 'bKxh4vz1WpDnMlK7';
  3. var base64data = CryptoJS.enc.Base64.parse(src);
  4. var encrypted = new CryptoJS.lib.WordArray.init(
  5. base64data.words.slice(4),
  6. base64data.sigBytes - 16,
  7. );
  8. var iv = new CryptoJS.lib.WordArray.init(base64data.words.slice(0, 4));
  9. var cipher = CryptoJS.lib.CipherParams.create({ciphertext: encrypted});
  10. var decrypted = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(key), {
  11. iv: iv,
  12. mode: CryptoJS.mode.CFB,
  13. padding: CryptoJS.pad.NoPadding,
  14. });
  15. return decrypted.toString(CryptoJS.enc.Utf8);
  16. };

我已经尝试了许多解决方案,但仍然没有运气解密它,下面是我的解密功能

  1. extension StringEx on String {
  2. Map<dynamic, dynamic> get decryptData {
  3. final key = encrypt.Key.fromUtf8('bKxh4vz1WpDnMlK7');
  4. final base64data = base64.decode(base64.normalize(this));
  5. final encrypted = base64data.sublist(4, base64data.length - 16); // Assuming 16 bytes are the IV in CryptoJS
  6. final iv = base64data.sublist(0, 4); // Assuming 16 bytes are the IV in CryptoJS
  7. final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cfb64, padding: null));
  8. final decryptedBytes = encrypter.decrypt(encrypt.Encrypted(encrypted), iv: encrypt.IV(iv));
  9. final dataMap = jsonDecode(decryptedBytes);
  10. return dataMap;
  11. }
  12. }

任何帮助将不胜感激,非常感谢!

gpfsuwkq

gpfsuwkq1#

CryptoJS和Dart代码不兼容,因为1.所使用的段大小是不同的,并且2.与CryptoJS代码不同,Dart代码只能处理长度为段大小的整数倍的明文。

  • 关于1:在CFB模式下,始终存在相关联的段大小。段大小是每个加密步骤加密的位数,并且通常附加到标识符,例如,CFB-128指定CFB的段大小为128位。

CryptoJS代码使用128位的段大小(CFB-128),而Dart代码使用64位的段大小(CFB-64)。段的大小不能在任何一个库中更改,所以在Dart端,encrypt 库不能用于解密CryptoJS代码的密文。
因此,在Dart方面,需要另一个也支持CFB-128的库。一种可能性是 PointyCastle(注意 encrypt 库是 PointyCastle 的子功能的 Package 器,所以实际上直接使用相同的库)。

  • 关于2:CFB模式是流密码模式,因此可以加密任意长度的明文而无需填充。

然而,PointyCastle(以及 encrypt 库)的CFB实现只能加密长度为段大小的整数倍的明文,即:对于CFB-128,为块大小的整数倍。这通常需要额外的填充,这是低效的,实际上不应该是必要的。
相反,由于这个约束,要用 PointyCastle 解密CryptoJS代码的密文,密文必须在解密之前填充到块大小的整数倍。
为此,可以使用任何填充,例如。零填充(后者是足够的,因为关于填充字节的长度信息由密文的原始长度给出,因此不需要包含在填充中)。
在解密之后,明文必须被取消填充(即,缩短为密文的原始长度)。
使用 PointyCastle 实现CryptoJS密文的一种可能实现是:

  1. import 'dart:convert';
  2. import 'dart:typed_data';
  3. import 'package:pointycastle/export.dart';
  4. ...
  5. final dataB64 = "NpevHdSNWoXzXXzndH4WgRnM6QChqPwI8wguZ3iCOzGo4sG1RtHRiGGMkPcR2EaHOqJ22LQUcTM2BLKe6rQAdHJ58E/E/OpCY5wV45AYqJIgB2Yx4GbfeNeo0Do0AGhfVdbFFTybSElpJoLVdX5a4KWQVifKrw";
  6. print(dataB64.decryptData);
  7. ...
  8. extension StringEx on String {
  9. Map<dynamic, dynamic> get decryptData {
  10. // Get key
  11. final key = utf8.encode('bKxh4vz1WpDnMlK7');
  12. // Separate IV and ciphertext
  13. const aesBlockSize = 16;
  14. final base64data = base64.decode(base64.normalize(this));
  15. final encrypted = base64data.sublist(aesBlockSize);
  16. final iv = base64data.sublist(0, aesBlockSize);
  17. // Zero pad ciphertext
  18. final padLength = (aesBlockSize - (encrypted.length % aesBlockSize)) % aesBlockSize;
  19. final cipherBytesPadded = Uint8List(encrypted.length + padLength)..setAll(0, encrypted);
  20. // Decrypt
  21. final params = ParametersWithIV(KeyParameter(key), iv);
  22. final cipher = BlockCipher("AES/CFB-128")..init(false, params);
  23. final plainBytesPadded = Uint8List(cipherBytesPadded.length);
  24. for (var offset = 0; offset < cipherBytesPadded.length;) {
  25. final len = cipher.processBlock(cipherBytesPadded, offset, plainBytesPadded, offset);
  26. offset += len;
  27. }
  28. // Truncate plaintext to ciphertext size
  29. final plainBytes = plainBytesPadded.sublist(0, encrypted.length);
  30. return jsonDecode(utf8.decode(plainBytes)); // {error: Signature invalid, hash: 6c0ccf462bee20812224664ad0a8cc27, str: null10131696322798salt}
  31. }
  32. }
展开查看全部

相关问题