Generating CSR using Java

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

A Certificate Signing Request (CSR) is a vital component for obtaining signed certificates from a Certificate Authority, encapsulating subject details and public key information. For applications requiring dynamic CSR creation, programmatic generation in Java is necessary, moving beyond command-line tools like `keytool`. The core steps involve generating or loading a keypair, defining the certificate subject, signing the request with the private key, and then encoding the resulting data. Developers can utilize Java's security APIs, such as `KeyPairGenerator` and `Signature`, along with `PKCS10` for Oracle Java or `CertificationRequest` for IBM Java, while being mindful of API variations between Java versions. The final output is a BASE64 encoded request ready for submission to a CA.

Một CSR(Yêu cầu ký chứng chỉ) là một loại yêu cầu được tạo bởi một ứng dụng và được gửi đến Cơ quan cấp chứng chỉ để tạo một chứng chỉ đã ký có thể được phân phối. Nó thường chứa thông tin chứng chỉ như tên chủ thể, thông tin khóa công khai và thông tin chữ ký.

Trong Java, keytool có thể được sử dụng để tạo yêu cầu chứng chỉ với tùy chọn -certreq.  Nhưng đôi khi nếu một ứng dụng muốn tạo CSR bằng lập trình, keytool sẽ không giúp ích, thay vào đó bạn nên sử dụng các API được cung cấp bởi Java để tạo CSR.

Về cơ bản các bước để tạo một CSR là:

  1. Lấy cặp khóa mà CSR được yêu cầu. Nó có thể được tạo bằng KeyPairGenerator hoặc có thể được tải từ kho khóa (Được ưu tiên)
  2. Tạo chủ thể cho yêu cầu chứng chỉ và cũng tạo chữ ký cho yêu cầu chứng chỉ
  3. Ký yêu cầu chứng chỉ bằng khóa riêng từ cặp khóa trong #1
  4. Lấy dữ liệu yêu cầu chứng chỉ được mã hóa và lưu trữ nó và gửi nó đến CA để tạo chứng chỉ.

Vì mục đích trình diễn, chúng ta sẽ lấy cặp khóa bằng KeyPairGenerator, nhưng trong ứng dụng thực tế, tốt hơn là nên lưu trữ cặp khóa trong một kho khóa.

Dưới đây là một ví dụ để tạo yêu cầu chứng chỉ với RSA.

public class CSRGenerator {
	public static void main(String[] args) {
		CSRGenerator csrGeneration = new CSRGenerator();
		
		// Tạo cặp khóa
		KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
		System.out.println("KeyPair generated");
		
		byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
		
		System.out.println(new String(csrData));
	}
	
	/**
	 * Tạo CSR mong muốn để ký
	 * 
	 * @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];
	}

	/**
	 * Tạo cặp khóa mong muốn
	 * 
	 * @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;
	}
}

Lưu ý rằng có một số khác biệt giữa Java 6 và Java 7 khi gọi PKCS10.encodeAndSign(). Java 7 không còn X500Signer nữa.

Nếu bạn đang sử dụng IBM Java thay vì Oracle Java, cách tạo yêu cầu chứng chỉ sẽ khác. Xem bên dưới.

public class CSRGenerator {
	public static void main(String[] args) {
		CSRGenerator csrGeneration = new CSRGenerator();
		
		// Tạo cặp khóa
		KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
		System.out.println("KeyPair generated");
		
		byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
		
		System.out.println(new String(csrData));
	}
	
	/**
	 * Tạo CSR mong muốn để ký
	 * 
	 * @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];
	}

	/**
	 * Tạo cặp khóa mong muốn
	 * 
	 * @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;
	}
}

Yêu cầu chứng chỉ được tạo ở dạng mã hóa BASE64 sẽ trông như thế này:

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

Hy vọng điều này sẽ giúp bạn nếu bạn đang gặp khó khăn với việc tạo yêu cầu chứng chỉ trong Java.

JAVA SECURITY CSR CERTIFICATE REQUEST

  RELATED

  COMMENTS

0

No comment for this article.