DBMS_CRYPTO执行权限必须显式授予指定用户,不能通过PUBLIC、角色或同义词间接获取;授予权限后需手动重新编译依赖的存储过程。
DBMS_CRYPTO 执行权限必须显式授予,PUBLIC 不能自动获得
oracle 默认不给任何用户 dbms_crypto 的执行权限,哪怕你是 dba 角色也不行。这个包不属于系统预授权对象,必须手动 grant execute on dbms_crypto to user_name。常见错误是以为用 create procedure 包含加密逻辑后,调用者就能执行——实际运行时会报 ora-00904: "dbms_crypto"."encrypt": invalid identifier 或更隐蔽的 pls-00201: identifier 'dbms_crypto.encrypt' must be declared,本质都是权限缺失。
注意:DBMS_CRYPTO 是 SYS 拥有的包,不能被同义词或角色间接代理;EXECUTE_CATALOG_ROLE 或 DBA 角色都不包含它的权限。
只授最小必要权限,避免跨 schema 泄密风险
别图省事一次性 GRANT EXECUTE ON DBMS_CRYPTO TO PUBLIC。一旦放开,任意用户都能调用 DBMS_CRYPTO.ENCRYPT、DBMS_CRYPTO.DECRYPT,甚至用相同密钥解密其他用户的加密数据——只要他能拿到密文和密钥(比如从日志、临时表、应用层硬编码里捞到)。真实场景中,经常有开发在测试环境这么干,上线后被审计卡住。
- 按业务模块拆分:比如只给
app_user授予ENCRYPT权限,给report_user只授DECRYPT(如果真需要) - 密钥管理必须独立:禁止把密钥写死在 PL/SQL 包里,优先用 Oracle Wallet 或外部 KMS
- 若用
DBMS_CRYPTO.RANDOMBYTES生成密钥,确保调用者无权读取V$ENCRYPTION_WALLET或GV$WALLET
加密函数调用失败常因权限 + 参数组合出错
即使有了 EXECUTE 权限,DBMS_CRYPTO.ENCRYPT 还可能报 ORA-28234: key length too short 或 ORA-28232: invalid input length。这不是权限问题,但新手容易误判。根本原因是:Oracle 对不同算法强制要求密钥长度和输入块大小对齐(比如 DBMS_CRYPTO.DES_CBC_PKCS5 要求密钥正好 8 字节,明文长度必须是 8 的倍数)。
实操建议:
- 优先用 AES:如
DBMS_CRYPTO.AES_CBC_PKCS5,密钥支持 16/24/32 字节,兼容性好 - 别依赖默认填充:显式指定
pad_type => DBMS_CRYPTO.PAD_PKCS5,避免不同 Oracle 版本行为差异 - 输入
RAW类型前务必用UTL_I18N.STRING_TO_RAW转码,否则中文会乱码或截断
权限变更后需重新编译依赖的存储过程
给用户授完 DBMS_CRYPTO 权限,如果之前已创建过调用它的存储过程,该过程仍处于 INVALID 状态,执行时报 PLS-00201。Oracle 不会自动重编译,必须手动 ALTER PROCEDURE your_proc COMPILE。
容易被忽略的点:
- 权限授予对象是包本身(
SYS.DBMS_CRYPTO),不是某个具体函数名 - 如果过程定义在另一个 schema 下(比如
pkg_owner.my_encrypt_proc),要确保pkg_owner有权限,而不是调用者 - 使用
AUTHID DEFINER的过程,权限检查发生在定义者侧;用AUTHID CURRENT_USER才检查调用者权限
密钥生命周期和权限粒度必须同步设计,光解决“能不能跑”只是第一步。










