C# Создание сертификата клиента из Root Сертификата с использованием CertEnroll - PullRequest
0 голосов
/ 04 мая 2020

Я хотел бы написать функцию, которая генерирует клиентские сертификаты, подписанные моим root сертификатом, используя CertEnroll.dll, у меня есть Root PFX-файл в указанном c местоположении и при чтении этого объекта CSignerCertificate. Вот мой код для того же.

Я получаю ошибку для кода ниже 'CertEnroll :: CSignerCertificate :: Initialize: Невозможно найти объект или свойство. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND) '

 public static X509Certificate2 CertCreateNew(string subjectName)
    {
        // create DN for subject and issuer
        var dn = new CX500DistinguishedName();
        dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);


        // create a new private key for the certificate
        CX509PrivateKey privateKey = new CX509PrivateKey();
        privateKey.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
        privateKey.MachineContext = false;
        privateKey.Length = 2048;
        privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; // use is not limited
        privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
        privateKey.Create();


        var hashobj = new CObjectId();
        hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
            ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
            AlgorithmFlags.AlgorithmFlagsNone, "SHA256");

        // add extended key usage if you want - look at MSDN for a list of possible OIDs
        var oid = new CObjectId();
        oid.InitializeFromValue("1.3.6.1.5.5.7.3.1"); // SSL server
        var oidlist = new CObjectIds();
        oidlist.Add(oid);
        var eku = new CX509ExtensionEnhancedKeyUsage();
        eku.InitializeEncode(oidlist);

        // Create the self signing request
        var cert = new CX509CertificateRequestCertificate();
        X509Certificate2 signercertificate = CertOpen("My Personal CA");
        X509Certificate2 signer = new X509Certificate2(System.IO.File.ReadAllBytes(@"d:\\PKICertificates\\Root Certificates\\MyPersonalCA.pfx"), "password");
        if (signer == null)
        {
            throw new CryptographicException("Signer not found");
        }            

        ISignerCertificate signerCertificate = new CSignerCertificate();

        signerCertificate.Initialize(false, X509PrivateKeyVerify.VerifySilent, EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(signer.RawData)); 

        cert.Issuer.Encode(signer.Subject, X500NameFlags.XCN_CERT_NAME_STR_NONE);

        cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, privateKey, "");           
        cert.SignerCertificate = (CSignerCertificate)signerCertificate;
        cert.Subject = dn;            
        cert.NotBefore = DateTime.Now;
        // this cert expires immediately. Change to whatever makes sense for you
        cert.NotAfter = DateTime.Now.AddYears(10);
        cert.X509Extensions.Add((CX509Extension)eku); // add the EKU
        cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
        cert.Encode(); // encode the certificate

        // Do the final enrollment process
        var enroll = new CX509Enrollment();
        enroll.InitializeFromRequest(cert); // load the certificate
        enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name

        string csr = enroll.CreateRequest(); // Output the request in base64
                                             // and install it back as the response
        enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
            csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
                                                            // output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
        var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
            PFXExportOptions.PFXExportChainWithRoot);

        // instantiate the target class with the PKCS#12 data (and the empty password)
        return new System.Security.Cryptography.X509Certificates.X509Certificate2(
            System.Convert.FromBase64String(base64encoded), "",
            // mark the private key as exportable (this is usually what you want to do)
            System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable
        );
    }

Кто-нибудь знает, как я могу создать клиент CX509CertificateRequest, подписанный моим root?

Любая помощь или совет будет принята с благодарностью.

1 Ответ

0 голосов
/ 05 мая 2020

Я нашел свой ответ методом проб и ошибок и, наконец, добился успеха. Размещение здесь кода может быть полезным для тех, кто получает ту же ошибку.

Примечание. Нет необходимости присваивать свойство Issuer, которое будет установлено автоматически, если свойство IssuerCertificate назначено до Encode

public static X509Certificate2 CertCreateNew(string subjectName)
    {
        X509Certificate2 signer = new X509Certificate2(System.IO.File.ReadAllBytes(@"d:\\PKICertificates\\Root Certificates\\MyPersonalCA.pfx"), "password");

        // create DN for subject and issuer
        var dn = new CX500DistinguishedName();
        dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);


        // create a new private key for the certificate
        CX509PrivateKey privateKey = new CX509PrivateKey();
        privateKey.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
        privateKey.MachineContext = false;
        privateKey.Length = 2048;
        privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; // use is not limited
        privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
        privateKey.Create();


        var hashobj = new CObjectId();
        hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
            ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
            AlgorithmFlags.AlgorithmFlagsNone, "SHA256");

        // add extended key usage if you want - look at MSDN for a list of possible OIDs
        var oid = new CObjectId();
        oid.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // SSL server
        var oidlist = new CObjectIds();
        oidlist.Add(oid);
        var eku = new CX509ExtensionEnhancedKeyUsage();
        eku.InitializeEncode(oidlist);

        // Create the self signing request
        var cert = new CX509CertificateRequestCertificate();
        if (signer == null)
            throw new CryptographicException("Signer not found");


        ISignerCertificate signerCertificate = new CSignerCertificate();
        signerCertificate.Initialize(false, X509PrivateKeyVerify.VerifySilent, EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(signer.RawData));


        cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, privateKey, "");
        cert.SignerCertificate = (CSignerCertificate)signerCertificate;
        cert.Subject = dn;
        cert.NotBefore = DateTime.Now.Date;
        cert.NotAfter = cert.NotBefore + new TimeSpan(3650, 0, 0, 0);
        cert.X509Extensions.Add((CX509Extension)eku); // add the EKU
        cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
        cert.Encode(); // encode the certificate

        // Do the final enrollment process
        var enroll = new CX509Enrollment();
        enroll.InitializeFromRequest(cert); // load the certificate
        enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name

        string csr = enroll.CreateRequest();
        enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
            csr, EncodingType.XCN_CRYPT_STRING_BASE64, "");
        var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
            PFXExportOptions.PFXExportChainWithRoot);

        // instantiate the target class with the PKCS#12 data (and the empty password)
        return new System.Security.Cryptography.X509Certificates.X509Certificate2(
            System.Convert.FromBase64String(base64encoded), "",
            // mark the private key as exportable (this is usually what you want to do)
            System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable
        );
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...