在网络上使用cryptoJS AES解密Flutter上的AES输入

时间:2019-02-25 10:39:08

标签: encryption flutter aes cryptojs

在网络上,我正在使用CryptoJS来解密JS:

  

CryptoJS.AES.decrypt(inputBase64,key).toString(CryptoJS.enc.Utf8);

示例:

  

输入:“ tzfwnxVwE / qNoaWRRfqLp11ZyhB4UtKO + 0 / Lvv5B7eE =“   密钥:“ 20190225165436_15230006321670000_15510884759030000”

在颤抖的情况下,我找不到任何要用任何长度的密钥解密的库。

我知道“对于AES,NIST选择了Rijndael家族的三个成员,每个成员的块大小为128位,但是具有三个不同的密钥长度:128、192和256位。 “

但是我不知道如何将任何长度的密钥转换为128位格式?

4 个答案:

答案 0 :(得分:1)

当您将字符串作为密钥传递给CryptoJS时,它将字符串视为密码短语,并使用密钥派生函数(在本例中为PBKDF2)从中生成密钥。它生成一个256位密钥和一个128位初始化向量(IV)。然后,将其用于加密/解密。您还需要找出CryptoJS使用哪种链接方法(可能是密码块链接(CBC))以及它使用哪种填充方法(以确保纯文本是128位块的整数-可能是PKCS#7)。 / p>

CryptoJS具有这种“即开即用”的模式,但是尚不清楚它在做什么—您需要阅读源代码或搜索文档。

当试图在两种系统/语言之间进行互操作时,最好是由您自己负责,而不是让一端做出任意决定。这样,您可以确保两端的设置相同。

因此,您可以选择:

  • 使用PBKDF2从字符串生成128位密钥和128位IV 密码-例如9999发
  • 使用PKCS#7填充
  • 在CBC模式下使用AES

pointycastle软件包在Dart中支持以上所有内容。看起来CryptoJS也支持所有这些。

从密码短语开始,确保可以在JS和Dart中生成相同的密钥和IV。然后继续创建密码。

也请记住,从不使用相同的密钥/ IV对加密两条消息。例如,使用消息序列号来稍稍更改每条消息的IV。

答案 1 :(得分:0)

我搜索了尖尖的图书馆 但是对我来说工作太少了 您是否有用dart编写的任何类似示例,并且在网络上使用cryptoJS

答案 2 :(得分:0)

使用nodejs脚本进行样本加密:

var key = CryptoJS.PBKDF2("123456", "123456", {
  keySize: 256 / 32
});
var iv = CryptoJS.PBKDF2("123456", "123456", {
  keySize: 128 / 32
});

var encrypted = CryptoJS.AES.encrypt('my message', key, { iv: iv,
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.Pkcs7
}).toString();

使用飞镖解脱


import 'package:encrypt/encrypt.dart' as aes;
import 'package:crypto/crypto.dart';
import 'package:hex/hex.dart';
import 'package:password_hash/pbkdf2.dart';

void main(List<String> arguments) {
  String encrypted = 'HbsmGAigiIWmU3MNZAf8+w==';

  final generator = PBKDF2(hashAlgorithm: sha1);
  final key = aes.Key.fromBase16(HEX.encode(generator.generateKey("123456", "123456", 1, 32)));
  final iv = aes.IV.fromBase16(HEX.encode(generator.generateKey("123456", "123456", 1, 16)));

  final encrypter = aes.Encrypter(aes.AES(key, mode: aes.AESMode.cbc, padding: 'PKCS7'));

  final decrypted = encrypter.decrypt64(encrypted, iv:iv);
  print(decrypted);
}

答案 3 :(得分:0)

import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:tuple/tuple.dart';
import 'package:encrypt/encrypt.dart' as encrypt;

String encryptAESCryptoJS(String plainText, String passphrase) {
try {
    final salt = genRandomWithNonZero(8);
    var keyndIV = deriveKeyAndIV(passphrase, salt);
    final key = encrypt.Key(keyndIV.item1);
    final iv = encrypt.IV(keyndIV.item2);

    final encrypter = encrypt.Encrypter(
        encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
    final encrypted = encrypter.encrypt(plainText, iv: iv);
    Uint8List encryptedBytesWithSalt = Uint8List.fromList(
        createUint8ListFromString("Salted__") + salt + encrypted.bytes);
    return base64.encode(encryptedBytesWithSalt);
} catch (error) {
    throw error;
}
}

String decryptAESCryptoJS(String encrypted, String passphrase) {
try {
    Uint8List encryptedBytesWithSalt = base64.decode(encrypted);

    Uint8List encryptedBytes =
        encryptedBytesWithSalt.sublist(16, encryptedBytesWithSalt.length);
    final salt = encryptedBytesWithSalt.sublist(8, 16);
    var keyndIV = deriveKeyAndIV(passphrase, salt);
    final key = encrypt.Key(keyndIV.item1);
    final iv = encrypt.IV(keyndIV.item2);

    final encrypter = encrypt.Encrypter(
        encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
    final decrypted =
        encrypter.decrypt64(base64.encode(encryptedBytes), iv: iv);
    return decrypted;
} catch (error) {
    throw error;
}
}

Tuple2<Uint8List, Uint8List> deriveKeyAndIV(String passphrase, Uint8List salt) {
var password = createUint8ListFromString(passphrase);
Uint8List concatenatedHashes = Uint8List(0);
Uint8List currentHash = Uint8List(0);
bool enoughBytesForKey = false;
Uint8List preHash = Uint8List(0);

while (!enoughBytesForKey) {
    int preHashLength = currentHash.length + password.length + salt.length;
    if (currentHash.length > 0)
    preHash = Uint8List.fromList(
        currentHash + password + salt);
    else
    preHash = Uint8List.fromList(
        password + salt);

    currentHash = md5.convert(preHash).bytes;
    concatenatedHashes = Uint8List.fromList(concatenatedHashes + currentHash);
    if (concatenatedHashes.length >= 48) enoughBytesForKey = true;
}

var keyBtyes = concatenatedHashes.sublist(0, 32);
var ivBtyes = concatenatedHashes.sublist(32, 48);
return new Tuple2(keyBtyes, ivBtyes);
}

Uint8List createUint8ListFromString(String s) {
var ret = new Uint8List(s.length);
for (var i = 0; i < s.length; i++) {
    ret[i] = s.codeUnitAt(i);
}
return ret;
}

Uint8List genRandomWithNonZero(int seedLength) {
final random = Random.secure();
const int randomMax = 245;
final Uint8List uint8list = Uint8List(seedLength);
for (int i=0; i < seedLength; i++) {
    uint8list[i] = random.nextInt(randomMax)+1;
}
return uint8list;
}

用法

import 'package:app/utils/cryptojs_aes_encryption_helper.dart'; String plainText = 'PlainText is Me'; var encrypted = encryptAESCryptoJS(plainText, "password"); var decrypted = decryptAESCryptoJS(encrypted, "password");