Dart 适用于颤振和javascript的兼容AES加密和解密
我正在尝试用flatter和Javascript编写两个函数,我可以在整个项目中使用它们在交换数据时使用AES加密或解密数据。 对于颤振,我根据说明使用pointycastle包 这两种解决方案在各自的环境中都能很好地工作,但是,flutter或Javascript散列无法交换,它们不会解密。我的猜测是字符编码与此有关,因此base64的大小差异很大。有没有人有办法让这项工作一起进行?谢谢Dart 适用于颤振和javascript的兼容AES加密和解密,dart,flutter,cryptojs,pointycastle,Dart,Flutter,Cryptojs,Pointycastle,我正在尝试用flatter和Javascript编写两个函数,我可以在整个项目中使用它们在交换数据时使用AES加密或解密数据。 对于颤振,我根据说明使用pointycastle包 这两种解决方案在各自的环境中都能很好地工作,但是,flutter或Javascript散列无法交换,它们不会解密。我的猜测是字符编码与此有关,因此base64的大小差异很大。有没有人有办法让这项工作一起进行?谢谢 有没有人有办法把这两种算法结合起来?主要问题是这两种密钥派生算法是不同的。 在Dart/PC代码中,您使
有没有人有办法把这两种算法结合起来?主要问题是这两种密钥派生算法是不同的。 在Dart/PC代码中,您使用的是PBKDF2,但
CryptoJS.AES.encrypt
使用的KDF是OpenSSL的
您可以使用PC在Dart中实现与EVP_BytesToKey相当的EVP_
。但是,更改JavaScript代码以使用PBKDF2派生其密钥可能会更容易,PBKDF2已经存在。这将为您提供一把钥匙和一个IV供您使用:
导入'dart:convert';
导入“dart:math”;
导入“dart:键入的_数据”;
导入“包:crypto/crypto.dart”;
导入“package:tuple/tuple.dart”;
导入“package:encrypt/encrypt.dart”作为加密;
字符串EncryptAESCryptJS(字符串明文、字符串密码短语){
试一试{
最终盐=非零(8);
var keyndIV=派生Keyandiv(密码短语,salt);
最终密钥=encrypt.key(keyndIV.item1);
最终iv=encrypt.iv(keyndIV.item2);
最终加密程序=encrypt.encrypter(
encrypt.AES(密钥,模式:encrypt.AESMode.cbc,填充:“PKCS7”);
最终加密=encrypter.encrypt(明文,iv:iv);
Uint8List EncryptedBytesWithAlt=Uint8List.fromList(
createUint8ListFromString(“Salted_u_;”)+salt+encrypted.bytes);
返回base64.encode(EncryptedBytesWithAlt);
}捕获(错误){
投掷误差;
}
}
字符串解密加密JS(字符串加密,字符串密码短语){
试一试{
UINT8列表EncryptedBytesWithAlt=base64.解码(加密);
UINT8列出加密字节=
EncryptedBytesWithAlt.sublist(16,EncryptedBytesWithAlt.length);
最终salt=加密字节和盐子列表(8,16);
var keyndIV=派生Keyandiv(密码短语,salt);
最终密钥=encrypt.key(keyndIV.item1);
最终iv=encrypt.iv(keyndIV.item2);
最终加密程序=encrypt.encrypter(
encrypt.AES(密钥,模式:encrypt.AESMode.cbc,填充:“PKCS7”);
最终解密=
encrypter.decrypt64(base64.encode(encryptedBytes),iv:iv;
返回解密;
}捕获(错误){
投掷误差;
}
}
Tuple2-deriveKeyAndIV(字符串密码短语,UINT8列表){
var password=createUint8ListFromString(密码短语);
Uint8List CONNECTEDHASHES=Uint8List(0);
Uint8List currentHash=Uint8List(0);
bool-enoughBytesForKey=false;
Uint8List preHash=Uint8List(0);
而(!enoughBytesForKey){
int preHashLength=currentHash.length+password.length+salt.length;
如果(currentHash.length>0)
preHash=Uint8List.fromList(
currentHash+密码+salt);
其他的
preHash=Uint8List.fromList(
密码+盐);
currentHash=md5.convert(preHash).bytes;
concatenatedHashes=Uint8List.fromList(concatenatedHashes+currentHash);
如果(concatenatedHashes.length>=48)enoughBytesForKey=true;
}
var keyBtyes=concatenatedHashes.sublist(0,32);
var ivBtyes=concatenatedHashes.sublist(32,48);
返回新的Tuple2(keyBtyes,ivBtyes);
}
Uint8List createUint8ListFromString(字符串s){
var ret=新UINT8列表(s.长度);
对于(变量i=0;i
请参考下面的链接了解解决方案
对于那些正在寻找C#(RijndaelManaged&Rfc2898DeriveBytes)和Flatter解决方案的人,请检查此软件包:我尝试了很多次,但它的加密与CryptoJS上的加密不同。我希望这有帮助:这个问题解决了吗。如果解决了,请公布答案。我们将不胜感激。顺便说一句,您的助手代码中的前4个函数已经在Dart中提供了。第一个是
String.codeUnits()
,第二个是hex.decode()
来自package:convert
,第三个是Uint8List.fromList()
,第四个是hex.encode()
来自package:convert
救了我的命(Y)
import 'dart:convert';
import 'dart:typed_data';
import "package:pointycastle/export.dart";
import "./convert_helper.dart";
// AES key size
const KEY_SIZE = 32; // 32 byte key for AES-256
const ITERATION_COUNT = 1000;
class AesHelper {
static const CBC_MODE = 'CBC';
static const CFB_MODE = 'CFB';
static Uint8List deriveKey(dynamic password,
{String salt = '',
int iterationCount = ITERATION_COUNT,
int derivedKeyLength = KEY_SIZE}) {
if (password == null || password.isEmpty) {
throw new ArgumentError('password must not be empty');
}
if (password is String) {
password = createUint8ListFromString(password);
}
Uint8List saltBytes = createUint8ListFromString(salt);
Pbkdf2Parameters params =
new Pbkdf2Parameters(saltBytes, iterationCount, derivedKeyLength);
KeyDerivator keyDerivator =
new PBKDF2KeyDerivator(new HMac(new SHA256Digest(), 64));
keyDerivator.init(params);
return keyDerivator.process(password);
}
static Uint8List pad(Uint8List src, int blockSize) {
var pad = new PKCS7Padding();
pad.init(null);
int padLength = blockSize - (src.length % blockSize);
var out = new Uint8List(src.length + padLength)..setAll(0, src);
pad.addPadding(out, src.length);
return out;
}
static Uint8List unpad(Uint8List src) {
var pad = new PKCS7Padding();
pad.init(null);
int padLength = pad.padCount(src);
int len = src.length - padLength;
return new Uint8List(len)..setRange(0, len, src);
}
static String encrypt(String password, String plaintext,
{String mode = CBC_MODE}) {
Uint8List derivedKey = deriveKey(password);
KeyParameter keyParam = new KeyParameter(derivedKey);
BlockCipher aes = new AESFastEngine();
var rnd = FortunaRandom();
rnd.seed(keyParam);
Uint8List iv = rnd.nextBytes(aes.blockSize);
BlockCipher cipher;
ParametersWithIV params = new ParametersWithIV(keyParam, iv);
switch (mode) {
case CBC_MODE:
cipher = new CBCBlockCipher(aes);
break;
case CFB_MODE:
cipher = new CFBBlockCipher(aes, aes.blockSize);
break;
default:
throw new ArgumentError('incorrect value of the "mode" parameter');
break;
}
cipher.init(true, params);
Uint8List textBytes = createUint8ListFromString(plaintext);
Uint8List paddedText = pad(textBytes, aes.blockSize);
Uint8List cipherBytes = _processBlocks(cipher, paddedText);
Uint8List cipherIvBytes = new Uint8List(cipherBytes.length + iv.length)
..setAll(0, iv)
..setAll(iv.length, cipherBytes);
return base64.encode(cipherIvBytes);
}
static String decrypt(String password, String ciphertext,
{String mode = CBC_MODE}) {
Uint8List derivedKey = deriveKey(password);
KeyParameter keyParam = new KeyParameter(derivedKey);
BlockCipher aes = new AESFastEngine();
Uint8List cipherIvBytes = base64.decode(ciphertext);
Uint8List iv = new Uint8List(aes.blockSize)
..setRange(0, aes.blockSize, cipherIvBytes);
BlockCipher cipher;
ParametersWithIV params = new ParametersWithIV(keyParam, iv);
switch (mode) {
case CBC_MODE:
cipher = new CBCBlockCipher(aes);
break;
case CFB_MODE:
cipher = new CFBBlockCipher(aes, aes.blockSize);
break;
default:
throw new ArgumentError('incorrect value of the "mode" parameter');
break;
}
cipher.init(false, params);
int cipherLen = cipherIvBytes.length - aes.blockSize;
Uint8List cipherBytes = new Uint8List(cipherLen)
..setRange(0, cipherLen, cipherIvBytes, aes.blockSize);
Uint8List paddedText = _processBlocks(cipher, cipherBytes);
Uint8List textBytes = unpad(paddedText);
return new String.fromCharCodes(textBytes);
}
static Uint8List _processBlocks(BlockCipher cipher, Uint8List inp) {
var out = new Uint8List(inp.lengthInBytes);
for (var offset = 0; offset < inp.lengthInBytes;) {
var len = cipher.processBlock(inp, offset, out, offset);
offset += len;
}
return out;
}
}
import "dart:typed_data";
import 'dart:convert';
import 'package:convert/convert.dart' as convert;
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 createUint8ListFromHexString(String hex) {
var result = new Uint8List(hex.length ~/ 2);
for (var i = 0; i < hex.length; i += 2) {
var num = hex.substring(i, i + 2);
var byte = int.parse(num, radix: 16);
result[i ~/ 2] = byte;
}
return result;
}
Uint8List createUint8ListFromSequentialNumbers(int len) {
var ret = new Uint8List(len);
for (var i = 0; i < len; i++) {
ret[i] = i;
}
return ret;
}
String formatBytesAsHexString(Uint8List bytes) {
var result = new StringBuffer();
for (var i = 0; i < bytes.lengthInBytes; i++) {
var part = bytes[i];
result.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
}
return result.toString();
}
List<int> decodePEM(String pem) {
var startsWith = [
"-----BEGIN PUBLIC KEY-----",
"-----BEGIN PRIVATE KEY-----",
"-----BEGIN ENCRYPTED MESSAGE-----",
"-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: React-Native-OpenPGP.js 0.1\r\nComment: http://openpgpjs.org\r\n\r\n",
"-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: React-Native-OpenPGP.js 0.1\r\nComment: http://openpgpjs.org\r\n\r\n",
];
var endsWith = [
"-----END PUBLIC KEY-----",
"-----END PRIVATE KEY-----",
"-----END ENCRYPTED MESSAGE-----",
"-----END PGP PUBLIC KEY BLOCK-----",
"-----END PGP PRIVATE KEY BLOCK-----",
];
bool isOpenPgp = pem.indexOf('BEGIN PGP') != -1;
for (var s in startsWith) {
if (pem.startsWith(s)) {
pem = pem.substring(s.length);
}
}
for (var s in endsWith) {
if (pem.endsWith(s)) {
pem = pem.substring(0, pem.length - s.length);
}
}
if (isOpenPgp) {
var index = pem.indexOf('\r\n');
pem = pem.substring(0, index);
}
pem = pem.replaceAll('\n', '');
pem = pem.replaceAll('\r', '');
return base64.decode(pem);
}
List<int> decodeHex(String hex) {
hex = hex
.replaceAll(':', '')
.replaceAll('\n', '')
.replaceAll('\r', '')
.replaceAll('\t', '');
return convert.hex.decode(hex);
}
var AESKey = "20190225165436_15230006321670000"
cc = CryptoJS.AES.encrypt( ("abcdef ha ha "), AESKey, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ).toString()
CryptoJS.AES.decrypt(cc, AESKey).toString(CryptoJS.enc.Utf8); //return abcdef ha ha
var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
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;
}