I am facing one issue with dart unable to decrypt data for AES-GCM mode with an authentication password. Below is my dart code:
// Cipher Text Generated by Java.
String cipherText = "c6b80cf9e86e2ec219b4fef448aa73e6eed8e6e6e93211832dee5d45bb6043d6e9193ef084686e482700c86673c5616b10d583b39e0450513de415ce9ce7a32b90a9dcaa9e0b382593a5718d330373344a969013865ad690a6fda81ee47d28746f8bfb9acce9fd8f80d1efa0edd5703693571fafdffe466105488be2c8e78c942eeb3a8b0e81612b5575e2cac3aef4ab0435227483f69c505ad90094a9a50b601ef42663bd09900c20e7ebe8d1a98a29291d81f024304a387194979fbaa940d9d85325ee37c8b2fb70d248cdeeceb552aa157201f374527e4fedfc490c055b256b81a83e877abbf5e8f59972007e9bbd64bfec35343635c681d5916dbbf16e34fadaf1fe6690f06a759b31aac7b64505ac34bf19dfe0b9e21398f0bd9d3d47dbd6773520a71389184c10aaec99aa81dc0a8872d525f94d48160dcae7d74a59f7589ce3cc5205529b7000b23af3b1391abca458f49a96f2dae2148de3ed04c01a0af77e5e4f09f76b4e279e51524d94ff132ad5d2e4a87afe301b3899b9fb3540e1c281a724828f6d643cd597ea0f0952c55702d512a93e162045b738fb1916c85b5cfb4a13c4c20426187fb1f34339d1";
// PassPhare or IV pass Generated by Java.
String passPhare = "myLfN7pToARn4t33RyZwAw==";
// Private Key Used by Both Java and dart.
String privateKey = "DGq1tmmtiXXlCtBAFpFuGZbdWolHcna7kbRJTbTIw4Y=";
I dont know how to decrypt the cipherText with above supported keys in the Flutter(dart) language. Since I am a newbie in flutter, Pls could someone help me to guys to decrypt the above data.
Thanks
CodePudding user response:
I post my full java code here.
// secretKey = DGq1tmmtiXXlCtBAFpFuGZbdWolHcna7kbRJTbTIw4Y=
private static final String ALGORITHM = "AES";
private static final String ALGORITHM_MODE = "AES/GCM/NoPadding";
private static final int KEY_SIZE = 256;
private static final int IV_SIZE = 16;
private static final int TAG_LENGTH_BIT = 128;
//To generate random iv
public static IvParameterSpec getIvParameterSpec() {
byte[] iv = new byte[IV_SIZE];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
public static SecretKey getAESKey() {
try {
KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
keyGen.init(KEY_SIZE);
return keyGen.generateKey();
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
throw new UnExpectedException(ErrorCode.ERR_AES_KEY_GEN);
}
}
public static SecretKey generateKeyFromEncodedString(String encodedKeyString) {
var encodedKey = Base64.getDecoder().decode(encodedKeyString);
return new SecretKeySpec(encodedKey, 0, encodedKey.length, ALGORITHM);
}
public static IvParameterSpec generateIvFromEncodedString(String encodedIv) {
return new IvParameterSpec(Base64.getDecoder().decode(encodedIv));
}
// Password derived AES 256 bits secret key
public static SecretKey getAESKeyFromPassword() {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
//generate random salt
var salt = getAESKey().getEncoded();
var password = "hM3gyGpYa2uGFnE4".toCharArray();
KeySpec spec = new PBEKeySpec(password, salt, 65536, KEY_SIZE);
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), ALGORITHM);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new UnExpectedException(ErrorCode.ERR_AES_KEY_GEN);
}
}
private static String bytesToHex(byte[] bytes) {
final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
private static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i = 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
Character.digit(s.charAt(i 1), 16));
}
return data;
}
//returns the encrypted cipherText in base64 format
public static String encrypt(String input, SecretKey secretKey, IvParameterSpec iv) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv.getIV()));
byte[] cipherText = cipher.doFinal(input.getBytes());
return bytesToHex(cipherText);
} catch (InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException | InvalidKeyException e) {
log.error("error encrypting", e);
}
return null;
}
public static String decrypt(String cipherText, SecretKey secretKey, IvParameterSpec iv) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv.getIV()));
byte[] plainText = cipher.doFinal(hexStringToByteArray(cipherText));
return new String(plainText);
} catch (Exception e) {
log.error("decrypt error", e);
throw new UnExpectedException(ErrorCode.ERR_DECRYPT);
}
}
Flutter(Dart): Using the above java code. I need to develop encryption and decryption in flutter(dart). Suggest me a package and implementation please help me to sort out this issue.
CodePudding user response:
This can be done with the pointycastle package (and convert because your ciphertext is hex):
import 'dart:convert';
import 'dart:typed_data';
import 'package:convert/convert.dart';
import 'package:pointycastle/block/aes.dart';
import 'package:pointycastle/block/modes/cbc.dart';
import 'package:pointycastle/pointycastle.dart';
void main() {
String cipherText =
"c6b80cf9e86e2ec219b4fef448aa73e6eed8e6e6e93211832dee5d45bb6043d6e9193ef084686e482700c86673c5616b10d583b39e0450513de415ce9ce7a32b90a9dcaa9e0b382593a5718d330373344a969013865ad690a6fda81ee47d28746f8bfb9acce9fd8f80d1efa0edd5703693571fafdffe466105488be2c8e78c942eeb3a8b0e81612b5575e2cac3aef4ab0435227483f69c505ad90094a9a50b601ef42663bd09900c20e7ebe8d1a98a29291d81f024304a387194979fbaa940d9d85325ee37c8b2fb70d248cdeeceb552aa157201f374527e4fedfc490c055b256b81a83e877abbf5e8f59972007e9bbd64bfec35343635c681d5916dbbf16e34fadaf1fe6690f06a759b31aac7b64505ac34bf19dfe0b9e21398f0bd9d3d47dbd6773520a71389184c10aaec99aa81dc0a8872d525f94d48160dcae7d74a59f7589ce3cc5205529b7000b23af3b1391abca458f49a96f2dae2148de3ed04c01a0af77e5e4f09f76b4e279e51524d94ff132ad5d2e4a87afe301b3899b9fb3540e1c281a724828f6d643cd597ea0f0952c55702d512a93e162045b738fb1916c85b5cfb4a13c4c20426187fb1f34339d1";
String iv = "myLfN7pToARn4t33RyZwAw==";
String secret = "DGq1tmmtiXXlCtBAFpFuGZbdWolHcna7kbRJTbTIw4Y=";
final binaryCipherText = Uint8List.fromList(hex.decode(cipherText));
final binaryIV = base64Decode(iv);
final binarySecret = base64Decode(secret);
final cipher = CBCBlockCipher(AESEngine());
cipher.init(
false,
ParametersWithIV(
KeyParameter(binarySecret),
binaryIV,
),
);
final binaryPlaintext = cipher.process(binaryCipherText);
print('plaintext: ${hex.encode(binaryPlaintext)}');
}