如何在Flutter/Dart中解密AES加密字符串?

zynd9foi  于 2023-06-03  发布在  Flutter
关注(0)|答案(2)|浏览(1065)

我有一个在Laravel PHP中加密的字符串。加密函数如下。

public function getEncryptedString()
{
    try {
            $m2 = Crypt::encryptString('Thismessagewillbeencrypted', 'theencryptionkey');
        return response()->json([
            'm2' => $m2 ? $m2 : null,
        ], 200);
    } catch (\Exception $e) {
        return response()->json([
            'message' => 'Something went wrong',
            'error' => $e->getMessage()
        ], 400);
    }
}

Flutter/dart如下所示。

import 'dart:convert';
import 'dart:typed_data';

import 'package:pointycastle/export.dart';

Uint8List aesCbcDecrypt(Uint8List key, Uint8List iv, Uint8List cipherText) {
  assert([128, 192, 256].contains(key.length * 8), 'Invalid key length.');
  assert(128 == iv.length * 8, 'Invalid IV length. IV must be 128 bits');
  assert(
    128 == cipherText.length * 8,
    'Invalid cipherText length. cipherText must be 128 bits.',
  );

  // Create a CBC block cipher with AES, and initialize with key and IV

  final cbc = CBCBlockCipher(AESEngine())
    ..init(false, ParametersWithIV(KeyParameter(key), iv)); // false=decrypt

  // Decrypt the cipherText block-by-block

  final paddedPlainText = Uint8List(cipherText.length); // allocate space

  var offset = 0;
  while (offset < cipherText.length) {
    offset += cbc.processBlock(cipherText, offset, paddedPlainText, offset);
  }
  assert(
    offset == cipherText.length,
    'Decryption process did not process the entire cipherText.',
  );

  return paddedPlainText;
}

void decrypter() {
  const encryptedString =
      'eyJpdiI6IjFLc001N25UNzhQNXVMOGxHMGZzeEE9PSIsInZhbHVlIjoiVmU0SGVVL0xFQUtCeW83NkVSSXpOZDRXWUV2allZTEg0c3J4aTJNV1BkST0iLCJtYWMiOiI2Yjk2MGQ3NzAzOTIwMjM5YTc5NTEwMjM2NWFlNDM1MTYwZDI5NzBjNjE4MWQzN2Q0OTE4NmZjNDUxZjNjZGUwIiwidGFnIjoiIn0=';

  const key = 'theencryptionkey';

  final json = jsonDecode(utf8.decode(base64Decode(encryptedString)));

  final decodedKey = base64Decode(key);
  final decodedIV = base64Decode(json['iv'] as String);
  final decodedCipherText = base64Decode(json['value'] as String);

  // Ensure cipherText has the correct length
  final cipherText =
      decodedCipherText.sublist(0, 16); // Take the first 16 bytes (128 bits)

  final result = aesCbcDecrypt(decodedKey, decodedIV, cipherText);

  print(base64.encode(result));
}

encryptedStringthecryptionkeykey加密Thismessagewillbeencrypted后得到的响应String。这当然是为了测试这个过程。

但是在测试用flutter dart代码解密加密字符串时,我不断得到不同的错误。我不明白我做错了什么。
有没有什么解密指南能帮上忙?
我使用的是pointycastle软件包,并遵循this

lyr7nygr

lyr7nygr1#

正如注解中所指出的,您需要了解Crypt中的密钥是如何派生的。
一旦你解决了这个问题,在pointycastle中,你几乎肯定需要将CBC密码 Package 在PKCS7填充密码中(或者你必须自己删除填充)。它还为您处理逐块处理。aesCbcDecrypt的Dart代码简化为:

final cipher = PaddedBlockCipherImpl(
    PKCS7Padding(),
    CBCBlockCipher(AESEngine()),
  )..init(
    false, // decrypt
    PaddedBlockCipherParameters(
      ParametersWithIV(KeyParameter(key), iv),
      null,
    ),
  );

  // a single call to process converts the ciphertext to plaintext (and removes the padding)
  final pt = cipher.process(ct);
z9smfwbn

z9smfwbn2#

我没有使用pointycastle包的经验,但是,我过去使用过encrypt包。
如果您不介意切换软件包,可以尝试以下操作:
1.安装软件包:
flutter pub add encrypt
1.导入包:
import 'package:encrypt/encrypt.dart';
1.用AESMode.cbc创建一个Encrypter示例,因为我看到您正在使用它。
final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
1.使用IV class文档中的构造函数选项之一创建IV
1.使用文档Encrypted class中的一个构造函数,为从Laravel接收到的字符串创建一个Encrypted示例。
1.使用刚刚创建的EncryptedIV示例调用decrypt函数:
final decrypted = encrypter.decrypt(encrypted, iv: iv);
希望这能帮上忙。

相关问题