You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lockbox3 AES128加密与Oracle PLSQL解密结果不一致问题求助

Hey there, let's work through this AES 128 encryption mismatch between Delphi (RAD Studio Tokyo 10.2 with Lockbox3) and Oracle. This is a super common issue with cross-library encryption, and 9 times out of 10 it boils down to mismatched settings rather than a bug in either tool. Let's break down the most likely culprits and how to test them.

Top Causes to Check First

1. Padding Mode Inconsistencies

This is the #1 suspect for your issue. Even small differences in padding will completely break encryption consistency.

  • Lockbox3 Default: Lockbox3 uses pmPKCS7 as its default padding mode. You can explicitly set it in code to avoid surprises:
    FCodec.PaddingMode := pmPKCS7;
    
  • Oracle Default: If you're using DBMS_CRYPTO, Oracle defaults to PKCS5_PADDING for AES. While PKCS5 is technically a subset of PKCS7 (and identical for 128-bit blocks), it's safer to explicitly specify the padding mode in your Oracle call to match Lockbox3:
    DBMS_CRYPTO.AES_CBC_PKCS7_PADDING -- Use this if your Oracle version supports it
    -- Or PKCS5 if PKCS7 isn't available (they work the same for AES128)
    DBMS_CRYPTO.AES_CBC_PKCS5_PADDING
    
  • If either side uses zero-padding or no padding, your results will never match—double-check this first.

2. Mismatched Initialization Vector (IV)

AES in CBC mode (the default for both Lockbox3 and Oracle) requires an identical IV on both encryption and decryption sides.

  • Lockbox3 Gotcha: If you don't explicitly set the IV, Lockbox3 generates a random one each time you encrypt. This means every encryption of the same plaintext will produce a different result. For testing, set a fixed IV:
    // 16-byte IV (matches AES128 block size)
    FCodec.IV := TBytes.Create($00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F);
    
  • Oracle Side: Use the exact same IV value in your encryption call. Convert it to a RAW type like this:
    v_iv RAW(16) := UTL_RAW.CAST_FROM_HEX('000102030405060708090A0B0C0D0E0F');
    

3. Key Handling Differences

How you convert your keyText string into a 16-byte AES128 key must be identical on both sides.

  • Delphi Check: Are you using the raw UTF-8 bytes of keyText directly as the key, or hashing it first? For example, if you're using SHA256 to hash the key string then taking the first 16 bytes, your code might look like this:
    var
      KeyHash: TIdHashSHA256;
      KeyBytes: TBytes;
    begin
      KeyHash := TIdHashSHA256.Create;
      try
        KeyBytes := KeyHash.HashStringAsBytes(KeyText, IndyTextEncoding_UTF8);
        // Take first 16 bytes for AES128
        SetLength(KeyBytes, 16);
        FCodec.SetKey(KeyBytes, Length(KeyBytes)*8);
      finally
        KeyHash.Free;
      end;
    end;
    
  • Oracle Match: You need to replicate this exact logic in Oracle. For the SHA256 example:
    v_key_raw RAW(32) := DBMS_CRYPTO.HASH(UTL_I18N.STRING_TO_RAW(v_key, 'AL32UTF8'), DBMS_CRYPTO.SHA256);
    v_aes_key RAW(16) := SUBSTR(v_key_raw, 1, 16); -- Take first 16 bytes
    
  • Never assume "the key is the same string"—always verify the raw byte values match between Delphi and Oracle.

4. Encoding & Block/Key Size

  • Plaintext Encoding: You're using utf8string in Delphi, so make sure Oracle is also converting the plaintext to UTF-8 bytes before encryption:
    UTL_I18N.STRING_TO_RAW(v_plaintext, 'AL32UTF8')
    
  • AES128 Confirmation: Double-check both sides are using AES128 specifically (16-byte key, 16-byte block size). In Lockbox3:
    FCodec.AlgorithmID := ALG_RIJNDAEL; -- AES is a subset of Rijndael
    FCodec.KeySize := ks128;
    FCodec.ChainMode := cmCBC; -- Match Oracle's mode
    

Test with Minimal, Reproducible Code

To eliminate variables, use these simplified snippets to test encryption on both sides and compare the base64-encoded results.

Delphi Test Code

uses
  uTPLb_Constants, uTPLb_BaseNonVisualComponent, uTPLb_Codec, uTPLb_CryptographicLibrary;

procedure TestAESConsistency;
var
  FCryptoLib: TCryptographicLibrary;
  FCodec: TCodec;
  PlainText: UTF8String;
  KeyText: UTF8String;
  CipherBase64: string;
  FixedIV: TBytes;
begin
  FCryptoLib := TCryptographicLibrary.Create(nil);
  FCodec := TCodec.Create(nil);
  try
    FCodec.CryptoLibrary := FCryptoLib;
    // Configure AES128 CBC with PKCS7 padding
    FCodec.AlgorithmID := ALG_RIJNDAEL;
    FCodec.KeySize := ks128;
    FCodec.ChainMode := cmCBC;
    FCodec.PaddingMode := pmPKCS7;

    // Fixed test key (16-byte UTF8 string)
    KeyText := 'MyTestKey12345678';
    FCodec.Password := KeyText;

    // Fixed IV
    FixedIV := TBytes.Create($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F);
    FCodec.IV := FixedIV;

    // Test plaintext
    PlainText := 'Hello AES Test!';

    // Encrypt to Base64
    FCodec.EncryptString(PlainText, CipherBase64);
    ShowMessage('Delphi Cipher (Base64): ' + CipherBase64);
  finally
    FCodec.Free;
    FCryptoLib.Free;
  end;
end;

Oracle Test Code

DECLARE
  v_plaintext VARCHAR2(100) := 'Hello AES Test!';
  v_key VARCHAR2(100) := 'MyTestKey12345678'; -- Match Delphi's KeyText
  v_iv RAW(16) := UTL_RAW.CAST_FROM_HEX('000102030405060708090A0B0C0D0E0F'); -- Match Delphi's IV
  v_cipher_raw RAW(2000);
  v_cipher_base64 VARCHAR2(2000);
BEGIN
  v_cipher_raw := DBMS_CRYPTO.ENCRYPT(
    src => UTL_I18N.STRING_TO_RAW(v_plaintext, 'AL32UTF8'),
    typ => DBMS_CRYPTO.AES_CBC_PKCS5_PADDING, -- Equivalent to PKCS7 for AES128
    key => UTL_I18N.STRING_TO_RAW(v_key, 'AL32UTF8'),
    iv => v_iv
  );
  
  v_cipher_base64 := UTL_ENCODE.BASE64_ENCODE(v_cipher_raw);
  DBMS_OUTPUT.PUT_LINE('Oracle Cipher (Base64): ' || v_cipher_base64);
END;
/

Final Troubleshooting Step

If the test code still doesn't produce matching results, print out the raw byte values of the plaintext, key, and IV from both sides. A single mismatched byte anywhere in these will cause the encryption results to differ entirely.

内容的提问来源于stack exchange,提问作者Faadiel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:28:20