Using C# to Automate Java Keytool Certificate Signing Requests

The Java keytool is a utility to manage public/private key pairs for certificates used in authentication services. Keytool is straightforward to use and runs from the command line. Creating a new certificate at high level involves first creating a keystore to store the private / public key pair, then creating the certificate signing request, and then finally importing the completed certificate.

Recently I found myself creating multiple certificates on a weekly basis so I decided to try automating the process. The servers I was supporting were Windows Server 2012 R2 and Windows Server 2016 so my solution was to create an asp.net Win Form.  Please note I am only covering keytool examples for my specific situation. Refer to the keytool documentation for additional information.

 

Run command line processes with c#

To create the keystore I used the keytool.exe –genkeypair command. This will create a public and private key pair within the keystore file.  All my certificates use the server FQDN for the common name so I just use the server hostname for the keystore name.  The additional parameters required are:

  •  -alias: alias name
  • -keystore:  keystore name
  • -keypass:  key password
  • -keyalg: key algorithm
  • -sigalg: signature algorithm
  • -keysize: key size
  • -validity: days valid
  • -dname: Distinguished name

The –dname  parameter references the specific certificate details like Common Name, Organizational Unit, City, State, and Country. One additional parameter I need to use is –noprompt which as it implies suppresses any command line prompting. Here is an example of the keytool command I will run.

keytool.exe -genkeypair -v -alias mykeystore –keystore myservername -dname "CN=myservername,O=mybizname, OU=internet, L=Mytown, S=MyState,C=US" -storepass xxx -keypass xxx -keyalg RSA -sigalg SHA256withRSA -keysize 2048 -validity 360 –noprompt

 

My program will start a new process with cmd.exe and then pass the command name, command arguments, and command path and then return the output of the process for validation. Please note the command path in this context is the path to keytool.exe in the JDK folder. This path may already be in local system path but you can also set it dynamically. I recently I did blog post on using C# to check and set a path in the Windows path environment variable.

public string runProcess(string cmdName, string cmdArgs, string cmdPath)
{

 string myProcOutput = "";
 try
 {
  Process myproc = new Process();
  myproc.StartInfo.UserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
  myproc.StartInfo = new ProcessStartInfo("cmd.exe");
  myproc.StartInfo.LoadUserProfile = true;
  myproc.StartInfo.FileName = cmdName;
  myproc.StartInfo.Arguments = cmdArgs;
  myproc.StartInfo.WorkingDirectory = @cmdPath;
  myproc.StartInfo.RedirectStandardOutput = true;
  myproc.StartInfo.UseShellExecute = false;
  myproc.StartInfo.Verb = "runas";
  myproc.Start();
  myProcOutput = myproc.StandardOutput.ReadToEnd();
  myproc.WaitForExit();
}
catch (Exception ex)
{
  MessageBox.Show(ex.ToString());
}

 return myProcOutput;
}

 

With automation in mind I also speed up the process by leveraging the application config file to save the certificate details such as Organization, Organizational Unit, City, State, etc.  This way I only set these values once when the program runs. For example:

<appSettings>
   <add key="certOrg" value="My Company" />
   <add key="certOU" value="Internet" />
   <add key="certCity" value="mycity" />
   <add key="certState" value="mystate" />
</appSettings>

 

You can access these values in the program like below. Just be sure to reference the System.Configuration namespace.

string certOrg= ConfigurationManager.AppSettings["certOrg"];
string certOu= ConfigurationManager.AppSettings["certOu"];
string certCity= ConfigurationManager.AppSettings["certCity"];
string certState= ConfigurationManager.AppSettings["certState"];

 

Once the keystore has been created the next step is run the –certreq command to create the certificate signing request (CSR). In my example I also use the –file parameter which indicates the name of the file to store the CSR. Reusing the code snippet above I pass my command syntax and then validate if the CSR file was created using File.Exists. If the file in fact exists then I use Process.Start() to open the file in Notepad to review.

public void createCSR()
{
    string cmdName = "keytool.exe";
    string csrArgs = "-v-certreq -alias mykeystore –keystore -myservername -storepass xxx -file myservername.csr.txt”;
        
    try
    {
        runProcess(cmdName, csrArgs, keystorePath);
        if (File.Exists(Path.Combine(keystorePath, csrName)))
        {
            Process.Start(Path.Combine(keystorePath, csrName)); 
            //opens the new csr file in Notepad
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

 

The next step is to take the new CSR to my certificate authority and complete the certificate creation. Once I obtain the new certificate I will then import it into the keystore file created above along with any intermediate certificates. I will cover those steps in a future post.

In Summary

Using the Java keytool to create a keystore and certificate signing request is a straight forward process but if you start doing them frequently can get repetitive and time consuming. Leveraging  asp.net Win Forms is a great way to automate the command line process on a Windows server and can save yourself some time.  Thanks for reading!

Peter Viola

Creative, customer focused, results oriented, Senior Web Systems Engineer who enjoys providing the highest level of customer service supporting complex Windows hosting solutions. MCITP, MCSA, MCTS

More Posts - Website