我们的文章会在微信公众号IT民工的龙马人生和博客网站 ( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。
1.1 前言
在数据库国产化迁移的过程中,安全能力的对标成熟商业数据库与核心逻辑的平滑过渡到YashanDB是关键环节。Oracle 早期版本常使用 dbms_obfuscation_toolkit 进行基础加密,但是在后期Oracle dbms_obfuscation_toolkit列为过期组件。但在现代国产数据库研发(如 YashanDB)中,为了获得更强的算法支持和更标准化的接口,通常只适配了 DBMS_CRYPTO ,这就涉及到需要将 dbms_obfuscation_toolkit改写为DBMS_CRYPTO。
本文将详细展示如何将一个基于 DES 算法的解密函数从旧有的 Oracle Toolkit 模式迁移至 Oracle的DBMS_CRYPTO 模式,在平滑的迁移到YashanDB 兼容的 DBMS_CRYPTO 模式,并分享验证一致性的最佳实践。
1.2 现状分析:Oracle 原始逻辑
在 Oracle 早期遗留系统中,解密逻辑通常如下所示。该方法直接处理 VARCHAR2 类型,且对 DES 块对齐的要求较为隐蔽。
原始代码如下:
-- 原始基于 dbms_obfuscation_toolkit 的代码
CREATE OR REPLACE FUNCTION "HTZ"."DECRYPT_DES" (p_text VARCHAR
)
RETURN VARCHAR
IS
v_text VARCHAR(2000);
BEGINIF p_text IS NULL OR p_text = '' THEN RETURN p_text;END IF ;dbms_obfuscation_toolkit.DESDECRYPT(input_string => UTL_RAW.CAST_TO_varchar2(p_text), key_string => 'huangtin', decrypted_string => v_text);v_text := rtrim(v_text, chr(0));RETURN v_text;
EXCEPTIONWHEN others THEN RETURN p_text;
END;
/
1.3 演进与适配:改写为 DBMS_CRYPTO 模式
YashanDB 高度兼容 Oracle 的系统包,所以我们现在Oracle数据库中将代码修改为DBMS_CRYPTO。改写为 DBMS_CRYPTO 能够提供更明确的填充模式控制。以下代码展示了如何通过定义 v_typ(DES + CBC模式 + 无填充)来精准模拟原始逻辑。
CREATE OR REPLACE FUNCTION "HTZ"."DECRYPT_DES" (p_text IN VARCHAR2
)
RETURN VARCHAR2
ISv_ret RAW(2000);v_key RAW(8);v_input RAW(2000);v_decrypted VARCHAR2(2000);-- DES + CBC + No Padding (精确匹配原始逻辑,手动处理补齐)v_typ PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_DES + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_NONE;
BEGIN-- 1. 处理空值输入IF p_text IS NULL THEN RETURN p_text;END IF;-- 2. 准备密钥与输入 (强制使用 RAW 类型确保字节级安全)v_key := UTL_RAW.CAST_TO_RAW('huangtin');v_input := UTL_RAW.CAST_TO_RAW(p_text);-- 3. 调用 DBMS_CRYPTO 进行解密v_ret := DBMS_CRYPTO.DECRYPT(src => v_input,typ => v_typ,key => v_key);-- 4. 转换回字符串并去除末尾的 CHR(0) 填充v_decrypted := UTL_RAW.CAST_TO_VARCHAR2(v_ret);v_decrypted := RTRIM(v_decrypted, CHR(0));RETURN v_decrypted;EXCEPTIONWHEN OTHERS THEN-- 遵循原始需求,报错时返回原文本RETURN p_text;
END;
/
1.4 兼容性验证:确保逻辑闭环
在正式迁移到 YashanDB 之前,我们需要在 Oracle 环境中通过“新旧对比测试”验证改写后的函数是否能正确解密由旧包产生的数据。
1.4.1 场景一:模拟旧数据解密验证
由于 DES 要求输入必须是 8 的倍数,我们在测试中对不足 8 位的 huanghtz 进行了补齐处理。
SET SERVEROUTPUT ON;DECLAREv_raw_text VARCHAR2(100) := 'huanghtz'; v_key VARCHAR2(20) := 'huangtin';v_padded_text VARCHAR2(100);v_encrypted_str VARCHAR2(2000);v_decrypted_new VARCHAR2(2000);-- 模拟老方法加密逻辑PROCEDURE mock_old_encrypt(p_in IN VARCHAR2, p_out OUT VARCHAR2) ISBEGINv_padded_text := RPAD(p_in, 8, CHR(0));DBMS_OBFUSCATION_TOOLKIT.DESENCRYPT(input_string => v_padded_text,key_string => v_key,encrypted_string => p_out);END;BEGINDBMS_OUTPUT.PUT_LINE('--- Testing String: ' || v_raw_text || ' ---');-- Step A: 旧包加密mock_old_encrypt(v_raw_text, v_encrypted_str);DBMS_OUTPUT.PUT_LINE('Step 1: Encrypted String (Hex): ' || UTL_RAW.CAST_TO_RAW(v_encrypted_str));-- Step B: 新函数解密v_decrypted_new := "HTZ"."DECRYPT_DES"(v_encrypted_str);-- Step C: 结果比对DBMS_OUTPUT.PUT_LINE('Step 2: Decrypted Result: ' || v_decrypted_new);IF v_decrypted_new = v_raw_text THENDBMS_OUTPUT.PUT_LINE('SUCCESS: The new method matches the old logic.');ELSEDBMS_OUTPUT.PUT_LINE('FAILURE: Results do not match.');END IF;
END;
/
1.5 迁移 YashanDB 后的生产验证
将上述 DECRYPT_DES 函数迁移至 YashanDB 后,我们使用 YashanDB 原生的 DBMS_CRYPTO 能力进行最终验证。
1.5.1 场景二:YashanDB 环境内独立验证
SET SERVEROUTPUT ON;DECLAREv_original_plain VARCHAR2(100) := 'huanghtz'; v_encryption_key VARCHAR2(20) := 'huangtin';v_encrypted_raw RAW(2000);v_encrypted_char VARCHAR2(2000);v_decrypted_final VARCHAR2(2000);
BEGIN-- 1. 在 YashanDB 中模拟生成标准 DES 加密数据v_encrypted_raw := DBMS_CRYPTO.ENCRYPT(src => UTL_RAW.CAST_TO_RAW(v_original_plain),typ => DBMS_CRYPTO.ENCRYPT_DES + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_NONE,key => UTL_RAW.CAST_TO_RAW(v_encryption_key));v_encrypted_char := UTL_RAW.CAST_TO_VARCHAR2(v_encrypted_raw);-- 2. 调用迁移后的解密函数v_decrypted_final := "HTZ"."DECRYPT_DES"(v_encrypted_char);-- 3. 验证输出DBMS_OUTPUT.PUT_LINE('--- Function Verification in YashanDB ---');DBMS_OUTPUT.PUT_LINE('Original Text: ' || v_original_plain);DBMS_OUTPUT.PUT_LINE('Function Output: ' || v_decrypted_final);IF v_decrypted_final = v_original_plain THENDBMS_OUTPUT.PUT_LINE('RESULT: SUCCESS');ELSEDBMS_OUTPUT.PUT_LINE('RESULT: FAILED');END IF;
END;
/
1.6 总结与建议
- 权限控制:在 YashanDB 中编译该函数前,务必确保
HTZ用户已被显式授予权限:GRANT EXECUTE ON DBMS_CRYPTO TO HTZ;。 - RAW 类型的重要性:从 Oracle 迁移到 YashanDB 时,应尽量将加密数据存储为
RAW。如果必须以VARCHAR2存储,需格外注意字符集对不可见字符的影响。 - 算法演进:DES 算法在安全性上已逐渐被 AES 取代。在完成平滑迁移后,建议后续考虑将业务中的解密算法升级为
AES-256。
通过上述改写流程,我们不仅成功实现了 Oracle 到 YashanDB 的逻辑迁移,更将底层的安全组件升级到了更可靠的 DBMS_CRYPTO 架构。