非对称密钥不匹配增强的强名称
Asymmetric Key not matching Enhanced Strong Name
所以我在互联网上搜索了很多答案。我已经成功创建了一个模板,用于以编程方式使用简单的强名称和证书将 CLR Assemblies
部署到多个(超过 100 个)SQL Server
实例和服务器......甚至不需要使用 IDE 类似于 VISUAL STUDIO 除了语法和检查程序集。 :)
唯一的问题似乎是我用来签名的 public 密钥,因为 C# 编译器 csc.exe
使用 SHA-1 散列来签署程序集。所以唯一的解决方法是使用 Enhanced Strong Naming
或 MSBuild
(这里不是真正的选项)。
增强型强命名是一个足够简单的过程:
创建强名称密钥 (snk
) 文件:
sn.exe -k [RSA_Length] CLR_IdentityKey.snk
发布 public 密钥并使用 SHA-2
对其进行哈希处理
sn.exe -p CLR_IdentityKey.snk CLR_PubKey.snk sha256
延迟使用 public 密钥对程序集进行签名(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
想要使用增强型强名称方法对我的程序集进行签名的主要原因有两个:
- 避免在多台服务器上长时间公开私钥。
- 提供发布散列 public snk 的替代方法,并提供在创建
ASYMMETRIC KEY
时设置加密密码的选项。
请注意,虽然我可以同时使用 pfx
和一个简单的 snk 文件来完成此操作,但此处的程序集是一个简单的 HTTP POST
操作,并且证书的成本高得令人望而却步在内网环境中很少使用。
现在检查已签名的程序集,我在清单中看到以下内容:
Public key (hash algorithm: sha256):
002400000c80000014010000060200...
Public key token is b8ee775aa5bfbc5b
显然 sn.exe 已成功使用 SHA-2 方法对程序集进行签名。
不幸的是,当我尝试基于 SQL 服务器中的这个签名程序集创建我的非对称密钥时,似乎 public 密钥关联不正确。
Msg 10327, Level 14, State 1, Line 14
CREATE ASSEMBLY for assembly
'CLR_Assembly' failed because assembly 'CLR_Assembly' is not authorized for
PERMISSION_SET = UNSAFE. The assembly is authorized when either of
the following is true: the database owner (DBO) has UNSAFE ASSEMBLY
permission and the database has the TRUSTWORTHY database property on;
or the assembly is signed with a certificate or an asymmetric key that
has a corresponding login with UNSAFE ASSEMBLY permission.
示例代码:
请注意,命名实例和默认名称在位置和安全权限方面存在差异。所选文件夹可能没有足够的权限,因此您可能必须添加它。
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 服务器找不到正确的 public 密钥,而它们应该是相同的?
有谁知道在 SQL 服务器中获取延迟程序集的工作示例?
Why is SQL Server unable to find the correct public key when they are supposedly one and the same?
如果您临时将您的数据库设置为TRUSTWORTHY ON
以便您可以加载程序集,那么您应该能够看到问题。
SELECT * FROM sys.asymmetric_keys;
SELECT * FROM sys.assemblies;
在 运行 之后,您应该看到 sys.asymmetric_keys
的 "thumbprint" 列与 [=113= 中显示的 "publickeytoken" 属性 不匹配] 列 sys.assemblies
。这很可能是由于在 运行 sn -p
时使用 SHA-256,但您别无选择,因为 SHA-1 不适用于增强型强命名。非对称密钥的 "thumbprint" 是 SHA-1,您无法控制它,因此无法使它们匹配。
Does anyone know of a working example of getting delayed assemblies in SQL Server?
幸运的是,Enhanced Strong Naming mentions using the AssemblySignatureKeyAttribute 属性的文档允许一些遗留场景工作,这当然是一个。事实上,使用该属性确实允许增强的强命名工作。
使用 SQLCLR 获得增强强命名的步骤(在 SQL Server 2016 SP1 上测试):
创建身份和签名密钥对:
sn -k 2048 IdentityKey.snk
sn -k 2048 SignatureKey.snk
从两个密钥对中提取 public 密钥:
sn -p IdentityKey.snk IdentityPubKey.snk
sn -p SignatureKey.snk SignaturePubKey.snk sha256
请注意,身份密钥 不是 使用 sha256
,因此使用默认值 sha1
,而签名密钥 是 使用 sha256
.
生成 AssemblySignatureKey
属性所需的 publicKey
和 counterSignature
值:
sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk
将前一步中生成的两个值复制到其中一个源文件中(即通常 AssemblyInfo.cs
):
[assembly:System.Reflection.AssemblySignatureKey(
"public" +
"key" +
"value",
"counter" +
"Signature" +
"value"
)]
使用延迟签名编译程序集:
csc /target:library /out:MyAssembly.dll SqlStoredProcedure.cs
/keyfile:IdentityPubKey.snk /delaySign+
重新签署程序集:
sn -Ra MyAssembly.dll SignatureKey.snk
在 SQL 服务器中,通过 DLL 在 master
中创建非对称密钥:
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
意味着 EXTERNAL ACCESS
,但是从 SQL Server 2017 开始,如果您使用 clr strict
的默认配置启用,则需要 UNSAFE ASSEMBLY
.
更改为目标数据库并创建程序集:
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;
P.S。您的其他顾虑大多不是问题:
- 不确定您认为私钥是如何暴露的,但它不是
ASYMMETRIC KEY
的一部分(因为它是从程序集创建的)所以没有这种可能性。
- 无法通过
CREATE ASYMMETRIC KEY
设置密码,因为私钥不存在(因为它是从程序集创建的)。
- 如果您更喜欢使用证书,则不需要任何费用,因为自签名证书(通过
MAKECERT
或 PowerShell)很好,尤其是对于一个小型内部项目。使用证书的一个好处是您可以从十六进制字节而不是文件或程序集创建它,并且由于您也可以从十六进制字节创建程序集,因此您的安装脚本可以完全移植,因为它没有任何文件系统参考 :-).
所以我在互联网上搜索了很多答案。我已经成功创建了一个模板,用于以编程方式使用简单的强名称和证书将 CLR Assemblies
部署到多个(超过 100 个)SQL Server
实例和服务器......甚至不需要使用 IDE 类似于 VISUAL STUDIO 除了语法和检查程序集。 :)
唯一的问题似乎是我用来签名的 public 密钥,因为 C# 编译器 csc.exe
使用 SHA-1 散列来签署程序集。所以唯一的解决方法是使用 Enhanced Strong Naming
或 MSBuild
(这里不是真正的选项)。
增强型强命名是一个足够简单的过程:
创建强名称密钥 (
snk
) 文件:sn.exe -k [RSA_Length] CLR_IdentityKey.snk
发布 public 密钥并使用
对其进行哈希处理SHA-2
sn.exe -p CLR_IdentityKey.snk CLR_PubKey.snk sha256
延迟使用 public 密钥对程序集进行签名(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
想要使用增强型强名称方法对我的程序集进行签名的主要原因有两个:
- 避免在多台服务器上长时间公开私钥。
- 提供发布散列 public snk 的替代方法,并提供在创建
ASYMMETRIC KEY
时设置加密密码的选项。
请注意,虽然我可以同时使用 pfx
和一个简单的 snk 文件来完成此操作,但此处的程序集是一个简单的 HTTP POST
操作,并且证书的成本高得令人望而却步在内网环境中很少使用。
现在检查已签名的程序集,我在清单中看到以下内容:
Public key (hash algorithm: sha256): 002400000c80000014010000060200...
Public key token is b8ee775aa5bfbc5b
显然 sn.exe 已成功使用 SHA-2 方法对程序集进行签名。
不幸的是,当我尝试基于 SQL 服务器中的这个签名程序集创建我的非对称密钥时,似乎 public 密钥关联不正确。
Msg 10327, Level 14, State 1, Line 14
CREATE ASSEMBLY for assembly 'CLR_Assembly' failed because assembly 'CLR_Assembly' is not authorized for PERMISSION_SET = UNSAFE. The assembly is authorized when either of the following is true: the database owner (DBO) has UNSAFE ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with UNSAFE ASSEMBLY permission.
示例代码: 请注意,命名实例和默认名称在位置和安全权限方面存在差异。所选文件夹可能没有足够的权限,因此您可能必须添加它。
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 服务器找不到正确的 public 密钥,而它们应该是相同的?
有谁知道在 SQL 服务器中获取延迟程序集的工作示例?
Why is SQL Server unable to find the correct public key when they are supposedly one and the same?
如果您临时将您的数据库设置为TRUSTWORTHY ON
以便您可以加载程序集,那么您应该能够看到问题。
SELECT * FROM sys.asymmetric_keys;
SELECT * FROM sys.assemblies;
在 运行 之后,您应该看到 sys.asymmetric_keys
的 "thumbprint" 列与 [=113= 中显示的 "publickeytoken" 属性 不匹配] 列 sys.assemblies
。这很可能是由于在 运行 sn -p
时使用 SHA-256,但您别无选择,因为 SHA-1 不适用于增强型强命名。非对称密钥的 "thumbprint" 是 SHA-1,您无法控制它,因此无法使它们匹配。
Does anyone know of a working example of getting delayed assemblies in SQL Server?
幸运的是,Enhanced Strong Naming mentions using the AssemblySignatureKeyAttribute 属性的文档允许一些遗留场景工作,这当然是一个。事实上,使用该属性确实允许增强的强命名工作。
使用 SQLCLR 获得增强强命名的步骤(在 SQL Server 2016 SP1 上测试):
创建身份和签名密钥对:
sn -k 2048 IdentityKey.snk sn -k 2048 SignatureKey.snk
从两个密钥对中提取 public 密钥:
sn -p IdentityKey.snk IdentityPubKey.snk sn -p SignatureKey.snk SignaturePubKey.snk sha256
请注意,身份密钥 不是 使用
sha256
,因此使用默认值sha1
,而签名密钥 是 使用sha256
.生成
AssemblySignatureKey
属性所需的publicKey
和counterSignature
值:sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk
将前一步中生成的两个值复制到其中一个源文件中(即通常
AssemblyInfo.cs
):[assembly:System.Reflection.AssemblySignatureKey( "public" + "key" + "value", "counter" + "Signature" + "value" )]
使用延迟签名编译程序集:
csc /target:library /out:MyAssembly.dll SqlStoredProcedure.cs /keyfile:IdentityPubKey.snk /delaySign+
重新签署程序集:
sn -Ra MyAssembly.dll SignatureKey.snk
在 SQL 服务器中,通过 DLL 在
master
中创建非对称密钥: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
意味着EXTERNAL ACCESS
,但是从 SQL Server 2017 开始,如果您使用clr strict
的默认配置启用,则需要UNSAFE ASSEMBLY
.更改为目标数据库并创建程序集:
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;
P.S。您的其他顾虑大多不是问题:
- 不确定您认为私钥是如何暴露的,但它不是
ASYMMETRIC KEY
的一部分(因为它是从程序集创建的)所以没有这种可能性。 - 无法通过
CREATE ASYMMETRIC KEY
设置密码,因为私钥不存在(因为它是从程序集创建的)。 - 如果您更喜欢使用证书,则不需要任何费用,因为自签名证书(通过
MAKECERT
或 PowerShell)很好,尤其是对于一个小型内部项目。使用证书的一个好处是您可以从十六进制字节而不是文件或程序集创建它,并且由于您也可以从十六进制字节创建程序集,因此您的安装脚本可以完全移植,因为它没有任何文件系统参考 :-).