WITH ENCRYPTION 仅提供弱混淆而非真正加密,密钥硬编码于SQL Server可执行文件中,有VIEW DEFINITION权限者可用第三方工具秒级还原明文,仅能防随手查看,不防泄密。

SQL Server 的 WITH ENCRYPTION 不能真正保护源码,它只是简单 obfuscation,反编译工具几秒就能还原——别拿它当版权盾牌用。
为什么 WITH ENCRYPTION 没法防泄密
这个选项本质是把存储过程文本转成加密 blob 存进系统表 sys.sysobjvalues(旧版本)或 sys.sql_modules(2005+),但密钥硬编码在 SQL Server 可执行文件里。只要能连上实例、有 VIEW DEFINITION 权限,用 sp_helptext 看不到内容,但用第三方工具(比如 sqldecryptor 或 PowerShell 脚本调用 DBCC PAGE + 解密逻辑)就能直接 dump 出明文。
常见错误现象:sp_helptext my_proc 返回 “The text for object 'my_proc' is encrypted”,就以为安全了——其实只是系统内置函数不支持解密,不是数据真加密。
- SQL Server 2000–2019 全系列都存在该问题,无版本差异
- 即使禁用
VIEW DEFINITION,sa 或 db_owner 仍可绕过 - 启用 TDE(透明数据加密)或列级加密,对存储过程体本身完全无效
哪些场景下还能用 WITH ENCRYPTION
它唯一靠谱的用途,是防止同事或外包人员随手 sp_helptext 查看逻辑,属于“防君子不防小人”的轻量级遮蔽。适合内部协作中隐藏简单计算规则、避免被误改,但绝不适用于交付给客户或部署在不可信环境。
实操建议:
- 只对非核心逻辑、无敏感算法的存储过程加
WITH ENCRYPTION - 必须配合权限控制:收回普通用户对
sys.sql_modules的 SELECT 权限 - 创建时写法要完整,
CREATE OR ALTER PROC ... WITH ENCRYPTION AS ...,漏掉ENCRYPTION关键字会导致已加密过程被覆盖为明文 - 注意:加密后无法做 diff 对比,源码管理必须依赖外部脚本文件,不能靠
sp_helptext导出存档
想真保护逻辑?得换思路
SQL Server 本身不提供代码级 DRM。可行路径只有三条,且各有硬伤:
- 把核心算法抽到外部服务:用 .NET CLR 集成(需启用
TRUSTWORTHY或签名,维护成本高) - 用 C# / Java 写独立 API,SQL 只做数据搬运,但增加网络调用和部署复杂度
- 客户现场部署时,由你方 DBA 手动部署加密后的脚本,并删除所有源码副本——依赖流程管控,不是技术方案
没有银弹。哪怕上了 CLR,只要有服务器管理员权限,照样能从内存 dump 出 IL 或反编译 DLL。
加密后查不到源码,怎么调试和运维?
这是最常被忽略的实际痛点:加密后 sys.dm_exec_describe_first_result_set 仍能获取结果集元数据,但 sys.dm_exec_query_plan 查执行计划时,query_plan XML 里的 StmtSimple 节点会显示 Encrypted="1",导致部分监控工具无法解析语句。
运维建议:
- 开发环境永远保留未加密版本,仅生产发布脚本加
WITH ENCRYPTION - 用扩展事件(
query_post_compilation_showplan)捕获计划时,记得过滤掉加密对象,否则日志体积暴增 - 备份前确认
sys.sql_modules中definition字段为 NULL —— 这是验证是否加密成功的唯一可靠方式,别信界面提示
真正难的从来不是加个关键字,而是厘清“谁需要看、谁不该看、出了问题谁来救火”。WITH ENCRYPTION 一按就生效,但权限边界、发布流程、应急回滚,这些才决定它到底有没有用。

















