当前位置: 首页 > 知识库问答 >
问题:

如何用Dart解密AES 256 CBC

闾丘诚
2023-03-14

我想将下面的PHP脚本转换为dart,我尝试了很多案例,但没有任何帮助。

我试过以下代码;但在这里抛出一个异常加密程序。解密方法。

import 'package:encrypt/encrypt.dart' as EncryptPack;
 import 'package:crypto/crypto.dart' as CryptoPack;
 import 'dart:convert' as ConvertPack;
void main(List<String> arguments) {
  var decrypt = extractPayload('$encryptedResopnse');
  print(decrypt);
}
String extractPayload(String encryptedResopnse) {
  if (encryptedResopnse == null) {
    return '';
  }
  var separated = encryptedResopnse.split(':');
  var secret = 'abcd123';
  var data = ConvertPack.base64Decode(separated[0].trim());
  var iv = CryptoPack.sha256.convert(data).toString().substring(0, 16);
  var salt = CryptoPack.sha256.convert(data).toString().substring(16, 32);
  var cipherText = CryptoPack.sha256.convert(data).toString().substring(64);
  print('cipherText : ${cipherText}');
  var ivObj = EncryptPack.IV.fromBase64(iv);
  var generator = PBKDF2(hashAlgorithm: CryptoPack.sha1);
  var hash = generator.generateBase64Key(secret, salt, 2048, 32);
  print('hash : $hash');
  var keyObj = EncryptPack.Key.fromBase64(hash);
  final encrypter = EncryptPack.Encrypter(
      EncryptPack.AES(keyObj, mode: EncryptPack.AESMode.cbc)); // Apply CBC mode
  print(cipherText);
  var firstBase64Decoding = cipherText; // First Base64 decoding
  print(firstBase64Decoding);
  final decrypted = encrypter.decrypt(
      EncryptPack.Encrypted.fromBase64(firstBase64Decoding),
      iv: ivObj);
  return decrypted;
}

演示内容;

初始化aes_密码

$aes_secret='123456ac';

演示内容;

="dBluiiVaHxhRcWJPaEip9kCGXDwufk3mFp8Xe9ioh9UKu6xL CHUZrKvuf3xI7P1vFpvyJ2Vz2Q3ieLEuRHk7NOinZU82FNdE3SOc9D2JTUFkif5ye3rVfQ7O39DpBnV41CduEP0OsASA8cr/RChqhulVHsaw6oUP0mg79M3Jlnpbab0EqlWRQx3k85rcajmov4cYLmsja p2Lyw/BgOTKDf/yw3NWiK73Ot4P3C6urUiFNUCQTaOHCas1Sa8Wl0udQo1viyApuCE9 Ll1SGnUu26uNy5R

class AesEncryption {
  private static $encryptionMethod = 'aes-256-cbc';
  private static $blockSize = 16;
  private static $keySize = 32; // in bytes - so 256 bit for aes-256
  private static $iterations = 2048;

  public static function sign($data, $key) {
    return hash_hmac('sha256', $data, $key);
  }

  /**
   * @param string $encryptedContent
   * @param string $secret
   * @return string
   */
  public static function decrypt(string $encryptedContent, string $secret) {
    if (!$encryptedContent) {
      return "";
    }

    // Separate payload from potential hmac
    $separated = explode(":", trim($encryptedContent));
  
    // Extract HMAC if signed
    $hmac = (isset($separated[1])) ? $separated[1] : null;

    // Convert data-string to array
    $data = base64_decode($separated[0]);

    // Then we remove the iv and salt to fetch the original text
    $iv = substr($data, 0, self::$blockSize);

    //echo($iv);


    $salt = substr($data, self::$blockSize, self::$blockSize);

    // We finally extract  the ciphertext
    $cipherText = substr($data, self::$blockSize * 2);

    // Generate Key
    $key = hash_pbkdf2('sha1', $secret, $salt, self::$iterations, self::$keySize, true);
    
    

    
    // Check https://www.php.net/manual/en/function.openssl-decrypt.php
    return openssl_decrypt($cipherText, self::$encryptionMethod, $key, OPENSSL_RAW_DATA, $iv);
  }

}

共有1个答案

扈高逸
2023-03-14

PBKDF2包的generateBase64键generateKey方法需要一个用于salt的字符串。在这些方法的实现中,salt是UTF8编码的
通常,salt是随机生成的,因此包含与UTF8编码不兼容的字节序列。我们不知道这里使用的盐是如何产生的。但是,它包含与UTF8编码不兼容的字节序列(如随机生成的salt)。因此,在这种情况下,应用的PBKDF2包不适用于密钥派生。在我看来,为盐选择字符串类型是一个糟糕的设计。

另一方面,cryptography包提供了一个Pbkdf2实现,该实现将salt处理为Uint8List,因此是合适的。该库还支持AES/CBC,因此也可以使用该库进行解密。

以下实现将解密已发布的密文:

var encryptedResopnse = 'dBluiiVaHxhRcWJPaEip9kCGXDwufk3mFp8Xe9ioh9UKu6xL+CHUZrKvuf3xI7P1vFpvyyJ2Vz2Q3ieLEuRHk7NOinZU82FNdE3SOc9D2JTUFkif5ye3rVfQ7O39DpBnV41CduEP0OsASA8cr/RChqhulVHsaw6oUP0mg79M3Jlnpbab0EqlWRQx3k85rcajmov4cYLmsja++p2Lyw/BgOTKDf/yw3NWiK73Ot4P3C6urUiFNUCQTaOHCas1Sa8Wl0udQo1viyApuCE9+Ll1SGnUu26uNy5RR55IFLVnAHuIOBDePjdAw3DapAtLFnSd+FrVjYcUuevMMliSy3PHiZU66qdyx8YSn13tYH6KGFxC/kvPsi5dLGorQ1TdNR5fxZGRPNQXEEIwWYSiF8LA0AJzVqpRoXs9PkEseCUnH1Sj5sBQgXQc0RA8vHWf3n2X/cABLEWaRHHlBlZjqjJXl0uKSgAWC3JoelABGSuSCvL3GJhn9SuSV6+jCOftb6UCmw7LzalKB7UNIQPJ1vMtKl3+38RKDwp7a4xpdlln+IPp+R2aGuobuhk9ySSJYN3GCn7MoC/uaCAR0aEYsIHP1BQ+UgOPOsQFZEVdKMrFLJsJ3HtQ1fQxqpPQ13TClWCOyZu+w+1q4W+8CBJuI4l4Em+91aMT4xm7FWB/RhmUN8hfsHk7EATW8CkRGF4zFGKKdeN9zzGM0ViZYv30PARg8W2SJRKoZkaMOgZXtE/8D9fWzrmNDdHBCbMt0yrGycBbn8/b3JLQkcqxzY6VnWrBR1VJ66OB1mH5i6ejDrkxLx5VvkdKf3fcoKEZ/FptZK4zUwXgHJIF/YLChsYUj2mX9Ox18ZZi9vBG9L5vONc0GuQ31FzjwG77yGrJrS4mVi76uaifu7Thd6TiYXuu7OaFBl9+lPMvfHf+wWRqLQbgDoVtOXvND5e4LncWPHZbEjHGwO9I/MnVjMnH6nSbKER63Na8XBUIwsSlJwrswa3fLNInJA1/qGBb9nrVNzKLRfvku1UPvavDP1WxsTEzg0gH8Ui6KzBoBOd9IK/7ZtmSmSug5Ig8GAZ0R/kR7DnSs4ekxKxmcCJ95YVyf9fx0Vlw2oB9iOoUaHM3OITeldfMtoM=';
var secret = 'abcd123';
var decrypt = extractPayload(encryptedResopnse, secret);
print(decrypt);

具有

import 'dart:convert' as ConvertPack;
import 'package:cryptography/cryptography.dart' as CryptographyPack;
...
String extractPayload(String encryptedResopnse, String secret)  {
    if (encryptedResopnse == null) {
      return '';
    }

    // Separate data
    // Note: Authentication not considered (separated: size = 1; see ciphertext and PHP code (hmac derived but unused))
    var separated = encryptedResopnse.split(':');
    var data = ConvertPack.base64Decode(separated[0].trim());
    var iv = data.sublist(0, 16);
    var salt = data.sublist(16, 32);
    var cipherText = data.sublist(32);

    // Derive key
    var generator = CryptographyPack.Pbkdf2(
        macAlgorithm: CryptographyPack.Hmac(CryptographyPack.sha1),
        iterations: 2048,
        bits: 256,
    );
    var hash = generator.deriveBitsSync(
        ConvertPack.utf8.encode(secret),
        nonce: CryptographyPack.Nonce(salt)
    );

    // Decrypt
    var decrypted = CryptographyPack.aesCbc.decryptSync(
        cipherText,
        secretKey: CryptographyPack.SecretKey(hash),
        nonce: CryptographyPack.Nonce(iv));
    var plaintext = ConvertPack.utf8.decode(decrypted);

    return plaintext;
}

并返回结果:

{"nofollow":false,"id":"2226521","title":"When You Say Nothing At All","album":"Ronan","albumID":"237798","artist":"Ronan Keating","artistID":"52715","track":"6","year":"1999","duration":"258.00","coverArt":"323816","ArtistArt":1002340723,"allowoffline":1,"genre":"Pop","AlbumArt":"323816","keywords":["When You Say Nothing At All","Ronan Keating","Ronan"],"languageid":2,"bitrates":"24,256","hexcolor":"#b43931","cleardetails":1,"bitrate":64,"size":"2108905","releasedate":"1999-01-01","explicit":"0","extras":"eyJyZXF1ZXN0dHlwZWlkIjo...","saveprogress":0,"lyrics":"true","is_podcast":0,"is_original":1,"location":"https:\\\/\\\/some audio file\u2019s URL","debugurl":"http:\\\/\\\/some URL","debugurldata":"http:\\\/\\\/some URL","hash":"b1229af8b0078e0b9ec9e203e3b32b7c","plays":"593963","likes":"13705"}

加密包必须在依赖项部分的pubspec.yaml中引用,这里:

cryptography: ^1.4.1
 类似资料:
  • 我正在考虑在我的一个项目中使用dart-protobuf来代替JSON。问题是这个库没有提供任何如何使用它的例子,测试也没有真正的帮助。 我对解析文件的工作方式也有点困惑。 所以我想找一个简单的例子来说明如何在dart中使用这个库。

  • 问题内容: 我正在使用ExtJS框架。我在 JavaScript中 有MD5函数来加密某些JSON。我的后端使用Java,所以我想知道如何使用 Java 解密MD5 Javascript加密? 这是我正在使用的MD5函数的JS等效项: 问题答案: MD5是 哈希 (即单向转换),因此您无法对其进行解密。您可以将已知哈希与从明文计算出的哈希进行比较,以验证输入的有效性。Java已经为此内置了库。我在

  • 问题内容: 创建公司使用的平台的开发人员不再为我们工作,而且我不知道如何从自定义PHP应用程序中检索密码。 当我查看PHPmyAdmin时,密码已加密(例如* 2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19) 如何更改或检索这些? 问题答案: 如果使用正确的加密方法,将无法轻松检索它们。 只需使用新密码重置即可。 编辑: 字符串看起来像它正在使用:

  • 问题内容: 我似乎找不到使用Dart语言在没有密钥的情况下解析json数组的解决方案。我所能找到的就是使用Java。我需要解析这样的内容。 Java解决方案来自这里 如果我有重复的问题,请告知我。谢谢! 问题答案: 只需json.decode正常使用,例如: 碰巧的成员l都将int小号

  • 问题内容: 我想用Java加密和解密文件,我已经阅读了这个URL http://www- users.york.ac.uk/~mal503/lore/pkencryption.htm ,我得到了两个文件,即公共安全证书和私有安全证书文件和private.pem文件,我将这些文件复制并粘贴到当前目录中,并按如下所示编写Java代码,当我运行此文件时,未执行任何加密或解密操作,请查看并告诉我我哪里出了

  • 最近,我一直在尝试教育自己如何使用Vigenere密码进行加密和解密。 我已成功加密该邮件,以下是我为实现加密所采取的步骤: 加密密钥:设置 消息:绝密 步骤1:键的数字表示为18、4、19(使用下表) E:P x k->C是加密函数 D:C x K->P为解密函数 明文:绝密 多谢了。