是否可以在 SQL Server 2014 中为 .NET 框架程序集创建非对称密钥?

Posted

技术标签:

【中文标题】是否可以在 SQL Server 2014 中为 .NET 框架程序集创建非对称密钥?【英文标题】:Is it possible to create an asymmetric key for a .NET framework assembly in SQL Server 2014? 【发布时间】:2016-03-15 17:40:08 【问题描述】:

我正在 Visual Studio 中开发一个 SQL Server 数据库项目,它实际上是一个用户定义的函数。在这个项目中,我包含了 Json.NET 作为参考(使用 NuGet)。

我通过首先打开数据库TRUSTWORTHY ON(因为我的项目是不安全的)然后运行以下命令,成功地将我的程序集和 UDF 发布(并使工作)到我的 SQL Server 实例:

CREATE ASSEMBLY [System.Runtime.Serialization] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE;

原来是 Json.NET 依赖的一个程序集(如果我不这样做,就会出错)

同时I read about how bad turning TRUSTWORTHY ON can be 和我尝试以go the asymmetric key 的方式避免开启它。

在签署我自己的程序集之前,我知道我必须为 System.Runtime.Serialization 创建一个密钥,因为我的项目依赖于 Json.Net,而 Json.Net 又依赖于它,但是当我运行它时,我得到了这个:

USE [master];
GO
  CREATE ASYMMETRIC KEY [SystemRuntimeSerializationKey]
    AUTHORIZATION [dbo]
    FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll';
GO

Msg 15468, Level 16, State 5, Line 3
An error occurred during the generation of the asymmetric key.

这对我没有多大帮助。

那么是否可以为 .NET 框架程序集生成这样的密钥,或者它是否存在打开 TRUSTWORTHY ON 以外的解决方法?

【问题讨论】:

顺便说一句——SQL Server 2016 还没有完全推出,但它会支持原生 JSON,这可能意味着整个问题都会为你解决——取决于你在做什么当然是 JSON。 【参考方案1】:

不,我从未找到实现此目的的方法。用于签署 .NET Framework 程序集的密钥是 Microsoft 内部/私有的。尝试的选项:

提取私钥/加载到 SQL Server:不可能,否则密钥不会是“私有的”。签名/强命名系统是有效的,因为外人不能声称他们签署了代码。

添加签名:我尝试使用sn 实用程序添加新签名。由于以下原因无法正常工作:

无法重新签署程序集 -- 程序集的公钥与签名公钥不匹配。

但是,即使这确实有效,这可能并不意味着将其加载到 SQL Server 中会有效,因为它与您作为资源添加到项目中的程序集不同。其他 .NET Framework DLL,如果有任何其他依赖项,只会知道原始签名。

删除当前签名并添加一个新签名:我尝试使用ILDASM 反汇编System.Runtime.Serialization.dll,然后添加从sn -k 创建的新私钥,然后使用ILASM 重新链接,但在@ 上失败了987654326@ step(我没有时间进一步调查)。

但是就像上面的选项一样,即使这确实有效,您也必须将 System.Runtime.Serialization 的 Json.NET 项目引用更改为这个新的 DLL,重新编译它,然后将您的项目引用更改为新的 DLL ,然后重新编译。但这只会让您能够干净地加载 DLL,如果它们具有期望原始 Microsoft 签名的外部依赖项,则不能保证它们能够工作。

本质上,如果您正在加载您无法控制签名的 DLL,那么唯一的希望是使用 ILDASM 反编译并使用 ILASM 重新编译,指定一个新的 snk 文件,但如果其他程序集链接到正在重新编译的内容,那将不起作用。当然 .NET Framework DLL 属于这一类。

简单地说:如果您正在加载不受支持的 .NET Framework DLL,那么您几乎需要设置 TRUSTWORTHY ON

但是:请记住,即使这确实可以通过非对称密钥或证书加载所有内容,但这并不意味着您不会遇到功能问题。这些库没有被批准/验证是有原因的。它们中的代码可以以您意想不到的方式工作,例如将数据存储到静态字段。在 Windows 和控制台应用程序中,这不是问题,因为它是每个应用程序域一次使用。但是 SQLCLR 使用共享的应用程序域,因此多个 SQL Server 会话将共享这些静态变量。可能是 Json.NET 库调用的方法没有使用那些不安全的东西,但没有办法知道,即使我们知道,现在我们也无能为力:-(.


我一直在考虑的一件事是跟踪不受支持的 .NET Framework DLL 中调用的方法,并假设它没有做任何不安全的事情,将代码直接复制到项目中。理论上应该可以,只要对 System.Runtime.Serialization 的调用不调用其他不受支持的 DLL 或做“不安全”的事情等。但是,我没有时间对此进行测试。

【讨论】:

太糟糕了,没有一种机制能够告诉类似“好吧,我知道这个程序集没有得到官方支持(安全),我没有它的密钥(签名) ,但我仍然希望我的用户使用它”,而不必在数据库上打开 TRUSTWHORTHY 并且顺便降低了我整个服务器的安全性。【参考方案2】:

我设法使用以下脚本在 .Net Framework 4 Systen.Drawing.dll 的 SQL Server 2014(版本 11.0.6248.0)上执行此操作

USE MASTER
GO

CREATE 
    ASYMMETRIC KEY SystemDrawingKey 
    FROM EXECUTABLE FILE = N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll'   

CREATE 
    LOGIN SystemDrawingKeyLogin 
    FROM ASYMMETRIC KEY SystemDrawingKey   

GRANT UNSAFE ASSEMBLY TO SystemDrawingKeyLogin

USE MY_DATABASE
GO 

CREATE ASSEMBLY [SystemDrawing]
FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll' WITH PERMISSION_SET = UNSAFE
GO 

SQL Server 接受此程序集,但给出警告:

警告:Microsoft .NET Framework 程序集 'system.drawing, 版本=4.0.0.0,文化=中性,publickeytoken=b03f5f7f11d50a3a, 处理器架构=msil。'您正在注册未经过全面测试 在 SQL Server 托管环境中,不受支持。在里面 将来,如果您升级或维修此程序集或 .NET Framework, 您的 CLR 集成例程可能会停止工作。请参考 SQL Server 更多详情请在线预订。

为了验证该设置是否关闭,我从 A warning about the TRUSTWORTHY database option 运行了以下查询:

SELECT name, is_trustworthy_on
FROM sys.databases
WHERE name <> 'msdb'
AND is_trustworthy_on = 1

没有结果。当然,现在我有WITH PERMISSION_SET = UNSAFE,但这似乎问题不大。

System.Drawning.dll 是我需要第三方程序集的依赖项。我很确定我调用的方法不会调用 System.Drawing 中的任何内容,所以现在我保持这种方式。

另外,我在创建自己的自定义程序集时遇到了错误。我丢失了确切的错误,但提到了 Synchonization,它引用了 System.Diagnostics,它帮助我找到了对 Debug.WriteLine 的调用。删除之后,可以创建程序集并且一切正常。

【讨论】:

以上是关于是否可以在 SQL Server 2014 中为 .NET 框架程序集创建非对称密钥?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 sql server 2008 中为现有项目执行数据库附件

在 SQL Server 中为关键数据库还原数据库的最佳方法

SQL Server 2014 在 JBOSS EAP 6.4 数据源配置中连接失败

一链接Sql Server2014提示找不到实例的问题解决方案

SQL SERVER2014的安装

在 SQL Server 2008 R2 中为特定数据库用户设置最大查询数