Search code examples
c#bouncycastlesigncacsr

Signing CSR using Bouncy Castle in C#


I have created root and intermediate certificates using Bouncy Castle in C#. Now I want to accept and sign CSR using the certificate. I am getting Java solutions everywhere. I want to convert java code to C# but not getting exact documentation for C#. Can somebody please help with this.


Solution

  • Here is my solution:

    public string SignCSR(string str_csr, int validityInYears)
            {
                try
                {
                    char[] characters = str_csr.Replace("-----BEGIN CERTIFICATE REQUEST-----", "").Replace("-----END CERTIFICATE REQUEST-----", "").ToCharArray();
    
                    byte[] csrEncode = Convert.FromBase64CharArray(characters, 0, characters.Length);
                    Pkcs10CertificationRequest pk10Holder = new Pkcs10CertificationRequest(csrEncode);
    
                    bool verify = pk10Holder.Verify();
                    if (verify == false)
                    {
                        return constants.INVALIDCERTIFICATEREQUEST;
                    }
                    // Generating Random Numbers
                    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
                    SecureRandom random = new SecureRandom(randomGenerator);
    
                    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
    
                    // Serial Number
                    BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
                    certificateGenerator.SetSerialNumber(serialNumber);
    
                    //Import intermediate certificate and get issuer details
                    string pathToRootCert = Configuration["intermediatecertificatelocation"];
                    string intermediateIssuer = rootBusinessLogic.ImportIssuerFromPem(pathToRootCert);
    
                    // Issuer and Subject Name
                    //X509Name issuerDN = new X509Name(issuerName);
                    X509Name issuerDN = new X509Name(intermediateIssuer);  //issuer is intermediate certificate here whi will sign
                    certificateGenerator.SetIssuerDN(issuerDN);
                    certificateGenerator.SetSubjectDN(pk10Holder.GetCertificationRequestInfo().Subject);
    
                    // Valid For
                    DateTime notBefore = DateTime.UtcNow.Date;
                    DateTime notAfter = notBefore.AddYears(validityInYears);
    
                    certificateGenerator.SetNotBefore(notBefore);
                    certificateGenerator.SetNotAfter(notAfter);
    
                    certificateGenerator.SetPublicKey(pk10Holder.GetPublicKey());
    
    
                    //Import root certificate and get issuer details
                    //get root private key from file
                    string rootKeyPathFromConfig = Configuration["intermediate_privatekeylocation"];
                    AsymmetricKeyParameter issuerPrivKey = rootBusinessLogic.ImportPrivateKeyFromPemFile(rootKeyPathFromConfig);
                    if (issuerPrivKey == null)
                    {
                        return constants.INTERMEDIATEKEYERROR;
                    }
    
                    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", issuerPrivKey, random);
    
                    // Selfsign certificate
                    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);
    
                    X509Certificate2 x509 = new X509Certificate2(certificate.GetEncoded());
                    StringBuilder builder = new StringBuilder();
                    builder.AppendLine("-----BEGIN CERTIFICATE-----");
                    builder.AppendLine(Convert.ToBase64String(x509.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
                    builder.AppendLine("-----END CERTIFICATE-----");
                    var str_certificate = builder.ToString();
                    return str_certificate ;
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
        }
    

    pathToRootCert is the path to the intermediate certificate stored in the device, ImportIssuerFromPem is the method to retrieve issuer name of the intermediate certificate, rootKeyPathFromConfig is the path to the private key of intermediate certificate for signing purpose, ImportPrivateKeyFromPemFile is the method to get the private key in AsymmetricKeyParameter format. This method returns certificate in PEM format.