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à:
- 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)
- 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ỉ
- Ký yêu cầu chứng chỉ bằng khóa riêng từ cặp khóa trong #1
- 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.