如何制作PKCS10请求,并使用模板注册?

时间:2014-07-04 02:09:39

标签: x509certificate x509certificate2 x509 certenroll

我一直在寻找各地(MSDN,Stackoverflow,博客等)来提出以下模式:

  1. 客户端向服务器请求与SMIME标准兼容的证书。 (缺少AD证书服务模板部分)

  2. 服务器接收PKCS10请求并对其进行修改,或使用API​​确保使用正确的模板注册

  3. 服务器生成响应并将其发送到客户端

  4. 客户接受回复并完成注册。

  5. 注意

    即使我在Windows客户端使用.NET,我希望这个过程足够通用,以便有OSX的人可以使用内置钥匙串或OpenSSL申请证书并申请证书,不得不提到EKU中的证书模板。

    我的目标是修改服务器上的请求并将结果发送回客户端。

    这是我迄今为止所尝试过的。

     class Program
       {
        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;
        private static string requestText = "";
    
        static string SMIMEEncrypt = "1.3.6.1.4.1.311.21.8.4946465.16405226.12930948.10533807.2139545.33.10793632.14573168";
        static string SMIMESign    = "1.3.6.1.4.1.311.21.8.4946465.16405226.12930948.10533807.2139545.33.5005369.11644649";
    
    
        enum FullResponsePropertyPropID
        {
            FR_PROP_NONE =0,
            FR_PROP_FULLRESPONSE =1,
            FR_PROP_STATUSINFOCOUNT=2,
            FR_PROP_BODYPARTSTRING=3,
            FR_PROP_STATUS=4,
            FR_PROP_STATUSSTRING=5,
            FR_PROP_OTHERINFOCHOICE=6,
            FR_PROP_FAILINFO=7,
            FR_PROP_PENDINFOTOKEN=8,
            FR_PROP_PENDINFOTIME=9,
            FR_PROP_ISSUEDCERTIFICATEHASH=10,
            FR_PROP_ISSUEDCERTIFICATE=11,
            FR_PROP_ISSUEDCERTIFICATECHAIN=12,
            FR_PROP_ISSUEDCERTIFICATECRLCHAIN=13,
            FR_PROP_ENCRYPTEDKEYHAS=14,
            FR_PROP_FULLRESPONSENOPKCS7=15,
            FR_PROP_CAEXCHANGECERTIFICATEHASH=16,
            FR_PROP_CAEXCHANGECERTIFICATE=17,
            FR_PROP_CAEXCHANGECERTIFICATECHAIN=18,
            FR_PROP_CAEXCHANGECERTIFICATECRLCHAIN=19,
            FR_PROP_ATTESTATIONCHALLENGE=20,
            FR_PROP_ATTESTATIONPROVIDERNAME=21
        }
        public static void Main()
        {
            int PROPTYPE_BINARY = 3;
            //// Client
            //var objEnroll = new CX509Enrollment();
            //string RequestStr = objEnroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64);
    
            ////TEST SERVER
            //CCertRequest  CertRequest = new CCertRequest ();
            // int Disposition = CertRequest.Submit(CR_IN_BASE64, RequestStr, string.Empty, @"caName");
    
    
            string subjectName = "E= makerofthings7@me.com, CN = makerofthings7@me.com, OU = Technology, L= NYC, S= NY, C=US";
            string friendlyName = "makerofthings7 - Encrypt...";
            string templateName = SMIMEEncrypt;
    
            //  --------------
            //  --------------
            // Client
            //  --------------
            //  --------------
    
            // 1. Call any initialization method implemented by the IX509Enrollment object.
            CX509Enrollment req1 = new CX509Enrollment();
            req1.Initialize(X509CertificateEnrollmentContext.ContextUser);
    
            // 2. Call the CreateRequest method.
            string req1a = req1.CreateRequest();
            // 3. Store the request for a period of time such as days or weeks.
    
            // --------------
            // --------------
            // Server
            // --------------
            // --------------
    
            // 4. Call the Initialize method to create a request object when you are ready to enroll.
            var reqServer = new CX509CertificateRequestPkcs10();
            reqServer.InitializeFromCertificate(
                X509CertificateEnrollmentContext.ContextUser,
                req1a  //    Beginning with Windows 7 and Windows Server 2008 R2, you can specify 
                       //    a certificate thumb print or serial number rather than an encoded certificate
                );
    
            // Add template (Sign or Encrypt or Both)
            CX509ExtensionTemplateName tmplateData2 = new CERTENROLLLib.CX509ExtensionTemplateName();
            tmplateData2.InitializeEncode(templateName);
            var tmplatex5092 = (IX509Extension)tmplateData2;
            reqServer.X509Extensions.Add(new CX509Extension(tmplatex5092));
    
            // -----------------------------------------------------------------------------------
            // The following properties can be set before calling the Encode method:
            //    AlternateSignatureAlgorithm
            //    ClientId
            //    HashAlgorithm
            //    ParentWindow
            //    RenewalCertificate
            //    Silent
            reqServer.Silent = true;
            //    SuppressDefaults
            //    ContextMessage
            //
            // The following properties must be set, if at all, before calling the Encode method:
            //    CspInformations
            //    KeyContainerNamePrefix
            //    SmimeCapabilities
            reqServer.SmimeCapabilities = true;
            //    Subject
            CX500DistinguishedName objName2 = new CX500DistinguishedName();
            objName2.Encode(subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);
            reqServer.Subject = objName2;
            // -----------------------------------------------------------------------------------
            reqServer.Encode();
            //reqServer.get_RawDataToBeSigned();
    
            // InitializeFromRequest() does the following:
            //    Verifies that the request is a PKCS #10, PKCS #7, or CMC request object.
            //    Retrieves the template, if any, associated with the request.
            //    Validates the template.
            //    Sets the request object on the Request property.
            //    Retrieves the signature count, issuance policies, and application policies from the template.
            //    Retrieves the renewal certificate if one exists.
            CX509Enrollment enroll2 = new CX509Enrollment();
            enroll2.InitializeFromRequest(reqServer);
    
            // Enroll()
            // -  The method may create a key pair if necessary. Depending on how you initialize the enrollment
            //    object and on what properties you set, there may be no need to create a key pair. For example, 
            //    if you are renewing a certificate by using an existing key, or if the IX509PrivateKey object 
            //    associated with the certificate request represents an existing key, this method does not create a new key pair.
            enroll2.Enroll();
    
            // ALTERNATE IMPLEMENTATION
            //CERTCLILib.ICertRequest3 serverReq2 = new CCertRequest();
            //var retVAl2 = serverReq2.Submit(CR_IN_ENCODEANY, reqr3.Request.get_RawData(), string.Empty, "a.issue01.bitclear.us\\Secure Issuer 01a-001");
            //var serverSignedResponse = serverReq2.GetCertificate(CR_OUT_BASE64HEADER);
            //var certwChain2 = serverReq2.GetCertificate(CR_OUT_BASE64HEADER | CR_OUT_CHAIN);
    
    
    
            //  --------------
            //  --------------
            // Client
            //  --------------
            //  --------------
    
            // 5.Populate the request object from your stored request.
            CCertRequest CertRequest = new CCertRequest();
            var disposition3 = CertRequest.RetrievePending(1, ""); // pretend we checked the server for result status, and it was OK
    
            // If Issued...
            if (true)
            {
                // 6. Call the InstallResponse method.
                X509CertificateEnrollmentContext context = X509CertificateEnrollmentContext.ContextUser;
    
                CX509Enrollment enroll3 = new CX509Enrollment();
                string serverSignedResponse = CertRequest.GetFullResponseProperty(
                   (int) FullResponsePropertyPropID.FR_PROP_FULLRESPONSE, 0, PROPTYPE_BINARY, CR_OUT_BASE64).ToString();
                enroll3.Initialize(context);
    
                // InstallResponse()
                // -  Retrieves the dummy certificate from the external store.
                // -  Retrieves the certificate contained in the response and installs it on the computer.
                // -  Copies properties from the dummy certificate in the external store onto the newly installed certificate in the personal store.
                enroll3.InstallResponse(
                    InstallResponseRestrictionFlags.AllowNone
                    | InstallResponseRestrictionFlags.AllowUntrustedRoot         //Perform the same action as the AllowUntrustedCertificate flag 
                    // but also installs the certificate even if the certificate chain 
                    //  cannot be built because the root is not trusted.
                    , serverSignedResponse, EncodingType.XCN_CRYPT_STRING_BASE64
                    , string.Empty // If there is a password, clear it from memory when you have finished using it by calling the SecureZeroMemory function
                    );
    
                // CreatePFX()
                // - Opens the certificate store in memory for the default provider.
                // - Adds the installed certificate to the store or builds the certificate chain adds a link to it.
                // - Exports the certificate and the private key to a PFX message depending on the export options specified.
                // - Encodes the exported message by using DER.
                string pfx = enroll3.CreatePFX(
                    "q", // When you have finished using the password, clear it from memory by calling the SecureZeroMemory function.
                    PFXExportOptions.PFXExportChainNoRoot);
            }
    

0 个答案:

没有答案