【发布时间】:2021-10-26 15:55:17
【问题描述】:
我正在使用以下代码在 java 中生成 CSR:
package demo;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import sun.security.pkcs10.PKCS10;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import sun.security.x509.CertificateExtensions;
import sun.security.x509.GeneralName;
import sun.security.x509.GeneralNames;
import sun.security.x509.SubjectAlternativeNameExtension;
import sun.security.x509.X500Name;
/**
* This class generates PKCS10 certificate signing request
*
* @author Pankaj@JournalDev.com
* @version 1.0
*/
public class GenerateCSR {
private static PublicKey publicKey = null;
private static PrivateKey privateKey = null;
private static KeyPairGenerator keyGen = null;
private static GenerateCSR gcsr = null;
private GenerateCSR() {
try {
keyGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyGen.initialize(2048, new SecureRandom());
KeyPair keypair = keyGen.generateKeyPair();
publicKey = keypair.getPublic();
privateKey = keypair.getPrivate();
}
public static GenerateCSR getInstance() {
if (gcsr == null)
gcsr = new GenerateCSR();
return gcsr;
}
public String getCSR(String cn) throws Exception {
byte[] csr = generatePKCS10(cn, "Java", "JournalDev", "Cupertino", "California", "USA");
return new String(csr);
}
/**
*
* @param CN Common Name, is X.509 speak for the name that distinguishes the Certificate best, and ties it to your
* Organization
* @param OU Organizational unit
* @param O Organization NAME
* @param L Location
* @param S State
* @param C Country
* @return
* @throws Exception
*/
private static byte[] generatePKCS10(String CN, String OU, String O, String L, String S, String C)
throws Exception {
GeneralNames generalNames = new GeneralNames();
generalNames.add(new GeneralName(new DerValue("b")));
generalNames.add(new GeneralName(new DerValue("a")));
CertificateExtensions ext = new CertificateExtensions();
ext.set(SubjectAlternativeNameExtension.NAME, new SubjectAlternativeNameExtension(generalNames));
// generate PKCS10 certificate request
String sigAlg = "MD5WithRSA";
PKCS10 pkcs10 = new PKCS10(publicKey);
Signature signature = Signature.getInstance(sigAlg);
signature.initSign(privateKey);
// common, orgUnit, org, locality, state, country
X500Name x500Name = new X500Name(CN, OU, O, L, S, C);
pkcs10.encodeAndSign(x500Name, signature);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bs);
pkcs10.print(ps);
byte[] c = bs.toByteArray();
try {
if (ps != null)
ps.close();
if (bs != null)
bs.close();
} catch (Throwable th) {
}
return c;
}
public PublicKey getPublicKey() {
return publicKey;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public static void main(String[] args) throws Exception {
GenerateCSR gcsr = GenerateCSR.getInstance();
System.out.println("Public Key:\n" + gcsr.getPublicKey().toString());
System.out.println("Private Key:\n" + gcsr.getPrivateKey().toString());
String csr = gcsr.getCSR("journaldev.com <https://www.journaldev.com>");
System.out.println("CSR Request Generated!!");
System.out.println(csr);
}
}
如您所见,我正在使用以下代码添加 SAN 名称
GeneralNames generalNames = new GeneralNames();
generalNames.add(new GeneralName(new DerValue("b")));
generalNames.add(new GeneralName(new DerValue("a")));
CertificateExtensions ext = new CertificateExtensions();
ext.set(SubjectAlternativeNameExtension.NAME, new SubjectAlternativeNameExtension(generalNames));
我的问题是:
- 这是正确的方法吗?
- 如果是如何使用CertificateExtensions的对象以及传递到哪里。
我指的是this的问题,上面提到我必须在我的证书的构造函数中传递它,但我不能让X500Name的构造函数只允许字符串值。
【问题讨论】:
-
使用来自
sun.security的任何类,或者实际上来自sun.*的任何类,正式不正确。这些是未记录为可供其他人使用的内部类。它们可能随时消失,或者行为可能会改变。并且它可能在 Java 库的其他兼容实现中根本不可用。您需要的一切都在 Bouncycastle 库 API 中提供。 -
然而,即使你使用
sun.*类也是不正确的。您使用的 GeneralName 必须是 DNSName 或 IPAddressName。new DerValue("b")两者都不是。像generalNames.add(new GeneralName(new DNSName("a.example.com")));这样的东西应该是正确的。虽然没有连接到 PKCS10 请求,所以需要更多的东西。
标签: java ssl x509certificate csr