Generating CSR and Exporting Private Key With C#

3.4k views Asked by At

I am trying to write a code to generate CSR and export its private key with C# programmatically. I found this blog post (it is almost the only one about)

With the codes below CSR and private key can be generated and exported as Base64 Strings. Also SSL sertificate can be issued by this CSR. However exported private key has some errors. I got "Key Modulus Hash: Unable to decode. The key may be corrupt or in an incorrect format." from online tool.

I hope you can show my mistake and you can save my day.

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;
        static void Main(string[] args) {
            //  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 {


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

                //  Add this CSP object to the CSP collection object
                objCSPs.Add(
                    objCSP
                );
                String date = DateTime.Now.ToString("MMddHHmmss") + DateTime.Now.Millisecond.ToString();
                //  Provide key container name, key length and key spec to the private key object
                objPrivateKey.ContainerName = "Company-" + date; 
                objPrivateKey.Length = 2048;
                objPrivateKey.ProviderName = "Microsoft RSA SChannel Cryptographic Provider";
                objPrivateKey.ProviderType = X509ProviderType.XCN_PROV_RSA_SCHANNEL;
                objPrivateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
                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;
                objPrivateKey.ExportPolicy = 
                    X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_ARCHIVING_FLAG | 
                    X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG | 
                    X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG |
                    X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;

                //  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(
                    CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
                    CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
                    CERTENROLLLib.X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
                    CERTENROLLLib.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.1"); // 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=www.mydomain.com, O=Company, OU=IT, C=TR, S=Istanbul;L=Istanbul, [email protected]",
                    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_BASE64REQUESTHEADER
                );
                string key = objPrivateKey.Export("PUBLICBLOB", EncodingType.XCN_CRYPT_STRING_BASE64);
                File.WriteAllText("C:\\csr.txt", key);

                File.AppendAllText("C:\\csr.txt", strRequest);

            }
            catch(Exception ex) {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
        }
    }
0

There are 0 answers