I am trying to perform encryption and decryption using the plug-in that I will show you below.
The decryption works perfectly for me as I have used an AES cipher from my backend and it converts it perfectly.
The problem is the following: When you encrypt, get the result and want to decrypt in dart it does not give the expected result.
I guess the IV and SALT I'm doing it wrong, I hope to get some advice or help, thanks.
crypto.dart
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:pointycastle/export.dart';
class Crypto {
static const String password = "password_here";
static const String algorithm = "AES";
static FortunaRandom? _secureRandom;
/// [decrypt] Method
/// Requires one parameter: ```cipherText```
static String decrypt( String cipherText ) {
CBCBlockCipher cipher = CBCBlockCipher(BlockCipher( algorithm ));
Uint8List ciphertextlist = base64.decode(cipherText);
Uint8List salt = generateRandomBytes(32);
Uint8List key = _generateKey(password, salt);
Uint8List iv = generateRandomBytes(128 ~/ 8);
Uint8List encrypted = ciphertextlist.sublist(20 + 16);
ParametersWithIV<KeyParameter> params = ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, KeyParameter> paddingParams = PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, KeyParameter>(params, null);
PaddedBlockCipherImpl paddingCipher = PaddedBlockCipherImpl(PKCS7Padding(), cipher);
paddingCipher.init(false, paddingParams);
var val = paddingCipher.process(encrypted);
String decrypted = String.fromCharCodes(val);
return decrypted;
}
/// [encrypt] Method
/// Requieres one parameter: ```plainText```
static String encrypt( String plainText ) {
final CBCBlockCipher cbcCipher = CBCBlockCipher(BlockCipher( algorithm ));
List<int> data = utf8.encode( plainText );
Uint8List iv = generateRandomBytes(128 ~/ 8);
Uint8List salt = generateRandomBytes(32);
Uint8List key = _generateKey(password, Uint8List.fromList(salt));
final ParametersWithIV<KeyParameter> ivParams = ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
final PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, KeyParameter> paddingParams =PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, KeyParameter>(ivParams, null);
final PaddedBlockCipherImpl paddedCipher = PaddedBlockCipherImpl(PKCS7Padding(), cbcCipher);
paddedCipher.init(true, paddingParams);
try {
return base64.encode(paddedCipher.process(Uint8List.fromList(data)));
} catch (e) {
return '';
}
}
/// [_generateKey] Method
/// Generates the key to Uint8List for encryption and description.
static Uint8List _generateKey(String passphrase, Uint8List salt) {
Uint8List passphraseInt8List = Uint8List.fromList(passphrase.codeUnits);
KeyDerivator derivator = PBKDF2KeyDerivator(HMac(SHA1Digest(), 64));
Pbkdf2Parameters params = Pbkdf2Parameters(salt, 65556, 32);
derivator.init(params);
return derivator.process(passphraseInt8List);
}
static Uint8List generateRandomBytes(int numBytes) {
if (_secureRandom == null) {
_secureRandom = FortunaRandom();
final seedSource = Random.secure();
final seeds = <int>[];
for (int i = 0; i < 32; i++) {
seeds.add(seedSource.nextInt(256));
}
_secureRandom!.seed(KeyParameter(Uint8List.fromList(seeds)));
}
return _secureRandom!.nextBytes(numBytes);
}
}
crypto_test.dart
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'models/crypto.dart';
void main() {
test('Descrypt Data', () async {
if( kDebugMode ){
String cipherText = "2FA4qsjxXzk5kp6cnbv8QrlcKPyxO/PihUky8HVkNf2hRlIAq25yCc1RbidvM7chE7JzuZUuNLIeoiEKr+vWx4AhSQclh94iC4eZMIGjyFllOn8qZl2zM+cYMuVp0zS5klVIgefBDd+SJSvsIElCBIAmsnY=";
final decryptToHuman = Crypto.decrypt( cipherText );
print( decryptToHuman );
}
});
test('Encrypt Data', () async {
if( kDebugMode ){
Map<String, dynamic> toCipherData = {
'email': 'Example@example.com',
'passowrd': '12345678'
};
final String json = jsonEncode( toCipherData );
final cipherText = Crypto.encrypt( json );
print( "Texto cifrado: $cipherText" );
}
});
}
Error debug console:
Invalid argument(s): Input data length must be a multiple of cipher's block size
PaddedBlockCipherImpl.process
package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:60
Crypto.decrypt
test\…\models\crypto.dart:38
main.<fn>
test\…\crypto\encrypt_test.dart:10
2
✖ Descrypt Data
Exited (1)
The solution to my problem was solved in this way.
Thanks for your help.
In encrypt method
Uint8List encryptedTextBytes = paddingCipher.process( plainTextBytes );
final buffer = Uint8List(salt.length + iv.length + encryptedTextBytes.length);
List.copyRange(buffer, 0, salt, 0, salt.length);
List.copyRange(buffer, salt.length, iv, 0, iv.length);
List.copyRange(buffer, salt.length+iv.length, encryptedTextBytes, 0, encryptedTextBytes.length);