我想在 Azure Key Vault 的 HSM 中生成一个私钥,然后创建一个证书签名请求 CSR,其中包含相应的公钥。
正在生成公钥,然后是 CSR,甚至可以在今天的 Key Vault 中生成 - 我在文档中没有看到任何关于生成相应公钥的提及?(或者也许我只是不了解 HSM 的本质?)
回退似乎是在其他地方创建密钥和 CSR,并将私钥导入 Key Vault HSM。这显然不如 HSM 之外从未存在过的私钥好。
我想在 Azure Key Vault 的 HSM 中生成一个私钥,然后创建一个证书签名请求 CSR,其中包含相应的公钥。
正在生成公钥,然后是 CSR,甚至可以在今天的 Key Vault 中生成 - 我在文档中没有看到任何关于生成相应公钥的提及?(或者也许我只是不了解 HSM 的本质?)
回退似乎是在其他地方创建密钥和 CSR,并将私钥导入 Key Vault HSM。这显然不如 HSM 之外从未存在过的私钥好。
这是在 Windows 上执行此操作的一种方法
使用适用于 .Net 的 Azure Key Vault SDK,在 Azure Key Vault 的 HSM 中创建密钥对
// Assuming you have a keyVaultClient object using the SDK var keyBundle = keyVaultClient.CreateKeyAsync(keyVaultUri, "myKey01", "RSA-HSM", 2048).GetAwaiter().GetResult();
将创建的密钥对的公钥作为 CSP blob 获取
var rsaCryptoProvider = new RSACryptoServiceProvider(); var rsaParameters = new RSAParameters() { Modulus = keyBundle.Key.N, Exponent = keyBundle.Key.E }; rsaCryptoProvider.ImportParameters(rsaParameters); var cspBlob = rsaCryptoProvider.ExportCspBlob(false);
PKCS10 (CSR) 的 subjectPublicKeyInfo 组件包含有关被认证的公钥的信息。subjectPublicKeyInfo 是 Windows Cryptography API: Next Generation (CNG) 的 ASN1 编码CERT_PUBLIC_KEY_INFO 结构。
本部分需要熟悉如何使用 Windows 加密 API:下一代 (CNG)。CNG 是一个原生 API,您需要使用 PInvoke (DllImport) 从托管代码中调用它。
一个。使用 NCryptOpenStorageProvider(SO 上的链接限制,搜索 MSDN)
[DllImport("ncrypt.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern ErrorCode NCryptOpenStorageProvider( [Out] out SafeNCryptProviderHandle phProvider, string pszProviderName, uint dwFlags);
打开 CNG 密钥存储提供程序 -
SafeNCryptProviderHandle providerHandle = null; var result = NCryptOpenStorageProvider( out providerHandle, null, 0);
湾。使用 NCryptImportKey(SO 上的链接限制,搜索 MSDN)
[DllImport("ncrypt.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern int NCryptImportKey( SafeNCryptProviderHandle hProvider, IntPtr hImportKey, // NCRYPT_KEY_HANDLE string pszBlobType, IntPtr pParameterList, // NCryptBufferDesc * [Out] out SafeNCryptKeyHandle phKey, [MarshalAs(UnmanagedType.LPArray)] byte[] pbData, int cbData, uint dwFlags);
将 (2) 中的 cspBlob 导入密钥服务提供者
SafeNCryptKeyHandle keyHandle; var result = NCryptImportKey( providerHandle, IntPtr.Zero, "CAPIPUBLICBLOB", IntPtr.Zero, out keyHandle, cspBlob, cspBlob.Length, 0x00000040);
C。keyHandle 现在可以与 CryptExportPublicKeyInfo 一起使用 -(SO 上的链接限制,搜索 MSDN)为 CSR 对象创建 CERT_PUBLIC_KEY_INFO 结构。查看文档中提供的示例。
填写PKCS10(CSR)的其他字段,ASN1对其进行编码。
使用适当的散列算法创建 (5) 的编码结果的散列。使用 (1) 中创建的密钥对的私钥对哈希进行签名
var signature = keyVaultClient.SignAsync(keyBundle.KeyIdentifier.Identifier, "RS256", hash).GetAwaiter().GetResult();
将签名附加到 (5) 的编码结果中,然后 ANS1 再次对其进行编码。
您可能会发现使用 Windows CertEnroll COM 接口更容易:创建和初始化 IX509CertificateRequestPkcs10 对象( https://msdn.microsoft.com/en-us/library/windows/desktop/aa377505(v=vs.85).aspx ),填充其属性,然后获取其 RawDataToBeSigned 属性并将其发送到 Azure Key Vault 以进行签名。这可以从本机代码、.NET 等调用。
另一种 [但更复杂的] 方法是使用构建 COM 接口的底层 Windows API。此示例 ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa382364(v=vs.85).aspx ) 演示了如何生成和签署这样的 PKCS#10。在我的脑海中,您应该能够通过替换对 CryptSignAndEncodeCertificate 的调用来调整示例:
调用 CryptEncodeObjectEx 到 ASN.1 将 CERT_REQUEST_INFO 对象编码为二进制;和
调用 Key Vault 以签署该二进制 blob。
然后,您需要构造一个 CERT_SIGNED_CONTENT_INFO,设置:
一个。ToBeSigned 成员到 #1 的编码二进制文件;
湾。用于使用 Key Vault 签名的算法的 SignatureAlgorithm 成员;和
C。从 Key Vault 返回的签名的签名成员。
然后,您将再次调用 CryptEncodeObjectEx 以 ASN.1 将生成的 PKCS #10 编码为二进制。
上面的解决方案是有效的,但实际上将通过 .NET 互操作通过 IMO 更复杂的方法(将示例中的 Crypto API v1.0 调用替换为 Crypto Next Gen 调用)。除非我有特定的原因,否则我不会从那里开始。