Of course. This is a very common and important task: encrypting data in one language (Java) and decrypting it in another (Delphi) using the AES algorithm. The key to success is strictly following the same parameters in both languages.

Here is a complete, step-by-step guide with code for both Java and Delphi, demonstrating how to encrypt a string in Java and decrypt it in Delphi.
The Golden Rules for Cross-Language AES
For the two languages to communicate, they must agree on the following:
- Algorithm:
AES(Advanced Encryption Standard). - Mode of Operation:
AES/CBC/PKCS5Paddingis a very common and robust choice.CBC(Cipher Block Chaining) mode requires an Initialization Vector (IV).PKCS5Padding(or its close relative,PKCS7Padding) pads the final block of data to make it a multiple of the block size (16 bytes for AES).
- Key: The exact same secret key must be used in both applications.
- IV: The exact same Initialization Vector must be used. It does not need to be secret, but it must be identical for encryption and decryption. A common practice is to prepend the IV to the ciphertext and then extract it before decryption.
- Character Encoding: Both languages must use the same character encoding when converting strings to bytes and vice-versa.
UTF-8is the standard and recommended choice. - Output Format: The encrypted data is binary. To transport it or store it as text, it must be encoded.
Base64is the standard for this.
Step 1: The Java Code (Encryption)
This Java code will take a plaintext string, a secret key, and an IV, and produce a Base64-encoded string containing the IV prepended to the ciphertext.
AesEncryptor.java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class AesEncryptor {
// The algorithm/mode/padding we will use
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String plaintext, String secretKey, String ivString) throws Exception {
// 1. Key and IV setup
// The key must be 16, 24, or 32 bytes for AES (128, 192, or 256 bits)
byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
byte[] ivBytes = ivString.getBytes(StandardCharsets.UTF_8);
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
// 2. Create Cipher instance
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
// 3. Encrypt the plaintext
byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// 4. Prepend the IV to the ciphertext for easy extraction later
byte[] combined = new byte[ivBytes.length + encryptedBytes.length];
System.arraycopy(ivBytes, 0, combined, 0, ivBytes.length);
System.arraycopy(encryptedBytes, 0, combined, ivBytes.length, encryptedBytes.length);
// 5. Return Base64 encoded string
return Base64.getEncoder().encodeToString(combined);
}
public static void main(String[] args) {
try {
// --- IMPORTANT: These must be shared with the Delphi side ---
String secretKey = "ThisIsASecretKey"; // 16 bytes for AES-128
String ivString = "RandomInitVector"; // 16 bytes for AES block size
String plaintext = "Hello from Java! This is a secret message.";
System.out.println("Original Plaintext: " + plaintext);
String encryptedString = encrypt(plaintext, secretKey, ivString);
System.out.println("Encrypted (Base64): " + encryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
To Run:
- Save the code as
AesEncryptor.java. - Compile and run it:
javac AesEncryptor.java && java AesEncryptor - Copy the output
Encrypted (Base64)string. This is what you will give to your Delphi application.
Step 2: The Delphi Code (Decryption)
This Delphi code will take the Base64-encoded string from the Java application, extract the IV and the ciphertext, and then decrypt it back to the original plaintext.
You will need to add the System.Hash unit for the THash class, which is available in modern Delphi versions (XE and later).
AesDecryptor.dpr (Main Project File)

program AesDecryptor;
uses
System.SysUtils,
System.Hash, // For THash to create the key
System.Classes; // For TBytesStream
// Helper function to convert a hex string to a TBytes array
function HexToBytes(const Hex: string): TBytes;
var
i: Integer;
begin
SetLength(Result, Length(Half) div 2);
for i := 0 to Length(Result) - 1 do
Result[i] := StrToInt('$' + Copy(Hex, i * 2 + 1, 2));
end;
// Main decryption function
function DecryptAesCbc(const EncryptedBase64, SecretKeyHex, IvHex: string): string;
var
Cipher: TCipher;
KeyBytes, IvBytes, CipherTextBytes, CombinedBytes: TBytes;
Stream: TBytesStream;
begin
// 1. Decode the Base64 string to get the combined IV and ciphertext
CombinedBytes := TNetEncoding.Base64.DecodeStringToBytes(EncryptedBase64);
// 2. Convert hex strings for key and IV to TBytes
KeyBytes := HexToBytes(SecretKeyHex);
IvBytes := HexToBytes(IvHex);
// 3. Extract the IV and ciphertext from the combined bytes
// The IV is always the first 16 bytes
SetLength(CipherTextBytes, Length(CombinedBytes) - Length(IvBytes));
Move(CombinedBytes[0], IvBytes[0], Length(IvBytes)); // Copy IV part
Move(CombinedBytes[Length(IvBytes)], CipherTextBytes[0], Length(CipherTextBytes)); // Copy ciphertext part
// 4. Create the AES cipher
Cipher := TCipher.Create(TAlgorithm.AES, TMode.CBC, TPadding.PKCS7);
try
// 5. Set the key and IV
Cipher.Key := KeyBytes;
Cipher.IV := IvBytes;
// 6. Decrypt the ciphertext
Stream := TBytesStream.Create;
try
Cipher.DecryptStream(CipherTextBytes, Stream);
Result := TEncoding.UTF8.GetString(Stream.Bytes, 0, Stream.Size);
finally
Stream.Free;
end;
finally
Cipher.Free;
end;
end;
begin
try
// --- IMPORTANT: These MUST match the Java values ---
// The key from Java, converted to Hex for easy handling in Delphi
// 'ThisIsASecretKey' in Hex is '546869734973415365637265744B6579'
const SECRET_KEY_HEX = '546869734973415365637265744B6579';
// The IV from Java, converted to Hex
// 'RandomInitVector' in Hex is '52616E646F6D496E6974566563746F72'
const IV_HEX = '52616E646F6D496E6974566563746F72';
// The string we got from the Java application
const ENCRYPTED_BASE64 = 'bXk4TlZ3WVdsekl6Y21GMFpXaz0=';
// IMPORTANT: Replace this with the actual output from your Java program.
// The example above is a placeholder. You must use the real output.
Writeln('Encrypted (Base64): ' + ENCRYPTED_BASE64);
Writeln('Decrypting...');
const decryptedText = DecryptAesCbc(ENCRYPTED_BASE64, SECRET_KEY_HEX, IV_HEX);
Writeln('Decrypted Plaintext: ' + decryptedText);
except
on E: Exception do
Writeln('Error: ' + E.Message);
end;
Readln; // Pause console
end.
How to Run the Delphi Code
- Save the code as
AesDecryptor.dpr. - Crucially, you must replace the
ENCRYPTED_BASE64constant with the actual Base64 string output by your Java program. - Run the project in Delphi. You should see the original plaintext message printed to the console.
Explanation of Key Differences and How We Bridged Them
| Feature | Java | Delphi | How We Made Them Compatible |
|---|---|---|---|
| Key Representation | A String (e.g., "ThisIsASecretKey"). |
A TBytes array. |
Delphi's TCipher expects a TBytes array. We pass the Java string as a Hex string to Delphi and use a helper HexToBytes function to convert it. This is a very robust way to pass binary data as text. |
| IV Handling | A String. |
A TBytes array. |
Same as the key. We pass the IV as a Hex string and convert it in Delphi. |
| Ciphertext Format | Raw binary byte[]. |
Raw TBytes array. |
Java prepends the IV to the ciphertext and then encodes the entire result as Base64. Delphi decodes the Base64 to get the combined bytes, then manually splits it to extract the IV and the ciphertext. |
| Padding | PKCS5Padding |
TPadding.PKCS7 |
These are functionally identical. Delphi's PKCS7 is the correct equivalent for Java's PKCS5Padding. |
| Encoding | StandardCharsets.UTF_8 |
TEncoding.UTF8 |
Both use UTF-8, ensuring that string-to-byte conversion is consistent. |
By meticulously defining and matching these parameters, you can ensure seamless AES encryption and decryption between Java and Delphi.
