必须使用dbms_crypto而非已弃用的dbms_obfuscation_toolkit,因其支持aes、可控iv、灵活填充;加密解密前需用utl_i18n.string_to_raw转raw并指定al32utf8字符集,密钥长度须匹配算法要求,base64数据须先解码再处理,iv必须随机生成且与密文一同管理。

直接用 DBMS_CRYPTO,别碰过时的 DBMS_OBFUSCATION_TOOLKIT —— 它在 12c 后已弃用,且不支持 AES、无 IV 控制、填充方式死板。
加密前必须转 RAW,不能直接传 VARCHAR2
Oracle 的 DBMS_CRYPTO.ENCRYPT 所有输入参数都要求是 RAW 类型。常见错误是把明文字符串直接塞进去,结果报 ORA-06502: PL/SQL: numeric or value error。
-
UTL_I18N.STRING_TO_RAW('hello', 'AL32UTF8')是安全选择;UTL_RAW.CAST_TO_RAW仅适用于 ASCII 字符,含中文会截断或乱码 - 密钥也必须是
RAW,比如UTL_I18N.STRING_TO_RAW('mykey123', 'AL32UTF8'),长度要严格匹配算法要求(AES-128 要 16 字节,AES-256 要 32 字节) - 若密钥来自参数绑定(如 C# 的
OracleParameter),类型必须设为OracleDbType.Raw,不是Varchar2
解密失败报 ORA-29275?大概率是 BASE64 链断了
这是生产环境最高频的坑:前端或应用层传入的是 BASE64 编码后的字符串(比如 "aGVsbG8="),但解密函数直接拿它去调 DBMS_CRYPTO.DECRYPT,而该函数只认 RAW。
- 必须先用
UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(:p_base64_str))还原成原始加密RAW - 还原后才能进
DECRYPT;解密出来仍是RAW,再用UTL_I18N.RAW_TO_CHAR(..., 'AL32UTF8')转回字符串 - 字符集不一致也会触发
ORA-29275:加密用AL32UTF8,解密却用US7ASCII,中间一截字节就识别不了
AES-CBC 必须配 IV,否则加解密不一致
用 DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC 时,IV(初始向量)不是可选项 —— 它决定相同明文每次加密结果不同。漏传或复用 IV,会导致解密出乱码或 ORA-28233。
- 生成 IV 推荐用
DBMS_CRYPTO.RANDOMBYTES(16)(AES-128 对应 16 字节) - IV 需和密文一起存储或传输,但无需保密;常见做法是拼在密文前(如
IV || CIPHERTEXT),解密时切分 - 如果硬编码 IV(比如全零),那等于放弃 CBC 的语义安全性,等同于 ECB 模式,敏感数据千万别这么干
真正难的不是写对一行 ENCRYPT 调用,而是整条编解码链的字符集、类型、长度、IV 管理全部对齐。哪怕只有一环用错 CAST_TO_RAW 代替 STRING_TO_RAW,或者 BASE64 解码后忘了 UTL_RAW.CAST_TO_RAW 套一层,就会在解密时静默失败。











