leo
leo

Reputation: 51

create certificateRequest from base64 string in .net Framework 4.7.2

In the past I used for our certTool the com CERTENROLLLib to create the csr. Since Version 4.7.2 you can use the .net Framework.

It is possible to create the csr by passing all the necessary Attributes in the CreateSigningRequest Method and convert it into a pem base64 string.

Unfortunately I couldn't find the other way around, copy a csr in pem Format in a field and read all the csr Attributes from it (cn, san, organization, etc.)

I don't want to use the com lib CERTENROLLLib, openssl or other 3rd parties.

Here is what I have done (to get the csr pem string) found good examples in here and at MS Framework class description, thanks for your help

protected void createButton_Click(object sender, EventArgs e)
    {
        string csr_cn = txtb_csr_cn.Text;
        string csr_c = txtb_csr_c.Text;
        string csr_l = txtb_csr_l.Text;
        string csr_o = txtb_csr_o.Text;
        string csr_ou = txtb_csr_ou.Text;
        string csr_s = txtb_csr_s.Text;
        csr_san = sanMemo.Text.Replace(" ", "");
        if (csr_san.IndexOf(csr_cn) == -1)
        {
            if (csr_san == "")
            {
                csr_san = csr_cn;
            }
            else
            {
                csr_san = csr_cn + "," + csr_san;
            }
        }
        csr_key_size = Convert.ToInt32(combobox_csr_key.Text);
        csr_info = "CN=" + csr_cn + "," + "OU=" + csr_ou + "," + "O=" + csr_o + "," + "L=" + csr_l + "," + "S=" + csr_s + "," + "C=" + csr_c;
        notesMemo.Text = CreateCSR(); //CreateRequest();

    }

public static string CreateCSR()
    {
        string[] arrSeperator = new string[] { "," };

        RSA keySize = RSA.Create(csr_key_size);

        CertificateRequest parentReq = new CertificateRequest(csr_info,
            //"CN=Experimental Issuing Authority",
            keySize,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);

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

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


        var sanBuilder = new SubjectAlternativeNameBuilder();
        Array arrsan = csr_san.Split(arrSeperator, StringSplitOptions.RemoveEmptyEntries);
        foreach (string sanvalue in arrsan)
        {
            sanBuilder.AddDnsName(sanvalue);
        }

        parentReq.CertificateExtensions.Add(sanBuilder.Build());

        string csrdecrypt = PemEncodeSigningRequest(parentReq);
        return csrdecrypt;

}

public static string PemEncodeSigningRequest(CertificateRequest request)
    {
        byte[] pkcs10 = request.CreateSigningRequest();
        StringBuilder builder = new StringBuilder();

        builder.AppendLine("-----BEGIN CERTIFICATE REQUEST-----");

        string base64 = Convert.ToBase64String(pkcs10);

        int offset = 0;
        const int LineLength = 64;

        while (offset < base64.Length)
        {
            int lineEnd = Math.Min(offset + LineLength, base64.Length);
            builder.AppendLine(base64.Substring(offset, lineEnd - offset));
            offset = lineEnd;
        }

        builder.AppendLine("-----END CERTIFICATE REQUEST-----");
        string tester2 = builder.ToString();
        return builder.ToString();
    }

Upvotes: 4

Views: 2014

Answers (1)

bartonjs
bartonjs

Reputation: 33178

There is no pure-managed way to read a Certification Signing Request without third party libraries.

You could try using a P/Invoke to CryptDecodeObjectEx, possibly using the structure identifier of X509_CERT (per https://learn.microsoft.com/en-us/windows/desktop/SecCrypto/constants-for-cryptencodeobject-and-cryptdecodeobject).

But the CertificateRequest class is a PKCS#10 writer without a reader in .NET Framework.

Update (2023-01-30): LoadSigningRequestPem and friends were added in .NET 7.

Upvotes: 1

Related Questions