javadartaes-gcm

AES/GCM : Encrypt in java but unable to decrypt string in dart


I have a server code (Java) which encrypts a string using the below method:

public static String encrypt(String plainText, String key) throws Exception {

    byte[] rawKey = key.getBytes(StandardCharsets.UTF_8);
    System.out.println("key size " + rawKey.length + " key: " + key);
    SecretKeySpec secretKey = new SecretKeySpec(rawKey, "AES");

    // Generate a random IV
    byte[] iv = new byte[12];
    new SecureRandom().nextBytes(iv);

    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(128, iv));

    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

    // Combine IV and ciphertext for transmission
    byte[] cipherTextWithIv = new byte[iv.length + encryptedBytes.length];
    System.arraycopy(iv, 0, cipherTextWithIv, 0, iv.length);
    System.arraycopy(encryptedBytes, 0, cipherTextWithIv, iv.length, encryptedBytes.length);

    return Base64.getEncoder().encodeToString(cipherTextWithIv);
}

//Base64 encoded output:

String encrypt = Test.encrypt("I am new to flutter", "mythirtytwolengthlonguniquekey12");

Output: zuaKIqlEBJKVMsqvBb4hfhONkxL9xVyJdezcnS/SSPRswF3P8VfPOJRBKtpvrEs=

Now when I use this output on dart side and try to decrypt it, it prints some gibberish characters.

//dart decrypt logic using 'encrypt: ^5.0.3':

void main() {
final encryptedBase64 = "zuaKIqlEBJKVMsqvBb4hfhONkxL9xVyJdezcnS/SSPRswF3P8VfPOJRBKtpvrEs=";
String uniqueKey = 'mythirtytwolengthlonguniquekey12';

// Extract IV (first 12 bytes)
var ivLength = 12;
final iv = IV.fromBase64(encryptedBase64.substring(0, ivLength));

// Extract ciphertext (remaining bytes)
final cipherText = Encrypted.fromBase64(encryptedBase64.substring(ivLength));

var key = Key.fromUtf8(uniqueKey);
final encrypter = Encrypter(AES(key, mode: AESMode.gcm, padding: null));

final decrypted = encrypter.decrypt(
  cipherText,
  iv: iv,
);
print(decrypted);

}

Output: �qۉ_t� ������'�����Ϧ�<��8}'&�e

The secret key and IV are correct. Padding is set to null. Also I am extracting the IV from the base64 text and decrypting only the cipher text.

What wrong am I doing?


Solution

  • Updated the decryption logic based on the suggestion from goose:

    void main() {
    final encryptedBase64 = "zuaKIqlEBJKVMsqvBb4hfhONkxL9xVyJdezcnS/SSPRswF3P8VfPOJRBKtpvrEs=";
    var decodedString = base64Decode(encryptedBase64);
    String uniqueKey = 'mythirtytwolengthlonguniquekey12';
    
    // Extract IV (first 12 bytes)
    var ivLength = 12;
    final iv = decodedString.sublist(0, ivLength);
    
    // Extract ciphertext (remaining bytes)
    // final cipherText = Encrypted.decodedString.substring(ivLength);
    final cipherText = decodedString.sublist(12);
    
    var key = Key.fromUtf8(uniqueKey);
    final encrypter = Encrypter(AES(key, mode: AESMode.gcm));
    
    final decrypted = encrypter.decrypt(
      Encrypted.fromBase64(base64.encode(cipherText)),
      iv: IV.fromBase64(base64.encode(iv)),
    );
    print(decrypted);
    

    }