1

所以我已經搜索了很多互聯網尋求答案。我成功創建了一個模板,用於以編程方式使用簡單的強名稱和證書來部署CLR Assemblies到多個(超過100個)SQL Server實例和服務器......甚至不需要使用像VISUAL STUDIO這樣的IDE,除了語法和檢查程序集。 :)非對稱密鑰不匹配增強強名稱

唯一的catch似乎是我簽署它的公鑰,因爲C#編譯器csc.exe使用SHA-1哈希來簽署程序集。所以唯一的解決方法是使用Enhanced Strong NamingMSBuild(這裏不是真正的選項)。

增強強命名是一個很簡單的過程:

  • 創建強名稱密鑰(snk)文件:

    sn.exe -k [RSA_Length] CLR_IdentityKey.snk

  • 發佈的公鑰和哈希這與SHA-2

    sn.exe -p CLR_IdentityKey.snk CLR_PubKey.snk sha256

  • 延時程序集進行簽名與公鑰(CSC.EXE源決定程序集的.NetFramework兼容性)

    csc.exe /target:library /keyfile:CLR_PubKey.snk /out:CLR_Assembly.dll "YourCSFiles.cs" "YourCSFiles2.cs" "YourCSFiles3.cs" /DelaySign+

  • 然後用與強名稱的原始密鑰辭職大會工具。

    sn.exe -Ra CLR_Assembly.dll CLR_IdentityKey.snk

的主要原因爲希望簽下我的組件與增強的強名稱方法有二:

  1. 避免暴露任何時間長度在多個服務器上的私有密鑰。
  2. 在創建ASYMMETRIC KEY時,提供發佈哈希公共snk的備選方案,並設置加密密碼的選項。

注意的是,雖然我可以同時使用pfx和一個簡單的SNK文件做到這一點,這裏的組件是簡單的HTTP POST動作,和證書的成本過高鑑於其在內部網環境中的小應用。

現在檢查簽名的程序集,我看到清單中的以下內容:

公鑰(散列算法:SHA256): 002400000c80000014010000060200 ...

公鑰標記是b8ee775aa5bfbc5b

所以很明顯sn.exe已經用SHA-2方法成功地簽署了程序集。

不幸的是,當我嘗試根據SQL Server中的此簽名程序集創建我的不對稱密鑰時,似乎公鑰錯誤地關聯了。

消息10327,級別14,狀態1,行14

CREATE組裝 ASSEMBLY 'CLR_Assembly' 失敗,因爲程序集 'CLR_Assembly' 未被授權 PERMISSION_SET =不安全的。如果 中的任何一個成立,則程序集將被授權:數據庫所有者(DBO)具有不安全ASSEMBLY 權限並且數據庫具有TRUSTWORTHY數據庫屬性; 或者程序集是使用證書或非對稱密鑰簽名的, 具有與UNSAFE ASSEMBLY權限相對應的登錄名。

示例代碼: 請注意,在位置和安全權限中,命名實例和默認名稱之間存在差異。選擇的文件夾可能沒有足夠的權限,因此您可能需要添加它。

Powershell的:

# The version of csc.exe dictates the version of .NetFramework your assembly is created. 
$csc_path="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" 
$sn_path="C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\sn.exe" 
$CLR_path="C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\" 

$CLR_Assembly_SNK=$CLR_path + "CLR_SNK.dll" 
$CLR_Assembly_DelaySign=$CLR_path + "CLR_DelaySign.dll" 

$cs_BackComp="C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\BackwardsCompatibility.cs " 
$cs_MyMethods="C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\MyMethods.cs " 
$cs_Main="C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\CLR_JSON_Program.cs" 

$CLR_IdentityKey=$CLR_path + "CLR_IdentityKey.snk" 
$CLR_IdentityKey1=$CLR_path + "CLR_IdentityKey1.snk" 
$CLR_PubKey=$CLR_path + "CLR_PubKey.snk" 

#using SNK method 
& $sn_path -k 2048 $CLR_IdentityKey 
& $csc_path /target:library /out:$CLR_Assembly_SNK /keyfile:$CLR_IdentityKey $cs_BackComp $cs_MyMethods $cs_Main 
& $sn_path -Tp $CLR_Assembly_SNK 

# using delaySign+ method version 
& $sn_path -k 2048 $CLR_IdentityKey1 
& $sn_path -p $CLR_IdentityKey $CLR_PubKey sha256 
& $csc_path /target:library /out:$CLR_Assembly_DelaySign /keyfile:$CLR_PubKey $cs_BackComp $cs_MyMethods $cs_Main /DelaySign+ 
& $sn_path -Ra $CLR_Assembly_DelaySign $CLR_IdentityKey 
& $sn_path -Tp $CLR_Assembly_DelaySign 

T-SQL代碼:

USE MASTER 
GO 
CREATE ASYMMETRIC KEY CLR_SNK_KEY 
FROM EXECUTABLE FILE = 'C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\CLR_SNK.dll' 
CREATE LOGIN CLR_SNK 
FROM ASYMMETRIC KEY CLR_SNK_KEY 
GRANT UNSAFE ASSEMBLY TO CLR_SNK 
GO 
CREATE ASSEMBLY CLR_SNK_ASSEMBLY 
AUTHORIZATION [dbo] 
FROM 'C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\CLR_SNK.dll' 
WITH PERMISSION_SET = UNSAFE 
GO 
DROP LOGIN CLR_SNK 
DROP ASYMMETRIC KEY CLR_SNK_KEY 
DROP ASSEMBLY CLR_SNK_ASSEMBLY 
GO 
/*DelaySign+ Version*/ 
CREATE ASYMMETRIC KEY CLR_Delay_KEY 
FROM EXECUTABLE FILE = 'C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\CLR_DelaySign.dll' 
CREATE LOGIN CLR_Delay 
FROM ASYMMETRIC KEY CLR_Delay_KEY 
GRANT UNSAFE ASSEMBLY TO CLR_Delay 
GO 
-- fails here due to the ASYMMETRIC key not matching the assembly 
CREATE ASSEMBLY CLR_Delay_Assembly 
AUTHORIZATION [dbo] 
FROM 'C:\Program Files\Microsoft SQL Server\MSSQL13.TESTSQL\MSSQL\JOBS\CLR_DelaySign.dll' 
WITH PERMISSION_SET = UNSAFE 

我的C#組件使用var postRequest = (HttpWebRequest)WebRequest.Create(uri);這不是一種安全的方法,並且需要至少EXTERNAL_ACCESS。

但是,SQL Server 2017不再支持CAS安全方法,而是引入了快速修復sp_configure'clr strict security`設置。使用UNSAFE創建未來的CLR。 Microsoft (April 19, 2017): CLR String Security

爲什麼SQL Server無法找到正確的公鑰時,他們被認爲是一個一樣的?

有誰知道在SQL Server中獲取延遲程序集的工作示例?

+0

請注意,ALTER DATABASE [DB_Name] SET TRUSTWORTHY ON'是管理程序集的一種可怕且可能很懶惰的方法。 –

+0

所以你完成了大會的所有簽名。但是你有沒有告訴SQL Server你相信任何關於UNSAFE程序集的關鍵材料?也就是說,您是否創建了基於密鑰或證書的登錄/用戶並授予其不安全的裝配權限?如果是這樣,您是否也可以發佈該代碼(請從您的實際密鑰材料中進行編輯)。 –

+0

@BenThul在回答問題時添加了示例代碼 –

回答

1

爲什麼SQL Server無法在找到正確的公鑰時被認爲是同一個公鑰?

如果暫時設置你的數據庫TRUSTWORTHY ON這樣就可以加載大會,那麼你應該能夠看到這個問題。

SELECT * FROM sys.asymmetric_keys; 
SELECT * FROM sys.assemblies; 

運行這些後,你應該看到的sys.asymmetric_keys的「指紋」列不匹配的sys.assemblies的「clr_name」列中顯示的「公鑰」屬性。這很可能是由於在運行sn -p時使用SHA-256,但由於SHA-1不適用於增強強名稱,因此您別無選擇。非對稱密鑰的「指紋」是SHA-1,您無法控制該密碼,因此無法使其匹配。

有誰知道在SQL Server中獲取延遲程序集的工作示例嗎?

幸運的是,對於Enhanced Strong Naming說明文檔中提到使用AssemblySignatureKeyAttribute屬性,讓一些舊的情況下工作,這當然可能是一個。事實上,使用該屬性確實可以使增強強名稱工作。

  1. 創建的身份和簽名密鑰對:

    步驟獲得增強的強命名與SQLCLR工作(SQL服務器2016 SP1上測試)

    sn -k 2048 IdentityKey.snk 
    sn -k 2048 SignatureKey.snk 
    
  2. 提取從公鑰兩個密鑰對:

    sn -p IdentityKey.snk IdentityPubKey.snk 
    sn -p SignatureKey.snk SignaturePubKey.snk sha256 
    

    請注意,身份密鑰是不是使用sha256,因此使用默認sha1,而簽名密鑰使用sha256

  3. 生成所需AssemblySignatureKey屬性publicKeycounterSignature值:

    [assembly:System.Reflection.AssemblySignatureKey(
    "public" + 
    "key" + 
    "value", 
    "counter" + 
    "Signature" + 
    "value" 
    )] 
    
  4. :在先前步驟中到源文件中的一個(即,通常 AssemblyInfo.cs)產生

    sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk 
    
  5. 複印兩個值

  6. 用延遲簽名編譯程序集:

    csc /target:library /out:MyAssembly.dll SqlStoredProcedure.cs 
         /keyfile:IdentityPubKey.snk /delaySign+ 
    
  7. 重新簽名大會:

    sn -Ra MyAssembly.dll SignatureKey.snk 
    
  8. 在SQL Server中,從DLL中master創建非對稱密鑰:

    USE [master]; 
    
    CREATE ASYMMETRIC KEY [MyAsymKey] 
    FROM EXECUTABLE FILE = N'C:\path\to\MyAssembly.dll'; 
    
  9. 從非對稱密鑰,並授予創建登錄它可以是EXTERNAL ACCESS ASSEMBLYUNSAFE ASSEMBLY

    CREATE LOGIN [MyAsymKeyLogin] 
    FROM ASYMMETRIC KEY [MyAsymKey]; 
    
    GRANT UNSAFE ASSEMBLY TO [MyAsymKeyLogin]; 
    

    您只需要授予其中一個爲UNSAFE就意味着EXTERNAL ACCESS,但從SQL Server 2017開始,如果您使用默認配置clr strict啓用,那麼這需要是UNSAFE ASSEMBLY

  10. 切換到目標數據庫和創建大會:

    USE [Test]; 
    ALTER DATABASE CURRENT SET TRUSTWORTHY OFF; -- Just to be sure! 
    
    CREATE ASSEMBLY [MyAssembly] 
    FROM N'C:\path\to\MyAssembly.dll' 
    WITH PERMISSION_SET = UNSAFE; 
    

附:你的其他問題大多是非問題:

  1. 不知道是怎麼想的私鑰可能會暴露,但它不是ASYMMETRIC KEY(因爲正在從一個程序集創建它)的一部分,所以不存在潛力。
  2. 通過CREATE ASYMMETRIC KEY設置密碼不是一個選項,因爲私鑰不存在(因爲它是從程序集創建的)。
  3. 如果您更喜歡使用證書,那麼作爲自簽名證書(通過MAKECERT或PowerShell)是沒有問題的,特別是對於這是一個小型的內部項目。使用證書帶來的好處是您可以使用十六進制字節而不是文件或程序集來創建它,並且由於您還可以從十六進制字節創建程序集,因此您的安裝腳本可以完全移植,因爲它不會有任何文件系統參考:-)。
+1

+1,這個問題已經變得塵土飛揚,並且在遺留答案中加倍努力。雖然我改變了我的思維過程(這必須在不同的版本上工作,所以SQL Server 2008 R2到2017年),但我很欣賞詳細,明確的答案。 –