目录
一、权限检查与赋予
先检查是否具备DBMS_CRYPTO权限
sql
SELECT * FROM user_tab_privs WHERE table_name = 'DBMS_CRYPTO';
如图所示就是已经具备权限了,否则加密和解密函数无法奏效

如果没有,则执行如下命令
sql
GRANT EXECUTE ON SYS.DBMS_CRYPTO TO 你的用户名;
二、AES加密函数
sql
create or replace function aes_encrypt(p_input VARCHAR2)
RETURN varchar2
IS
p_key VARCHAR2(16) := 'hj7x89H$yuBI0456';
p_iv VARCHAR2(16) := 'NIfb&95GUY86Gfgh';
raw_key RAW(16) := UTL_I18N.STRING_TO_RAW(p_key, 'UTF8');
raw_iv RAW(16) := UTL_I18N.STRING_TO_RAW(p_iv, 'UTF8');
l_src_data RAW(2000);
l_encval RAW(2000);
v_result VARCHAR2(2000);
v_padded_length NUMBER;
v_padding_length NUMBER;
v_padded_raw RAW(2000);
BEGIN
-- 1. 转换为RAW
l_src_data := UTL_I18N.STRING_TO_RAW(p_input, 'UTF8');
-- 2. 手动添加零填充(模拟Java的NoPadding)
-- 计算需要填充到16字节的倍数
v_padded_length := CEIL(UTL_RAW.LENGTH(l_src_data) / 16) * 16;
v_padding_length := v_padded_length - UTL_RAW.LENGTH(l_src_data);
-- 添加0x00填充
v_padded_raw := l_src_data;
FOR i IN 1..v_padding_length LOOP
v_padded_raw := UTL_RAW.CONCAT(v_padded_raw, '00');
END LOOP;
-- 3. AES/CBC加密,使用零填充
l_encval := DBMS_CRYPTO.ENCRYPT(
src => v_padded_raw,
typ => DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_ZERO,
key => raw_key,
iv => raw_iv
);
-- 4. Base64编码
v_result := UTL_I18N.RAW_TO_CHAR(
UTL_ENCODE.BASE64_ENCODE(l_encval),
'UTF8'
);
RETURN v_result;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
三、AES加密函数
sql
create or replace function aes_decrypt(p_input VARCHAR2)
RETURN varchar2
IS
-- 密钥和IV(与Java代码完全一致)
p_key VARCHAR2(16) := 'hj7x89H$yuBI0456';
p_iv VARCHAR2(16) := 'NIfb&95GUY86Gfgh';
raw_key RAW(16) := UTL_I18N.STRING_TO_RAW(p_key, 'UTF8');
raw_iv RAW(16) := UTL_I18N.STRING_TO_RAW(p_iv, 'UTF8');
l_enc_data RAW(2000);
l_decval RAW(2000);
v_raw_result RAW(2000);
v_result VARCHAR2(2000);
v_length NUMBER;
v_byte RAW(1);
BEGIN
-- 1. Base64解码
l_enc_data := UTL_ENCODE.BASE64_DECODE(
UTL_I18N.STRING_TO_RAW(p_input, 'UTF8')
);
-- 2. AES/CBC解密,使用零填充(匹配Java的NoPadding)
l_decval := DBMS_CRYPTO.DECRYPT(
src => l_enc_data,
typ => DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_ZERO,
key => raw_key,
iv => raw_iv
);
-- 3. 移除零填充:找到第一个0x00字节并停止
v_length := UTL_RAW.LENGTH(l_decval);
FOR i IN 1..v_length LOOP
v_byte := UTL_RAW.SUBSTR(l_decval, i, 1);
-- 遇到0x00填充字节时停止
IF v_byte = '00' THEN
EXIT;
END IF;
-- 累积有效字节
v_raw_result := UTL_RAW.CONCAT(v_raw_result, v_byte);
END LOOP;
-- 4. 将RAW数据转换为字符串
IF v_raw_result IS NOT NULL THEN
v_result := UTL_I18N.RAW_TO_CHAR(v_raw_result, 'UTF8');
END IF;
RETURN v_result;
EXCEPTION
WHEN OTHERS THEN
-- 解密失败时返回NULL
RETURN NULL;
END;
四、使用示例
sql
select AES_DECRYPT(ID_CARD) , AES_ENCRYPT(ID_CARD) from AES_SYS_USER
查询结果

数据库示例
