概要
- 自签名证书的用途
一般我们需要注册CA证书给网站添加HTTPS,不过本地测试的时候,我们可以使用自签名证书。
自签名证书只是作为测试用途,不具备安全性,客户端没有安装该证书时,浏览器也会给出提示。
关键实现代码
- SelfSignedCertificate.java
/**
* Creates a new instance.
*
* @param fqdn a fully qualified domain name 需要证书的完整域名
* @param random the {@link java.security.SecureRandom} to use
* @param bits the number of bits of the generated private key
* @param notBefore Certificate is not valid before this time 证书在该日期前无效,默认当前时间的一年前
* @param notAfter Certificate is not valid after this time 证书在该日期后无效,默认10000年
*/
public SelfSignedCertificate(String fqdn, SecureRandom random, int bits, Date notBefore, Date notAfter)
throws CertificateException {
// 基于jdk中的jar包java.security.KeyPair,生成RSA秘钥对
// Generate an RSA key pair.
final KeyPair keypair;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
//这里的random,netty默认使用ThreadLocalInsecureRandom类来生成非线程安全的1024bit随机数
keyGen.initialize(bits, random);
keypair = keyGen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
// Should not reach here because every Java implementation must have RSA key pair generator.
throw new Error(e);
}
String[] paths;
//通过OpenJdk或者BouncyCastle来生成证书文件,放在一个临时目录下
try {
// Try the OpenJDK's proprietary implementation.
paths = OpenJdkSelfSignedCertGenerator.generate(fqdn, keypair, random, notBefore, notAfter);
} catch (Throwable t) {
logger.debug("Failed to generate a self-signed X.509 certificate using sun.security.x509:", t);
try {
// Try Bouncy Castle if the current JVM didn't have sun.security.x509.
paths = BouncyCastleSelfSignedCertGenerator.generate(fqdn, keypair, random, notBefore, notAfter);
} catch (Throwable t2) {
logger.debug("Failed to generate a self-signed X.509 certificate using Bouncy Castle:", t2);
throw new CertificateException(
"No provider succeeded to generate a self-signed certificate. " +
"See debug log for the root cause.", t2);
// TODO: consider using Java 7 addSuppressed to append t
}
}
//这里的privateKey是私钥文件,key是私钥对象,内容是相同的
certificate = new File(paths[0]);
privateKey = new File(paths[1]);
key = keypair.getPrivate();
//根据证书文件,获取PEM格式的X509Certificate证书
FileInputStream certificateInput = null;
try {
certificateInput = new FileInputStream(certificate);
cert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(certificateInput);
} catch (Exception e) {
throw new CertificateEncodingException(e);
} finally {
if (certificateInput != null) {
try {
certificateInput.close();
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close a file: " + certificate, e);
}
}
}
}
}
Tips
- 如何根据PrivateKey转换成私钥文件中的私钥形式
new String(Base64.getEncoder().encode(keypair.getPrivate().getEncoded()),"UTF8")
Ref
https://netty.io/4.1/api/index.html
https://www.cnblogs.com/guogangj/p/4118605.html
网友评论