我需要从 Azure Key Vault 下载 x509 证书并将其导入 SQL Server 以用于 TDE。
注意:我不是指 EKM 提供程序/异步密钥,其中 SQL 访问密钥保管库以在需要时提取密钥。
我的用例很简单:从密钥保管库获取证书并将其加载到 SQL Server 中。由于安全要求,无法将证书保存到 SQL Server 可以访问的文件中。
我可以成功下载证书并将其转换为 X509Certificate2 对象,但是当我在 SQL Server 中运行 CREATE CERTIFICATE 语句时,它成功完成但不包含私钥。
我相信我需要指定一个PRIVATE KEY (BINARY = private_key_bits )
子句,但我不知道如何以 SQL Server 可接受的格式从 X509Certificate2 对象中提取私钥。
此 powershell 脚本运行时没有错误,但不包含私钥:
$keyVault = "my-key-vault"
$CertName = "tde-certificate"
$SQLInstance = ".\SQLEXPRESS"
$SQLCertName = "KeyVault_TDECert"
# download the KeyVaultSecret for the cert as base64 string
$certBase64 = Get-AzKeyVaultSecret -VaultName $keyVault -Name $CertName -AsPlainText
# Convert to a [System.Security.Cryptography.X509Certificates.X509Certificate2] object
$certBytes = [convert]::FromBase64String($certBase64)
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes, $null) # byte[], $null for password
# CREATE CERTIFICATE in SQL Server.
# $cert.GetRawCertDataString() returns hex encoded data, which SQL Server gladly accepts.
$sql = "CREATE CERTIFICATE [$SQLCertName] FROM BINARY = 0x$($cert.GetRawCertDataString()) "
Invoke-sqlcmd -ServerInstance $SQLInstance -Database master -Query $sql
$cert.HasPrivateKey
返回$true
。
$cert.PrivateKey.key.ExportPolicy
equalNone
应该意味着不受限制。
$cert.PrivateKey.key | Select-Object *
Algorithm : RSA
AlgorithmGroup : RSA
ExportPolicy : None
Handle : Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle
IsEphemeral : False
IsMachineKey : False
KeyName : <xxxxxx>
KeySize : 3072
KeyUsage : AllUsages
ParentWindowHandle : 0
Provider : Microsoft Enhanced RSA and AES Cryptographic Provider
ProviderHandle : Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle
UIPolicy : System.Security.Cryptography.CngUIPolicy
UniqueName : <xxxxxxx>
如何使用私钥从 Key Vault 下载证书并将其加载到 SQL Server 中?
更新1:
更改为 .Export("pfx"); 需要将“Exportable”添加到构造函数以使私钥可导出。
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes, $null) # byte[], $null for password
# CREATE CERTIFICATE in SQL Server.
# $cert.GetRawCertDataString() returns hex encoded data, which SQL Server gladly accepts.
$sql = "CREATE CERTIFICATE [$SQLCertName] FROM BINARY = 0x$($cert.GetRawCertDataString()) "
到
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes, $null, "Exportable") # byte[], $null for password,
# CREATE CERTIFICATE in SQL Server.
# $cert.GetRawCertDataString() returns hex encoded data, which SQL Server gladly accepts.
$sql = "CREATE CERTIFICATE [$SQLCertName] FROM BINARY = 0x$([Convert]::ToHexString($cert.Export(Pfx))) "
现在我收到一个 SQL 错误:
Msg 15468, Level 16, State 6, Line 5
An error occurred during the generation of the certificate.
Google 发现了一篇旧的 MS 博客文章,其中发生这种情况是由于 pfx 不是受支持的证书格式(影响 SQL 2014)。我正在 SQL 2022 上进行测试(但希望支持 2016+)
Get-AzKeyVaultSecret 允许你将证书下载为 .pfx 文件。SQL Server 期望公共证书数据采用 DER 格式,而私钥数据采用 .pvk 格式。
X509Certificate2.GetRawCertDataString() 方法返回 DER 格式的公共数据。
.pvk 是 Microsoft 专有格式,是 csp blob 的薄包装。csp blob 是本机 Win32 加密 API 中使用的私钥二进制表示形式。此问题的格式详细信息:How do I create/export to a .PVK file using C#? 。