Generating CSR using Java

  sonic0002        2016-05-25 04:49:17       26,522        0    

A CSR(Certificate Signing Request) is a kind of request generated by an application and is to be sent to a Certificate Authority to create a signed certificate which can be distributed. It usually contains certificate information such as subject name, public key info and signature info.

In Java, keytool can be used to generate a certificate request with option -certreq.  But sometimes if an application wants to create a CSR programmatically, keytool will not do a favor, instead you should use APIs provided by Java to generate CSRs.

Basically the steps to generate a CSR are :

  1. Get the keypair which the CSR is requested for. It can be generated with KeyPairGenerator or can get loaded from keystore(Preferred)
  2. Create the subject for the certificate request and also create a signature for the certificate request
  3. Sign the certificate request with the private key from the keypair in #1
  4. Get the encoded certificate request data and store it and sent it to the CA to create the certificate.

For a demo purpose, we will get the keypair using KeyPairGenerator, but in real application, it's better to have the keypair stored in a keystore.

Below is an example to create the certificate request with RSA.

public class CSRGenerator {
	public static void main(String[] args) {
		CSRGenerator csrGeneration = new CSRGenerator();
		
		// Generate key pair
		KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
		System.out.println("KeyPair generated");
		
		byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
		
		System.out.println(new String(csrData));
	}
	
	/**
	 * Generate the desired CSR for signing
	 * 
	 * @param sigAlg
	 * @param keyPair
	 * @return
	 */
	byte[] generateCSR(String sigAlg, KeyPair keyPair) {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		PrintStream printStream = new PrintStream(outStream);
		
		try {
			X500Name x500Name = new X500Name("CN=EXAMPLE.COM");
			
			Signature sig = Signature.getInstance(sigAlg);
			
			sig.initSign(keyPair.getPrivate());

			PKCS10 pkcs10 = new PKCS10(keyPair.getPublic());
//			pkcs10.encodeAndSign(new X500Signer(sig, x500Name));   // For Java 6
			pkcs10.encodeAndSign(x500Name, sig);                   // For Java 7 and Java 8
			pkcs10.print(printStream);
	        
			byte[] csrBytes = outStream.toByteArray();
			
			return csrBytes;
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if(null != outStream) {
				try {
					outStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(null != printStream) {
				printStream.close();
			}
		}
		
		return new byte[0];
	}

	/**
	 * Generate the desired keypair
	 * 
	 * @param alg
	 * @param keySize
	 * @return
	 */
	KeyPair generateKeyPair(String alg, int keySize) {
		try{
			KeyPairGenerator keyPairGenerator = null;
			keyPairGenerator = KeyPairGenerator.getInstance(alg);
			
			keyPairGenerator.initialize(keySize);
			
			return keyPairGenerator.generateKeyPair();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return null;
	}
}

Note that there is some difference between Java 6 and Java 7 while calling PKCS10.encodeAndSign(). Java 7 doesn't have X500Signer anymore.

If you are using IBM Java instead of Oracle Java, it's different on how the certificate request can be generated. See below.

public class CSRGenerator {
	public static void main(String[] args) {
		CSRGenerator csrGeneration = new CSRGenerator();
		
		// Generate key pair
		KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
		System.out.println("KeyPair generated");
		
		byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
		
		System.out.println(new String(csrData));
	}
	
	/**
	 * Generate the desired CSR for signing
	 * 
	 * @param sigAlg
	 * @param keyPair
	 * @return
	 */
	byte[] generateCSR(String sigAlg, KeyPair keyPair) {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		PrintStream printStream = new PrintStream(outStream);
		
		try {
			X500Name x500Name = new X500Name("CN=EXAMPLE.COM");
			
	        CertificateExtensions ext = new CertificateExtensions();
	        PKCSAttributes attrs = new PKCSAttributes().addAttribute(new PKCSAttribute(PKCSOID.EXTENSION_REQUEST_OID, ext));
	        
	        CertificationRequestInfo certInfo = new CertificationRequestInfo(x500Name, keyPair.getPublic(), attrs);
	        CertificationRequest request = new CertificationRequest(certInfo);
	        request = request.sign(sigAlg, keyPair.getPrivate());
	        request.print(printStream);
	        
			byte[] csrBytes = outStream.toByteArray();
			
			return csrBytes;
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if(null != outStream) {
				try {
					outStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(null != printStream) {
				printStream.close();
			}
		}
		
		return new byte[0];
	}

	/**
	 * Generate the desired keypair
	 * 
	 * @param alg
	 * @param keySize
	 * @return
	 */
	KeyPair generateKeyPair(String alg, int keySize) {
		try{
			KeyPairGenerator keyPairGenerator = null;
			keyPairGenerator = KeyPairGenerator.getInstance(alg);
			
			keyPairGenerator.initialize(keySize);
			
			return keyPairGenerator.generateKeyPair();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return null;
	}
}

The certificate request generated in BASE64 encoding should look like below :

-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBZjCB0AIBADAWMRQwEgYDVQQDEwtFWEFNUExFLkNPTTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAgXneACRkW0QvpuuNhzo8OOmxe7xPzd3UZJ9MOEA5VhP5QvWGMGFNITGmubL1I2AWmsHz
yMxwO0SHPFNclo4oSm+Cu2d67d28vingYBGEBrVXIwg3j1CVADcGjb39TcYL77fofBem8XNDCw0N
WKLaTqpnVaAtqvnE0+r7O3BZZg8CAwEAAaARMA8GCSqGSIb3DQEJDjECMAAwDQYJKoZIhvcNAQEL
BQADgYEAb5jNx6ASGpgTXTNz5UrD6BrTyLZYyTmlQwI0EjhG0lVY5sYiQGz7t6JQP62aqRFfM7vo
dYMnKxeuApp5LSY3EdyY1F5I20PPTbpSSP529pV5gIQZk4FZMoth7dvWgBH3pqB0BkHQ1g+wdWof
m2imkOR1D+7Yn6xvQ/Be9mXienU=
-----END NEW CERTIFICATE REQUEST-----

Hope this help you if you are struggling with the certificate request generation in Java.

CSR  CERTIFICATE REQUEST  SECURITY  JAVA 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Security question in action