我可以从Azure Key Vault创建CSR吗?

时间:2016-01-18 20:43:08

标签: pki csr azure-keyvault

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

现在生成公钥,以及随后的CSR,甚至可能在Key Vault中生成 - 我没有看到在文档中生成相应公钥的任何提及? (或者我可能只是不了解HSM的性质?)

似乎是在其他地方创建密钥和CSR并将私钥导入Key Vault HSM。这显然不如HSM之外从未存在的私钥那么好。

2 个答案:

答案 0 :(得分:4)

以下是在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密码学API:下一代(CNG)的ASN1编码CERT_PUBLIC_KEY_INFO structure

    本节需要熟悉如何使用Windows Cryptography API:Next Generation(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);
    
      
         

    ℃。 keyHandle现在可以与CryptExportPublicKeyInfo一起使用 - (SO上的链接限制,搜索MSDN)为CSR对象创建CERT_PUBLIC_KEY_INFO结构。请查看文档中提供的示例。

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

  5. 使用appopriate散列算法创建(5)的编码结果的散列。使用在(1)

    中创建的密钥对的私钥对哈希进行签名
      

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

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

答案 1 :(得分:2)

您可能会发现使用Windows CertEnroll COM接口更容易:创建初始化IX509CertificateRequestPkcs10对象(https://msdn.microsoft.com/en-us/library/windows/desktop/aa377505(v=vs.85).aspx),填充其属性,然后获取其RawDataToBeSigned属性并将其发送到要签名的Azure密钥保管库。这可以从本机代码,.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,设置:

    一个。来自#1;

    的编码二进制文件的ToBeSigned成员

    湾用于与Key Vault签名的算法的SignatureAlgorithm成员;和

    ℃。密钥保险库返回签名的签名成员。

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

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