Home > Back-end >  Generate and Sign Certificate using .NET, verifiable with OpenSSL
Generate and Sign Certificate using .NET, verifiable with OpenSSL

Time:07-05

Taking the code from this answer, saving the parentCert and the cert to .crt files, and trying to verify the certificate with OpenSSL as follows:

openssl verify -CAfile parentCert.crt cert.crt

Fails with this error:

Error loading file parentCert.crt
98580000:error:05800088:x509 certificate routines:X509_load_cert_crl_file_ex:no certificate or crl found:crypto\x509\by_file.c:251:

So the question is, how to create a ca.crt and a cert.crt (signed with that ca.crt) in .NET that OpenSSL can verify?

Here the full code for the test I did:

    using (RSA parent = RSA.Create(4096))
    using (RSA rsa = RSA.Create(2048))
    {
        CertificateRequest parentReq = new CertificateRequest(
            "CN=Experimental Issuing Authority",
            parent,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);

        parentReq.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(true, false, 0, true));

        parentReq.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));

        using (X509Certificate2 parentCert = parentReq.CreateSelfSigned(
            DateTimeOffset.UtcNow.AddDays(-45),
            DateTimeOffset.UtcNow.AddDays(365)))
        {
            CertificateRequest req = new CertificateRequest(
                "CN=Valid-Looking Timestamp Authority",
                rsa,
                HashAlgorithmName.SHA256,
                RSASignaturePadding.Pkcs1);

            req.CertificateExtensions.Add(
                new X509BasicConstraintsExtension(false, false, 0, false));

            req.CertificateExtensions.Add(
                new X509KeyUsageExtension(
                    X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation,
                    false));

            req.CertificateExtensions.Add(
                new X509EnhancedKeyUsageExtension(
                    new OidCollection
                    {
                    new Oid("1.3.6.1.5.5.7.3.8")
                    },
                    true));

            req.CertificateExtensions.Add(
                new X509SubjectKeyIdentifierExtension(req.PublicKey, false));

            using (X509Certificate2 cert = req.Create(
                parentCert,
                DateTimeOffset.UtcNow.AddDays(-1),
                DateTimeOffset.UtcNow.AddDays(90),
                new byte[] { 1, 2, 3, 4 }))
            {
                // Do something with these certs, like export them to PFX,
                // or add them to an X509Store, or whatever.

                string path = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"));
                File.WriteAllBytes(Path.Combine(path, "parentCert.crt"), parentCert.Export(X509ContentType.Cert));
                File.WriteAllBytes(Path.Combine(path, "cert.crt"), cert.Export(X509ContentType.Cert));
            }
        }
    }

CodePudding user response:

The problem is you've created your files as DER, but that OpenSSL command only reads PEM.

You can either convert them with something like openssl x509 -in parentCert.cer -inform der -out parentCert.pem, or just change your export code to something like

File.WriteAllText(
    Path.Combine(path, "parentCert.crt"),
    new string(PemEncoding.Write("CERTIFICATE", parentCert.RawData)));
File.WriteAllText(
    Path.Combine(path, "cert.crt"),
    new string(PemEncoding.Write("CERTIFICATE", cert.RawData)));

Or, in .NET 7 it's a little cleaner:

File.WriteAllText(
    Path.Combine(path, "parentCert.crt"),
    PemEncoding.WriteString("CERTIFICATE", parentCert.RawData));
File.WriteAllText(
    Path.Combine(path, "cert.crt"),
    PemEncoding.WriteString("CERTIFICATE", cert.RawData));
  • Related