杰瑞科技汇

java delphi aes

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.

java delphi aes-图1
(图片来源网络,侵删)

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:

  1. Algorithm: AES (Advanced Encryption Standard).
  2. Mode of Operation: AES/CBC/PKCS5Padding is 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).
  3. Key: The exact same secret key must be used in both applications.
  4. 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.
  5. Character Encoding: Both languages must use the same character encoding when converting strings to bytes and vice-versa. UTF-8 is the standard and recommended choice.
  6. Output Format: The encrypted data is binary. To transport it or store it as text, it must be encoded. Base64 is 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

java delphi aes-图2
(图片来源网络,侵删)
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:

  1. Save the code as AesEncryptor.java.
  2. Compile and run it: javac AesEncryptor.java && java AesEncryptor
  3. 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)

java delphi aes-图3
(图片来源网络,侵删)
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

  1. Save the code as AesDecryptor.dpr.
  2. Crucially, you must replace the ENCRYPTED_BASE64 constant with the actual Base64 string output by your Java program.
  3. 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.

分享:
扫描分享到社交APP
上一篇
下一篇