2014-06-26 63 views
1

以下code用於從ADCS實例請求證書。請求證書時,如何獲得pfx blob?

我如何提取請求,並確定外部存儲的pfx blob(和密碼保護它)?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

// Add the CertEnroll namespace 
using CERTENROLLLib; 
using CERTCLIENTLib; 

namespace CATest 
{ 
    public partial class Form1 : Form 
    { 
     private const int CC_DEFAULTCONFIG = 0; 
     private const int CC_UIPICKCONFIG = 0x1; 
     private const int CR_IN_BASE64 = 0x1; 
     private const int CR_IN_FORMATANY = 0; 
     private const int CR_IN_PKCS10 = 0x100; 
     private const int CR_DISP_ISSUED = 0x3; 
     private const int CR_DISP_UNDER_SUBMISSION = 0x5; 
     private const int CR_OUT_BASE64 = 0x1; 
     private const int CR_OUT_CHAIN = 0x100; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     // Create request 
     private void createRequestButton_Click(object sender, EventArgs e) 
     { 
      // Create all the objects that will be required 
      CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class(); 
      CX509PrivateKey objPrivateKey = new CX509PrivateKeyClass(); 
      CCspInformation objCSP = new CCspInformationClass(); 
      CCspInformations objCSPs = new CCspInformationsClass(); 
      CX500DistinguishedName objDN = new CX500DistinguishedNameClass(); 
      CX509Enrollment objEnroll = new CX509EnrollmentClass(); 
      CObjectIds objObjectIds = new CObjectIdsClass(); 
      CObjectId objObjectId = new CObjectIdClass(); 
      CX509ExtensionKeyUsage objExtensionKeyUsage = new CX509ExtensionKeyUsageClass(); 
      CX509ExtensionEnhancedKeyUsage objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsageClass(); 
      string strRequest; 

      try 
      { 
       requestText.Text = ""; 

       // Initialize the csp object using the desired Cryptograhic Service Provider (CSP) 
       objCSP.InitializeFromName(
        "Microsoft Enhanced Cryptographic Provider v1.0" 
       ); 

       // Add this CSP object to the CSP collection object 
       objCSPs.Add(
        objCSP 
       ); 

       // Provide key container name, key length and key spec to the private key object 
       //objPrivateKey.ContainerName = "AlejaCMa"; 
       objPrivateKey.Length = 1024; 
       objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; 
       objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES; 
       objPrivateKey.MachineContext = false; 

       // Provide the CSP collection object (in this case containing only 1 CSP object) 
       // to the private key object 
       objPrivateKey.CspInformations = objCSPs; 

       // Create the actual key pair 
       objPrivateKey.Create(); 

       // Initialize the PKCS#10 certificate request object based on the private key. 
       // Using the context, indicate that this is a user certificate request and don't 
       // provide a template name 
       objPkcs10.InitializeFromPrivateKey(
        X509CertificateEnrollmentContext.ContextUser, 
        objPrivateKey, 
        "" 
       ); 

       // Key Usage Extension 
       objExtensionKeyUsage.InitializeEncode(
        X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE | 
        X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE | 
        X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE | 
        X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE 
       ); 
       objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage); 

       // Enhanced Key Usage Extension 
       objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // OID for Client Authentication usage 
       objObjectIds.Add(objObjectId); 
       objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds); 
       objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage); 

       // Encode the name in using the Distinguished Name object 
       objDN.Encode(
        "CN=AlejaCMa", 
        X500NameFlags.XCN_CERT_NAME_STR_NONE 
       ); 

       // Assing the subject name by using the Distinguished Name object initialized above 
       objPkcs10.Subject = objDN; 

       // Create enrollment request 
       objEnroll.InitializeFromRequest(objPkcs10); 
       strRequest = objEnroll.CreateRequest(
        EncodingType.XCN_CRYPT_STRING_BASE64 
       ); 

       requestText.Text = strRequest; 

      } catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 

     // Submit request to CA and get response 
     private void sendRequestButton_Click(object sender, EventArgs e) 
     { 
      // Create all the objects that will be required 
      CCertConfig objCertConfig = new CCertConfigClass(); 
      CCertRequest objCertRequest = new CCertRequestClass(); 
      string strCAConfig; 
      string strRequest; 
      int iDisposition; 
      string strDisposition; 
      string strCert; 

      try 
      { 
       strRequest = requestText.Text; 

       // Get CA config from UI 
       //strCAConfig = objCertConfig.GetConfig(CC_DEFAULTCONFIG); 
       strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG);     

       // Submit the request 
       iDisposition = objCertRequest.Submit(
        CR_IN_BASE64 | CR_IN_FORMATANY, 
        strRequest, 
        null, 
        strCAConfig 
       ); 

       // Check the submission status 
       if (CR_DISP_ISSUED != iDisposition) // Not enrolled 
       { 
        strDisposition = objCertRequest.GetDispositionMessage(); 

        if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending 
        { 
         MessageBox.Show("The submission is pending: " + strDisposition); 
         return; 
        } 
        else // Failed 
        { 
         MessageBox.Show("The submission failed: " + strDisposition); 
         MessageBox.Show("Last status: " + objCertRequest.GetLastStatus().ToString()); 
         return; 
        } 
       } 

       // Get the certificate 
       strCert = objCertRequest.GetCertificate(
        CR_OUT_BASE64 | CR_OUT_CHAIN 
       ); 

       responseText.Text = strCert; 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 

     // Install response from CA 
     private void acceptPKCS7Button_Click(object sender, EventArgs e) 
     { 
      // Create all the objects that will be required 
      CX509Enrollment objEnroll = new CX509EnrollmentClass(); 
      string strCert; 

      try 
      { 
       strCert = responseText.Text; 

       // Install the certificate 
       objEnroll.Initialize(X509CertificateEnrollmentContext.ContextUser); 
       objEnroll.InstallResponse(
        InstallResponseRestrictionFlags.AllowUntrustedRoot, 
        strCert, 
        EncodingType.XCN_CRYPT_STRING_BASE64, 
        null 
       ); 

       MessageBox.Show("Certificate installed!"); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     }  
    } 
} 

與代碼的問題是,我不想加密材料存儲在Windows DPAPI,特別是我不想爲「安裝」的證書,因爲加密材料需要安全地發送並在多臺電腦之間共享。

的我遇到的麻煩的代碼的特定行包括此:

 // Install the certificate 
      objEnroll.Initialize(X509CertificateEnrollmentContext.ContextUser); 
      objEnroll.InstallResponse(
       InstallResponseRestrictionFlags.AllowUntrustedRoot, 
       strCert, 
       EncodingType.XCN_CRYPT_STRING_BASE64, 
       null 
      ); 

我也想保存並導入從定製存儲證書的請求......再沒有DPAPI

+1

你的代碼有什麼問題? – gunr2171

+0

@ gunr2171 - 澄清 – LamonteCristo

回答

1

你可以在acceptPKCS7Button_Click方法的objEnroll實例上調用CreatePFX方法:

objEnroll.CreatePFX("S3cret!", PFXExportOptions.PFXExportChainWithRoot, EncodingType.XCN_CRYPT_STRING_BASE64); 
+0

這樣做的問題是返回類型是'string',我需要一個二進制PFX,與我在導出時在證書MMC中完成的操作相似 – LamonteCristo

+0

將它保存到文件中 - Windows可以處理它。 –

+0

使用System.Convert.FromBase64String(「...」)並將其保存到一個文件中,以獲得一個* real *二進制文件 –