非对称密钥与增强型强名称不匹配

时间:2017-05-06 09:37:26

标签: sql-server .net-assembly sqlclr encryption-asymmetric strongname

所以我已经在互联网上搜索了很多答案。我已成功创建了一个模板,用于以编程方式使用简单的强名称和证书将CLR Assemblies部署到多个(超过100个)SQL Server个实例和服务器...甚至不需要使用类似IDE的IDE VISUAL STUDIO除语法和检查程序集外。 :)

唯一的问题似乎是我签署的公钥,因为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+

  • 然后使用StrongName工具使用原始密钥重新装配程序集。

    sn.exe -Ra CLR_Assembly.dll CLR_IdentityKey.snk

想要使用增强型强名称方法对程序集进行签名的主要原因有两个:

  1. 避免在多个服务器上暴露私钥任何时间​​。
  2. 在创建ASYMMETRIC KEY时,提供发布散列公共snk的备用内容以及设置加密密码的选项。
  3. 请注意,虽然我可以使用pfx和简单的snk文件来完成此操作,但此处的程序集是一个简单的HTTP POST操作,并且由于使用量很小,因此证书的成本过高在Intranet环境中。

    现在检查已签名的程序集,我在清单中看到以下内容:

      

    公钥(哈希算法:sha256):   002400000c80000014010000060200 ...

         

    公钥令牌是b8ee775aa5bfbc5b

    很明显,sn.exe已经使用SHA-2方法成功签署了程序集。

    不幸的是,当我尝试在SQL Server中基于此签名程序集创建我的非对称密钥时,似乎公钥密钥关联不正确。

      

    Msg 10327,Level 14,State 1,Line 14

         

    为装配创建装配   'CLR_Assembly'失败,因为未授权程序集'CLR_Assembly'   PERMISSION_SET = UNSAFE。任何一个组件都被授权   以下情况属实:数据库所有者(DBO)具有UNSAFE 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中获取延迟程序集的工作示例?

1 个答案:

答案 0 :(得分:1)

  

为什么SQL Server在它们被认为是同一个时无法找到正确的公钥?

如果暂时将数据库设置为TRUSTWORTHY ON,以便您可以加载程序集,那么您应该能够看到问题。

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

运行之后你应该看到"指纹" sys.asymmetric_keys的列与" publickeytoken"不匹配属性显示在" clr_name" sys.assemblies的列。这很可能是因为在运行sn -p时使用SHA-256,但您没有选择,因为SHA-1不适用于增强型强命名。 "指纹"非对称密钥是SHA-1,你无法控制它,因此无法使它们匹配。

  

有没有人知道在SQL Server中获取延迟程序集的工作示例?

幸运的是,Enhanced Strong Naming的文档提到使用AssemblySignatureKeyAttribute属性来允许一些遗留场景工作,这当然可以是一个。事实上,使用该属性确实允许增强强命名工作。

使用SQLCLR获得增强型强命名的步骤(在SQL Server 2016 SP1上测试):

  1. 创建身份和签名密钥对:

    sn -k 2048 IdentityKey.snk
    sn -k 2048 SignatureKey.snk
    
  2. 从两个密钥对中提取公钥:

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

    请注意,Identity密钥使用sha256,因此使用默认sha1,而签名密钥 使用{{1} }}

  3. 生成sha256属性所需的publicKeycounterSignature值:

    AssemblySignatureKey
  4. 将前一步骤中生成的两个值复制到一个源文件中(即通常为sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk ):

    AssemblyInfo.cs
  5. 使用延迟签名编译程序集:

    [assembly:System.Reflection.AssemblySignatureKey(
    "public" +
    "key" +
    "value",
    "counter" +
    "Signature" +
    "value"
    )]
    
  6. 重新签署大会:

    csc /target:library /out:MyAssembly.dll SqlStoredProcedure.cs
          /keyfile:IdentityPubKey.snk /delaySign+
    
  7. 在SQL Server中,从DLL中创建sn -Ra MyAssembly.dll SignatureKey.snk 中的非对称密钥:

    master
  8. 从该非对称密钥创建登录并授予其USE [master]; CREATE ASYMMETRIC KEY [MyAsymKey] FROM EXECUTABLE FILE = N'C:\path\to\MyAssembly.dll'; EXTERNAL ACCESS ASSEMBLY

    UNSAFE ASSEMBLY

    您只需要授予其中一个CREATE LOGIN [MyAsymKeyLogin] FROM ASYMMETRIC KEY [MyAsymKey]; GRANT UNSAFE ASSEMBLY TO [MyAsymKeyLogin]; 隐含UNSAFE,但从SQL Server 2017开始,如果您使用的是EXTERNAL ACCESS的默认配置,则需要是clr strict

  9. 更改为目标数据库并创建程序集:

    UNSAFE ASSEMBLY
  10. P.S。您的其他问题主要是非问题:

    1. 不确定您认为私钥是如何暴露的,但它不是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; 的一部分(因为它是从程序集创建的),因此没有潜力。
    2. 通过ASYMMETRIC KEY设置密码不是一个选项,因为私钥不存在(因为它是从程序集创建的)。
    3. 如果您更喜欢使用证书,则无需支付任何费用,因为自签名证书(通过CREATE ASYMMETRIC KEY或PowerShell)是可以的,特别是对于这是一个小型的内部项目。使用证书的一个好处是您可以从十六进制字节而不是文件或程序集创建它,并且因为您也可以从十六进制字节创建程序集,您的安装脚本可以完全可移植,因为它不会有任何文件系统引用: - )。