Home > Mobile >  AES-GSM mode Decryption issue in flutter(dart)
AES-GSM mode Decryption issue in flutter(dart)

Time:09-19

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)}');
}
  • Related