是否可以在 SQL Server 2014 中為 .NET 框架程序集創建非對稱密鑰?
我正在 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 依賴的一個程序集(如果我不這樣做,我會收到錯誤消息)
與此同時,我讀到了開啟 TRUSTWORTHY ON 有多糟糕,我嘗試採用非對稱密鑰方式來避免開啟它。
在簽署我自己的程序集之前,我知道我必須創建一個密鑰,
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 ?
不,我從來沒有找到實現這一目標的方法。用於簽署 .NET Framework 程序集的密鑰是 Microsoft 內部/私有的。嘗試的選項:
- 提取私鑰/載入到 SQL Server:不可能,否則密鑰不會是“私有的”。簽名/強命名系統是有效的,因為外人不能聲稱他們簽署了程式碼。
sn添加簽名:我嘗試使用該實用程序添加一個新簽名。由於以下原因不起作用:無法重新簽署程序集 - 程序集的公鑰與簽名公鑰不匹配。
但是,即使這確實有效,但這可能並不意味著將其載入到 SQL Server 中會有效,因為它與您作為資源添加到項目中的程序集不同。其他 .NET Framework DLL,如果有任何其他依賴項,將只知道原始簽名。
- 刪除目前簽名並添加一個新簽名:我嘗試使用
ILDASMto disassembleSystem.Runtime.Serialization.dll,然後添加一個從創建的新私鑰sn -k,然後重新連結 usingILASM,但這ILASM一步失敗了(我沒有時間進一步調查)。但就像上面的選項一樣,即使這確實有效,您也必須將 Json.NET 項目引用更改為
System.Runtime.Serialization這個新的 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 或做“不安全”的事情等,這應該可以工作。但是,我沒有時間對此進行測試。