自签名证书
自签证书(自颁发证书),由签名实体发布给自身的证书,即发布者和证书主体相同,是同一个CA的证书。
自颁发(签发)证书的一种特殊情形,由CA使用其私钥来对证书进行签名,而相应公钥就在证书中。
根CA的数字证书,由自己签发,就属于自签名证书。
颁发数字证书
定义:CA证书是由一个CA颁发给另一个CA的证书。
生成根证书
keytool -genkey -dname "CN=XFDServer,OU=XFDUnit,O=XFD,L=TaiYuan, ST=ShanXi, C=CN" -keysize 2048 -alias server -keyalg RSA -keystore d:/server.jks -keypass 123456 -storepass 123456 -validity 36500
颁发数字证书代码
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.List;
public class IssueCertificate {
static final String keyStoreType = "JKS";
// key长度
static final int keysize = 2048;
/**
* 从CA证书的JKS文件中读取私钥
*
* @param storeFile
* @param storePasswd
* @param caAlias
* @param trustPasswd
* @return
* @throws Exception
*/
public static KeyStore.PrivateKeyEntry getRootPrivateKey(String storeFile, String storePasswd, String caAlias, String trustPasswd) throws Exception {
KeyStore store = KeyStore.getInstance(keyStoreType);
store.load(new FileInputStream(storeFile), storePasswd.toCharArray());
char[] trustCPW = trustPasswd.toCharArray();
KeyStore.PasswordProtection passwordProtection = new KeyStore.PasswordProtection(trustCPW);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) store.getEntry(caAlias, passwordProtection);
return privateKeyEntry;
}
public static void issueCertificate(KeyStore.PrivateKeyEntry privateKeyEntry, String alias, String subject, String trustPasswd, int validityYear,
String trustPath) throws Exception {
// 生成秘钥对
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(keysize);
KeyPair keyPair = kpg.generateKeyPair();
KeyStore store = KeyStore.getInstance(keyStoreType);
store.load(null, null);
// 颁发者
X509Certificate caCert = (X509Certificate) privateKeyEntry.getCertificate();
// 颁发者
String issuer = caCert.getIssuerDN().toString();
Date notBefore = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
Date notAfter = new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 365 * validityYear);
Certificate signCert = generateV3(issuer, subject, BigInteger.ZERO, notBefore, notAfter, keyPair.getPublic(), privateKeyEntry.getPrivateKey(), null);
// 输出证书
makeSignCert(keyPair, alias, signCert, privateKeyEntry.getCertificate(), trustPasswd, trustPath);
}
/**
* 输出证书
*
* @param keyPair
* @param alias
* @param signCert
* @param caCert
* @param trustPasswd
* @param trustPath
* @throws Exception
*/
private static void makeSignCert(KeyPair keyPair, String alias, Certificate signCert, Certificate caCert, String trustPasswd, String trustPath) throws Exception {
KeyStore signStore = KeyStore.getInstance(keyStoreType);
signStore.load(null, null);
signStore.setKeyEntry(alias, keyPair.getPrivate(), trustPasswd.toCharArray(), new Certificate[]{signCert, caCert});
File file = new File(trustPath);
if (file.exists() || file.createNewFile()) {
signStore.store(new FileOutputStream(file), trustPasswd.toCharArray());
}
}
/**
* @param issuer
* @param subject
* @param serial
* @param notBefore
* @param notAfter
* @param publicKey
* @param privateKey
* @param extensions
* @return
* @throws Exception
*/
private static Certificate generateV3(String issuer, String subject, BigInteger serial, Date notBefore, Date notAfter,
PublicKey publicKey, PrivateKey privateKey, List<Extension> extensions) throws Exception {
// X500Name var1, BigInteger var2, Date var3, Date var4, X500Name var5, PublicKey var6
X500Name var1 = new X500Name(issuer);
X500Name var5 = new X500Name(subject);
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(var1, serial, notBefore, notAfter, var5, publicKey);
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA").build(privateKey);
// privateKey是CA的私钥,publicKey是待签名的公钥,那么生成的证书就是被CA签名的证书
if (extensions != null)
for (Extension ext : extensions) {
builder.addExtension(new ASN1ObjectIdentifier(ext.getId()), ext.isCritical(), ASN1Primitive.fromByteArray(ext.getValue()));
}
X509CertificateHolder holder = builder.build(contentSigner);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream is1 = new ByteArrayInputStream(holder.toASN1Structure().getEncoded());
X509Certificate theCert = (X509Certificate) certificateFactory.generateCertificate(is1);
is1.close();
return theCert;
}
}
import java.security.KeyStore;
public class IssueCertificateClient {
public static void main(String[] args) {
// 生成根证书
// keytool -genkey -dname "CN=XFDServer,OU=XFDUnit,O=XFD,L=TaiYuan, ST=ShanXi, C=CN" -keysize 2048 -alias server -keyalg RSA -keystore d:/server.jks -keypass 123456 -storepass 123456 -validity 36500
String storeFile = "d:/server.jks";
String storePasswd = "123456";
String caAlias = "server";
String trustPasswd = "123456";
KeyStore.PrivateKeyEntry rootPrivateKeyEntry = null;
try {
rootPrivateKeyEntry = IssueCertificate.getRootPrivateKey(storeFile, storePasswd, caAlias, trustPasswd);
} catch (Exception e) {
e.printStackTrace();
}
String alias = "client1";
String subjects = "C=CN,ST=ShanXi,L=TaiYuan,O=XFD,OU=XFDUnit,CN=XFDClient1";
String signTrustPasswd = "123456";
int validityYears = 10;
String trustPath = "d:/client1.jks";
try {
IssueCertificate.issueCertificate(rootPrivateKeyEntry, alias, subjects, signTrustPasswd, validityYears, trustPath);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("颁发证书完成.");
// keytool -export -alias client1 -keystore d:/client1.jks -file d:/client1.crt -storepass 123456
}
}
生成crt证书
keytool -export -alias client1 -keystore d:/client1.jks -file d:/client1.crt -storepass 123456
查看颁发证书
keytool -list -rfc -keystore d:/client1.jks -storepass 123456