Pki 我可以从Azure密钥库创建CSR吗?

Pki 我可以从Azure密钥库创建CSR吗?,pki,csr,azure-keyvault,Pki,Csr,Azure Keyvault,我想在Azure密钥库中的HSM中生成一个私钥,然后创建一个证书签名请求CSR,其中包含相应的公钥 在今天的密钥库中,是否可以生成公钥以及随后的CSR?我在文档中没有提到生成相应的公钥?(或者我只是不理解HSM的本质?) 退一步似乎是在别处创建密钥和CSR,并将私钥导入密钥库HSM。这显然不如HSM之外从未存在过的私钥好。这里有一种在Windows上实现这一点的方法 使用,在Azure密钥库中的HSM中创建密钥对 将创建的密钥对的公钥作为CSP blob获取 PKCS10(CSR)的subj

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

在今天的密钥库中,是否可以生成公钥以及随后的CSR?我在文档中没有提到生成相应的公钥?(或者我只是不理解HSM的本质?)


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

这里有一种在Windows上实现这一点的方法

  • 使用,在Azure密钥库中的HSM中创建密钥对

  • 将创建的密钥对的公钥作为CSP blob获取

  • PKCS10(CSR)的subjectPublicKeyInfo组件包含有关正在认证的公钥的信息。主题PublicKeyInfo是由Windows加密API:Next Generation(CNG)的ASN1编码

    本节要求您熟悉如何使用Windows加密API:Next Generation(CNG)。CNG是一个本机API,您需要使用PInvoke(DllImport)从托管代码中调用它

    a。使用NCryptOpenStorageProvider(SO上的链接限制,搜索MSDN)

    打开CNG密钥存储提供程序-

    b。使用NCryptImportKey(SO上的链接限制,搜索MSDN)

    将cspBlob从(2)导入密钥服务提供程序

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

  • 填写PKCS10(CSR)的其他字段,并按ASN1编码

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

    var signature=keyVaultClient.SignAsync(keyBundle.KeyIdentifier.Identifier,“RS256”,散列).GetAwaiter().GetResult()

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


  • 下面是一种在Windows上执行此操作的方法

  • 使用,在Azure密钥库中的HSM中创建密钥对

  • 将创建的密钥对的公钥作为CSP blob获取

  • PKCS10(CSR)的subjectPublicKeyInfo组件包含有关正在认证的公钥的信息。主题PublicKeyInfo是由Windows加密API:Next Generation(CNG)的ASN1编码

    本节要求您熟悉如何使用Windows加密API:Next Generation(CNG)。CNG是一个本机API,您需要使用PInvoke(DllImport)从托管代码中调用它

    a。使用NCryptOpenStorageProvider(SO上的链接限制,搜索MSDN)

    打开CNG密钥存储提供程序-

    b。使用NCryptImportKey(SO上的链接限制,搜索MSDN)

    将cspBlob从(2)导入密钥服务提供程序

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

  • 填写PKCS10(CSR)的其他字段,并按ASN1编码

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

    var signature=keyVaultClient.SignAsync(keyBundle.KeyIdentifier.Identifier,“RS256”,散列).GetAwaiter().GetResult()

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


  • 您可能会发现使用Windows CertEnroll COM接口更容易:创建并初始化IX509CertificateRequestPkcs10对象(),填充其属性,然后获取其RawDataToDesigned属性,并将其发送到Azure密钥库进行签名。这可以从本机代码、.NET等调用

    另一种[但更复杂的]方法是使用构建COM接口的基础Windows API。此示例()介绍如何生成和签署这样的PKCS#10。在我看来,您应该能够通过将对cryptsignandncodecertificate的调用替换为以下内容来调整示例:

  • 调用CryptEncodeObjectEx将证书请求信息对象编码为二进制;及

  • 调用Key Vault对该二进制blob进行签名

  • 然后,您需要构造一个证书签名的内容信息,设置:

    a。从#1到编码二进制的ToBeSigned成员

    b。用于使用密钥库签名的算法的SignatureAlgorithm成员;及

    c。从密钥库返回的签名的签名成员

  • 然后再次调用CryptEncodeObjectEx以将结果PKCS#10编码为二进制


  • 上面的解决方案是有效的,但实际上将通过.NET interop(用Crypto下一代调用替换示例中的Crypto API v1.0调用)执行IMO中更复杂的方法。除非我有明确的理由,否则我不会从那里开始

    您可能会发现使用Windows CertEnroll COM接口更容易:创建并初始化IX509CertificateRequestPkcs10对象(),填充其属性,然后获取其RawDataToBeSigned属性,并将其发送到Azure密钥保险库进行签名。这可以从本机代码、.NET等调用

    另一种[但更复杂的]方法是使用构建COM接口的基础Windows API。此示例()介绍如何生成和签署这样的PKCS#10。在我看来,您应该能够通过将对cryptsignandncodecertificate的调用替换为以下内容来调整示例:

  • 调用CryptEncodeObjectEx到ASN.1对证书请求信息进行编码
    // Assuming you have a keyVaultClient object using the SDK
    var keyBundle = keyVaultClient.CreateKeyAsync(keyVaultUri, "myKey01", "RSA-HSM", 2048).GetAwaiter().GetResult();
    
    var rsaCryptoProvider = new RSACryptoServiceProvider();
    var rsaParameters = new RSAParameters()
    {
        Modulus = keyBundle.Key.N,
        Exponent = keyBundle.Key.E
    };
    rsaCryptoProvider.ImportParameters(rsaParameters);
    var cspBlob = rsaCryptoProvider.ExportCspBlob(false);
    
    [DllImport("ncrypt.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
    private static extern ErrorCode NCryptOpenStorageProvider(
        [Out] out SafeNCryptProviderHandle phProvider,
        string pszProviderName,
        uint dwFlags);
    
    SafeNCryptProviderHandle providerHandle = null;
    var result = NCryptOpenStorageProvider(
        out providerHandle,
        null,
        0);
    
    [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);
    
    SafeNCryptKeyHandle keyHandle;
    var result = NCryptImportKey(
        providerHandle,
        IntPtr.Zero,
        "CAPIPUBLICBLOB",
        IntPtr.Zero,
        out keyHandle,
        cspBlob,
        cspBlob.Length,
        0x00000040);