仅使用java代码生成适用于nginx的https证书
添加maven依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
</dependency>
方法定义
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Calendar;
import java.util.Date;
/**
* @author lc
* @version 1.0
* @description: TODO
* @date 2023/3/29 19:29
*/
public class HttpsUtil {
static Log log = LogFactory.get();
public static final String caname = " .cn";
public static final String OU = ",OU= .cn,O= ,C=cn";
public static Date getStartDate() {
Calendar startC = Calendar.getInstance();
startC.add(Calendar.DAY_OF_YEAR, -1);
Date startDate = startC.getTime(); // yesterday
return startDate;
}
public static Date getEndDate() {
Calendar endC = Calendar.getInstance();
endC.add(Calendar.YEAR, 10);
Date endDate = endC.getTime(); // one year from now
return endDate;
}
public static void GenerateNginxHttpsCertificate(String hostname, String filePath, String filename, String pwd) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, CertificateException, OperatorCreationException {
// Generate key pair
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(4096);
KeyPair keyPair = generator.generateKeyPair();
// Create certificate
X500Principal issuer = new X500Principal("CN=" + hostname + OU);
X500Principal subject = new X500Principal("CN=" + hostname + OU);
X500Name issuerName = new X500Name(issuer.getName());
X500Name subjectName = new X500Name(subject.getName());
Date startDate = getStartDate(); // yesterday
Date endDate = getEndDate(); // one year from now
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
issuerName,
new BigInteger(64, new SecureRandom()),
startDate,
endDate,
subjectName,
keyPair.getPublic()
);
ASN1Encodable[] subjectAlternativeNames = new ASN1Encodable[]{
new GeneralName(GeneralName.dNSName, hostname),
// new GeneralName(GeneralName.dNSName, "www.example.com"),
// new GeneralName(GeneralName.iPAddress, "192.168.0.1")
};
byte[] sanExtensionValue = new DERSequence(subjectAlternativeNames).getEncoded(ASN1Encoding.DER);
// String dns1 = "DNS:" + hostname;
Extension dns = new Extension(Extension.subjectAlternativeName, false, sanExtensionValue);
builder.addExtension(dns);
// 添加基本约束扩展
BasicConstraints basicConstraints = new BasicConstraints(true);
builder.addExtension(Extension.basicConstraints, true, basicConstraints.getEncoded());
builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign
| KeyUsage.digitalSignature|KeyUsage.keyEncipherment));
// 添加Subject Key Identifier扩展
builder.addExtension(
Extension.subjectKeyIdentifier,
false,
new JcaX509ExtensionUtils().createSubjectKeyIdentifier(keyPair.getPublic())
);
// SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
// 添加Authority Key Identifier扩展
builder.addExtension(
Extension.authorityKeyIdentifier,
false,
new JcaX509ExtensionUtils().createAuthorityKeyIdentifier(keyPair.getPublic())
);
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate());
X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(builder.build(signer));
saveCertToFile(filePath, filename, certificate, keyPair, pwd);
}
public static void saveCertToFile(String filePath, String filename, X509Certificate certificate, KeyPair keyPair, String password) throws IOException, CertificateEncodingException, NoSuchAlgorithmException, InvalidKeySpecException {
// Write key pair and certificate to files
FileOutputStream keyOut = new FileOutputStream(filePath + File.separator + filename + ".private.key");
keyOut.write(keyPair.getPrivate().getEncoded());
keyOut.close();
FileOutputStream certOut = new FileOutputStream(filePath + File.separator + filename + ".crt");
certOut.write(certificate.getEncoded());
certOut.close();
FileOutputStream out = new FileOutputStream(filePath + File.separator + filename + ".pem");
JcaPEMWriter writer = new JcaPEMWriter(new java.io.OutputStreamWriter(out));
writer.writeObject(certificate);
writer.close();
out.close();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
FileOutputStream keyout = new FileOutputStream(filePath + File.separator + filename + ".key");
JcaPEMWriter keywriter = new JcaPEMWriter(new java.io.OutputStreamWriter(keyout));
keywriter.writeObject(key);
keywriter.close();
keyout.close();
try {
//创建一个空的keystore
KeyStore keyStore = null;
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
//将密钥对保存到keystore中
char[] password1 = password.toCharArray();
X509Certificate[] chain = {certificate};
keyStore.setKeyEntry("tomcat", keyPair.getPrivate(), password1, chain);
//将keystore保存到文件
try (FileOutputStream fos = new FileOutputStream(filePath + File.separator + filename + ".keystore")) {
keyStore.store(fos, password1);
}
} catch (KeyStoreException | CertificateException e) {
e.printStackTrace();
}
}
}
.pem 和 .key文件适用于nginx
nginx配置证书
server {
listen 443 ssl;
ssl_certificate certs/testhttps.pem;
ssl_certificate_key certs/testhttps.key;
```````