【问题标题】:Can I create a CSR from Azure Key Vault?是否可以从 Azure Key Vault 创建 CSR?
【发布时间】:2016-04-24 03:43:36
【问题描述】:

我想在 Azure Key Vault 的 HSM 中生成一个私钥,然后创建一个证书签名请求 CSR,其中包含相应的公钥。

正在生成公钥,随后生成 CSR,甚至在今天的 Key Vault 中也是可能的 - 我在文档中没有看到任何关于生成相应公钥的提及? (或者也许我只是不了解 HSM 的本质?)

回退似乎是在别处创建密钥和 CSR,并将私钥导入 Key Vault HSM。这显然不如 HSM 之外从未存在过的私钥。

【问题讨论】:

    标签: pki csr azure-keyvault


    【解决方案1】:

    这是在 Windows 上执行此操作的一种方法

    1. 使用Azure Key Vault SDK for .Net,在 Azure Key Vault 的 HSM 中创建密钥对

      // Assuming you have a keyVaultClient object using the SDK
      var keyBundle = keyVaultClient.CreateKeyAsync(keyVaultUri, "myKey01", "RSA-HSM", 2048).GetAwaiter().GetResult();
      
    2. 将创建的密钥对的公钥作为 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);
      
    3. PKCS10 (CSR) 的 subjectPublicKeyInfo 组件包含有关被认证的公钥的信息。 subjectPublicKeyInfo 是 Windows Cryptography API: Next Generation (CNG) 的 ASN1 编码 CERT_PUBLIC_KEY_INFO structure。

      本部分要求您熟悉如何使用 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);
      

      b.使用 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 结构。查看文档中提供的示例。

    4. 填写PKCS10(CSR)的其他字段,ASN1对其进行编码。

    5. 使用适当的散列算法创建 (5) 的编码结果的散列。使用 (1) 中创建的密钥对的私钥对哈希进行签名

      var 签名 = keyVaultClient.SignAsync(keyBundle.KeyIdentifier.Identifier, "RS256", hash).GetAwaiter().GetResult();

    6. 将签名附加到 (5) 的编码结果中,ANS1 再次对其进行编码。

    【讨论】:

    • 嗨罗希特,非常感谢。我稍后会尝试消化这个;不得不承认我对 Crypto API 并不感兴趣——以前的、现在的和下一代的。但至少你的回答表明有办法。对我们来说,这在构建基于令牌的身份验证时非常有趣,其中整个信任取决于保护令牌签名密钥。
    • 在 Key Vault 中构建对 CSR 生成的支持难道不是很有意义吗?这不是生成私钥的常见情况吗?
    • 对我来说同样的问题。 Key Vault 缺乏非常基本的 HSM 功能,例如在内部签署 CSR(无需导出宝贵的私钥)。
    【解决方案2】:

    您可能会发现使用 Windows CertEnroll COM 接口更容易:创建并初始化 IX509CertificateRequestPkcs10 对象(https://msdn.microsoft.com/en-us/library/windows/desktop/aa377505(v=vs.85).aspx),填充其属性,然后获取其 RawDataToBeSigned 属性并将其发送到 Azure Key保险柜要签名。这可以从本机代码、.NET 等调用。

    另一种 [但更复杂的] 方法是使用构建 COM 接口的底层 Windows API。此示例 (https://msdn.microsoft.com/en-us/library/windows/desktop/aa382364(v=vs.85).aspx) 演示如何生成和签署这样的 PKCS#10。在我的脑海中,您应该能够通过将 CryptSignAndEncodeCertificate 的调用替换为:

    1. 调用 CryptEncodeObjectEx 到 ASN.1 将 CERT_REQUEST_INFO 对象编码为二进制;和

    2. 调用 Key Vault 以签署该二进制 blob。

    3. 然后您需要构造一个 CERT_SIGNED_CONTENT_INFO,设置:

      一个。 ToBeSigned 成员到 #1 的编码二进制文件;

      b.用于使用 Key Vault 签名的算法的 SignatureAlgorithm 成员;和

      c。从 Key Vault 返回的签名的 Signature 成员。

    4. 然后您将再次调用 CryptEncodeObjectEx 以 ASN.1 将生成的 PKCS #10 编码为二进制。

    上述解决方案是有效的,但实际上将通过 .NET 互操作通过 IMO 更复杂的方法(将示例中的 Crypto API v1.0 调用替换为 Crypto Next Gen 调用)。除非我有特定的原因,否则我不会从那里开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      • 2023-03-16
      • 2021-10-11
      • 2021-10-10
      • 2016-08-30
      • 1970-01-01
      • 2019-10-16
      相关资源
      最近更新 更多