一个CSR(证书签名请求)是由应用程序生成的请求,用于发送到证书颁发机构以创建可分发的签名证书。它通常包含证书信息,例如主题名称、公钥信息和签名信息。
在Java中,可以使用keytool命令生成证书请求,选项为-certreq。但是,有时如果应用程序想要以编程方式创建CSR,keytool将无法提供帮助,而应该使用Java提供的API来生成CSR。
基本上,生成CSR的步骤如下:
- 获取CSR请求的密钥对。它可以使用KeyPairGenerator生成,也可以从密钥库加载(推荐)
- 创建证书请求的主题,并为证书请求创建签名
- 使用步骤1中密钥对的私钥签名证书请求
- 获取编码的证书请求数据,并将其存储并发送到CA以创建证书。
为了演示,我们将使用KeyPairGenerator获取密钥对,但在实际应用程序中,最好将密钥对存储在密钥库中。
以下是使用RSA创建证书请求的示例。
public class CSRGenerator {
public static void main(String[] args) {
CSRGenerator csrGeneration = new CSRGenerator();
// 生成密钥对
KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
System.out.println("KeyPair generated");
byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
System.out.println(new String(csrData));
}
/**
* 生成所需的CSR进行签名
*
* @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)); // 适用于Java 6
pkcs10.encodeAndSign(x500Name, sig); // 适用于Java 7和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];
}
/**
* 生成所需的密钥对
*
* @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;
}
}
请注意,在调用PKCS10.encodeAndSign()时,Java 6和Java 7之间存在一些差异。Java 7不再具有X500Signer。
如果您使用的是IBM Java而不是Oracle Java,则生成证书请求的方式有所不同。请参见下文。
public class CSRGenerator {
public static void main(String[] args) {
CSRGenerator csrGeneration = new CSRGenerator();
// 生成密钥对
KeyPair keyPair = csrGeneration.generateKeyPair("RSA", 1024);
System.out.println("KeyPair generated");
byte[] csrData = csrGeneration.generateCSR("SHA256WithRSA", keyPair);
System.out.println(new String(csrData));
}
/**
* 生成所需的CSR进行签名
*
* @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];
}
/**
* 生成所需的密钥对
*
* @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;
}
}
使用BASE64编码生成的证书请求应如下所示:
-----BEGIN NEW CERTIFICATE REQUEST----- MIIBZjCB0AIBADAWMRQwEgYDVQQDEwtFWEFNUExFLkNPTTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw gYkCgYEAgXneACRkW0QvpuuNhzo8OOmxe7xPzd3UZJ9MOEA5VhP5QvWGMGFNITGmubL1I2AWmsHz yMxwO0SHPFNclo4oSm+Cu2d67d28vingYBGEBrVXIwg3j1CVADcGjb39TcYL77fofBem8XNDCw0N WKLaTqpnVaAtqvnE0+r7O3BZZg8CAwEAAaARMA8GCSqGSIb3DQEJDjECMAAwDQYJKoZIhvcNAQEL BQADgYEAb5jNx6ASGpgTXTNz5UrD6BrTyLZYyTmlQwI0EjhG0lVY5sYiQGz7t6JQP62aqRFfM7vo dYMnKxeuApp5LSY3EdyY1F5I20PPTbpSSP529pV5gIQZk4FZMoth7dvWgBH3pqB0BkHQ1g+wdWof m2imkOR1D+7Yn6xvQ/Be9mXienU= -----END NEW CERTIFICATE REQUEST-----
如果您在Java中生成证书请求时遇到困难,希望这能帮到您。
No comment for this article.