Decrypt AES/CBC/PKCS5Padding Encryption in Dart Decrypt AES/CBC/PKCS5Padding Encryption in Dart dart dart

Decrypt AES/CBC/PKCS5Padding Encryption in Dart


The code can be simplified by using existing Dart libraries for the conversion binary to hex and vice versa. PointyCastle also supports the (PKCS7) padding, so that a custom implementation is not necessary, which also reduces the code. On the Internet you can find several dart implementations for AES/CBC/PKCS7Padding in combination with PBKDF2 that use PointyCastle, e.g. here and here.

A possible Dart implementation for decryption using the pointycastle and convert package is e.g. (for simplicity without exception handling):

import 'dart:typed_data';import "package:pointycastle/export.dart";import 'package:convert/convert.dart';import 'dart:convert';...static Uint8List decrypt(Uint8List ciphertext, Uint8List key, Uint8List iv) {  CBCBlockCipher cipher = new CBCBlockCipher(new AESFastEngine());  ParametersWithIV<KeyParameter> params = new ParametersWithIV<KeyParameter>(new KeyParameter(key), iv);  PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null> paddingParams = new PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>(params, null);  PaddedBlockCipherImpl paddingCipher = new PaddedBlockCipherImpl(new PKCS7Padding(), cipher);  paddingCipher.init(false, paddingParams);  return paddingCipher.process(ciphertext);}static Uint8List generateKey(Uint8List salt, Uint8List passphrase){  KeyDerivator derivator = new PBKDF2KeyDerivator(new HMac(new SHA1Digest(), 64));  Pbkdf2Parameters params = new Pbkdf2Parameters(salt, 5, 16);  derivator.init(params);  return derivator.process(passphrase);}

With the posted test data:

String saltHex = '00000000000000000000000000000000';String ivHex = '00000000000000000000000000000000';String passphraseUtf8 = 'Mayur12354673645';String ciphertextBase64 = "XjxCg0KK0ZDWa4XMFhykIw==";Uint8List salt = hex.decode(saltHex);Uint8List passphrase = utf8.encode(passphraseUtf8);Uint8List key = generateKey(salt, passphrase);Uint8List ciphertext = base64.decode(ciphertextBase64);Uint8List iv = hex.decode(ivHex);Uint8List decrypted = decrypt(ciphertext, key, iv);print(utf8.decode(decrypted)); // This is working

the ciphertext can be decrypted to: This is working.

An alternative to PointyCastle is the cryptography package, which allows even a more compact implementation in the current case:

import 'package:cryptography/cryptography.dart';import 'package:convert/convert.dart';import 'dart:convert';import 'dart:typed_data';...static Uint8List decrypt(Uint8List ciphertext, Uint8List key, Uint8List iv) {  SecretKey secretKey = new SecretKey(key);  Nonce nonce = new Nonce(iv);  Uint8List decrypted = aesCbc.decryptSync(ciphertext, secretKey: secretKey, nonce: nonce);  return decrypted;}static Uint8List generateKey(Uint8List salt, Uint8List passphrase){  Pbkdf2 pbkdf2 = Pbkdf2(macAlgorithm: new Hmac(sha1), iterations: 5, bits: 128);  return pbkdf2.deriveBitsSync(passphrase, nonce: Nonce(salt));}

Note that in practice IV and salt must be generated randomly for each encryption (which you already mentioned in your question). Apart from that the iteration count of 5 is generally much too low.