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

使用DBMS_CRYPTO AES算法实现固定长度加密的技术咨询

Fixed-Length AES Encryption/Decryption with Oracle DBMS_CRYPTO

Great question! Let's walk through how to implement fixed-length, reversible encryption for arbitrary input lengths using Oracle's DBMS_CRYPTO and AES—exactly what you're asking for.

Problem Breakdown

First, why can't you just encrypt directly? AES is a block cipher, meaning it processes data in fixed 16-byte chunks. When your input length isn't a multiple of 16 bytes, padding is added. This means different input lengths will produce different-length ciphertexts. To get a fixed output length while keeping decryption possible, we need two key steps:

  1. Convert any input into a fixed-length, reversible byte sequence (no one-way hashing—we need to get the original data back!)
  2. Encrypt that fixed-length sequence with AES, then encode it to a consistent-length string.

Core Approach

We'll use:

  • Lossless compression (Oracle's UTL_COMPRESS) to shrink arbitrary input text into a smaller byte stream, then pad it to a fixed buffer size.
  • AES-256-CBC (secure, widely supported) with a random IV (initialization vector) to encrypt the fixed buffer.
  • Base64 encoding to convert the combined IV + ciphertext into a fixed-length string.

Step-by-Step Implementation

All code uses Oracle's built-in packages—no external dependencies needed.

1. Define Configuration & Helper Functions

First, set constants for your encryption setup, plus helper functions to handle compression/padding:

-- Configuration constants (tweak these for your business needs)
DEFINE AES_KEY_SIZE = 256; -- 256-bit key = 32 bytes
DEFINE FIXED_PLAINTEXT_BUFFER = 128; -- Fixed size for compressed input (bytes)
DEFINE AES_BLOCK_SIZE = 16; -- AES standard block size (never change this)

-- Secure key retrieval (store keys in Oracle Wallet, NOT hardcoded!)
CREATE OR REPLACE FUNCTION get_aes_secret RETURN RAW IS
BEGIN
  -- Replace with logic to fetch from Wallet/encrypted config table
  RETURN UTL_RAW.CAST_TO_RAW('your-32-byte-secret-key-here-12345678');
END;
/

-- Compress input and pad to fixed buffer length (reversible)
CREATE OR REPLACE FUNCTION compress_to_fixed_buffer(p_input IN CLOB) RETURN RAW IS
  l_compressed RAW;
  l_padded_raw RAW;
BEGIN
  -- Compress input text to bytes
  l_compressed := UTL_COMPRESS.lz_compress(UTL_RAW.CAST_TO_RAW(p_input));
  
  -- Validate compressed size fits our fixed buffer
  IF UTL_RAW.LENGTH(l_compressed) > FIXED_PLAINTEXT_BUFFER THEN
    RAISE_APPLICATION_ERROR(-20001, 'Input too large—compressed data exceeds fixed buffer limit');
  END IF;
  
  -- Pad with null bytes to reach fixed length
  l_padded_raw := UTL_RAW.CONCAT(
    l_compressed,
    UTL_RAW.COPIES(UTL_RAW.CAST_TO_RAW(CHR(0)), FIXED_PLAINTEXT_BUFFER - UTL_RAW.LENGTH(l_compressed))
  );
  RETURN l_padded_raw;
END;
/

-- Reverse the padding/compression to get original input
CREATE OR REPLACE FUNCTION decompress_from_fixed_buffer(p_padded_raw IN RAW) RETURN CLOB IS
  l_compressed RAW;
BEGIN
  -- Strip trailing null padding
  l_compressed := RTRIM(p_padded_raw, UTL_RAW.CAST_TO_RAW(CHR(0)));
  
  -- Decompress back to text
  RETURN UTL_RAW.CAST_TO_CLOB(UTL_COMPRESS.lz_uncompress(l_compressed));
END;
/

2. Fixed-Length Encryption Function

This function takes any input, processes it, and returns a fixed-length Base64 string:

CREATE OR REPLACE FUNCTION fixed_len_aes_encrypt(p_input IN CLOB) RETURN VARCHAR2 IS
  l_key RAW(32) := get_aes_secret();
  l_iv RAW(16) := DBMS_CRYPTO.RANDOMBYTES(AES_BLOCK_SIZE); -- Random IV for security
  l_fixed_plaintext RAW(128) := compress_to_fixed_buffer(p_input);
  l_ciphertext RAW;
  l_full_payload RAW;
BEGIN
  -- AES-256-CBC encryption with PKCS5 padding (Oracle's default)
  l_ciphertext := DBMS_CRYPTO.ENCRYPT(
    src => l_fixed_plaintext,
    typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5,
    key => l_key,
    iv => l_iv
  );
  
  -- Combine IV + ciphertext (fixed total bytes: 16 + 128 = 144)
  l_full_payload := UTL_RAW.CONCAT(l_iv, l_ciphertext);
  
  -- Convert to Base64 (144 bytes = 192 characters, fixed length!)
  RETURN UTL_ENCODE.base64_encode(l_full_payload);
END;
/

3. Decryption Function

Reverse the process to get back the original input:

CREATE OR REPLACE FUNCTION fixed_len_aes_decrypt(p_input IN VARCHAR2) RETURN CLOB IS
  l_key RAW(32) := get_aes_secret();
  l_full_payload RAW;
  l_iv RAW(16);
  l_ciphertext RAW(128);
  l_fixed_plaintext RAW(128);
BEGIN
  -- Decode Base64 back to raw bytes
  l_full_payload := UTL_ENCODE.base64_decode(p_input);
  
  -- Split IV and ciphertext from the payload
  l_iv := UTL_RAW.SUBSTR(l_full_payload, 1, AES_BLOCK_SIZE);
  l_ciphertext := UTL_RAW.SUBSTR(l_full_payload, AES_BLOCK_SIZE + 1, FIXED_PLAINTEXT_BUFFER);
  
  -- AES decryption
  l_fixed_plaintext := DBMS_CRYPTO.DECRYPT(
    src => l_ciphertext,
    typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5,
    key => l_key,
    iv => l_iv
  );
  
  -- Decompress and return original text
  RETURN decompress_from_fixed_buffer(l_fixed_plaintext);
END;
/

Critical Notes

  • Key Security: Never hardcode your AES key. Use Oracle Wallet or an encrypted configuration table to store and retrieve keys securely.
  • Input Limits: Adjust FIXED_PLAINTEXT_BUFFER based on your maximum expected input size (after compression). If inputs are too large, the function will throw an error—this is intentional to prevent buffer overflow.
  • Security Upgrade: For better tamper protection, switch to AES-GCM mode (authenticated encryption). Just replace the typ parameter in DBMS_CRYPTO.ENCRYPT/DECRYPT with DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_GCM (no padding needed for GCM).
  • Encoding Choice: If you prefer hexadecimal over Base64, replace UTL_ENCODE.base64_encode/decode with RAWTOHEX/HEXTORAW—this will give a fixed 288-character string instead of 192.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:52:16