在之前的文章中,我们解释了如何在Java中创建证书链。生成链后,我们需要将其存储在某个位置,以便稍后在进行实际的SSL通信时可以使用它,无论是密钥库还是信任库。这篇文章将向您展示如何将私钥及其关联的证书链存储在密钥库文件中。
在Java中存在不同类型的密钥库,在这篇文章中,我们将选择JKS来演示如何存储证书链。将私钥条目存储到密钥库时,我们也需要存储其关联的证书链。通常,我们需要为条目提供一个别名来标识该条目。以下是将条目存储到密钥库的代码片段:
KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(null,null);
keyStore.setKeyEntry(alias, key, password, chain);
keyStore.store(new FileOutputStream(keystore),password);
首先,我们将加载一个空的密钥库,如果您已经有密钥库,可以替换:
keyStore.load(null,null);
为
keyStore.load(new FileInputStream(keystore),password);
加载密钥库后,我们可以通过调用setKeyEntry并传递别名、私钥、密钥保护密码和关联的证书链来设置条目。然后我们调用keyStore.store()来存储条目。请注意,在某些硬件密钥库中,我们不需要调用keyStore.store()方法来保存密钥库,setKeyEntry()将自动将条目放入硬件中。
我们可以通过调用
keyStore.getCertificateChain()方法并指定别名来从密钥库中检索证书链。
Certificate[] certs=keyStore.getCertificateChain(alias);
下面是一个可行的程序,演示如何存储和检索证书链。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
//import javax.security.cert.Certificate;
import sun.security.x509.BasicConstraintsExtension;
import sun.security.x509.CertAndKeyGen;
import sun.security.x509.CertificateExtensions;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
public class CertificateChainGeneration {
public static void main(String[] args){
try{
//生成ROOT证书
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
keyGen.generate(1024);
PrivateKey rootPrivateKey=keyGen.getPrivateKey();
X509Certificate rootCertificate = keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long) 365 * 24 * 60 * 60);
//生成中间证书
CertAndKeyGen keyGen1=new CertAndKeyGen("RSA","SHA1WithRSA",null);
keyGen1.generate(1024);
PrivateKey middlePrivateKey=keyGen1.getPrivateKey();
X509Certificate middleCertificate = keyGen1.getSelfCertificate(new X500Name("CN=MIDDLE"), (long) 365 * 24 * 60 * 60);
//生成叶子证书
CertAndKeyGen keyGen2=new CertAndKeyGen("RSA","SHA1WithRSA",null);
keyGen2.generate(1024);
PrivateKey topPrivateKey=keyGen2.getPrivateKey();
X509Certificate topCertificate = keyGen2.getSelfCertificate(new X500Name("CN=TOP"), (long) 365 * 24 * 60 * 60);
rootCertificate = createSignedCertificate(rootCertificate,rootCertificate,rootPrivateKey);
middleCertificate = createSignedCertificate(middleCertificate,rootCertificate,rootPrivateKey);
topCertificate = createSignedCertificate(topCertificate,middleCertificate,middlePrivateKey);
X509Certificate[] chain = new X509Certificate[3];
chain[0]=topCertificate;
chain[1]=middleCertificate;
chain[2]=rootCertificate;
String alias = "mykey";
char[] password = "password".toCharArray();
String keystore = "testkeys.jks";
//存储证书链
storeKeyAndCertificateChain(alias, password, keystore, topPrivateKey, chain);
//重新加载密钥库并显示密钥和证书链信息
loadAndDisplayChain(alias, password, keystore);
//清除密钥库
clearKeyStore(alias, password, keystore);
}catch(Exception ex){
ex.printStackTrace();
}
}
private static void storeKeyAndCertificateChain(String alias, char[] password, String keystore, Key key, X509Certificate[] chain) throws Exception{
KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(null,null);
keyStore.setKeyEntry(alias, key, password, chain);
keyStore.store(new FileOutputStream(keystore),password);
}
private static void loadAndDisplayChain(String alias,char[] password, String keystore) throws Exception{
//重新加载密钥库
KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(new FileInputStream(keystore),password);
Key key=keyStore.getKey(alias, password);
if(key instanceof PrivateKey){
System.out.println("获取私钥:");
System.out.println(key.toString());
Certificate[] certs=keyStore.getCertificateChain(alias);
System.out.println("证书链长度:"+certs.length);
for(Certificate cert:certs){
System.out.println(cert.toString());
}
}else{
System.out.println("密钥不是私钥");
}
}
private static void clearKeyStore(String alias,char[] password, String keystore) throws Exception{
KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(new FileInputStream(keystore),password);
keyStore.deleteEntry(alias);
keyStore.store(new FileOutputStream(keystore),password);
}
private static X509Certificate createSignedCertificate(X509Certificate cetrificate,X509Certificate issuerCertificate,PrivateKey issuerPrivateKey){
try{
Principal issuer = issuerCertificate.getSubjectDN();
String issuerSigAlg = issuerCertificate.getSigAlgName();
byte[] inCertBytes = cetrificate.getTBSCertificate();
X509CertInfo info = new X509CertInfo(inCertBytes);
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) issuer));
//不需要为叶子证书添加BasicContraint
if(!cetrificate.getSubjectDN().getName().equals("CN=TOP")){
CertificateExtensions exts=new CertificateExtensions();
BasicConstraintsExtension bce = new BasicConstraintsExtension(true, -1);
exts.set(BasicConstraintsExtension.NAME,new BasicConstraintsExtension(false, bce.getExtensionValue()));
info.set(X509CertInfo.EXTENSIONS, exts);
}
X509CertImpl outCert = new X509CertImpl(info);
outCert.sign(issuerPrivateKey, issuerSigAlg);
return outCert;
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
}
我们将在以后的文章中介绍证书的不同扩展。
the above code give that error to me when i run this on java netbeans.
java.security.cert.CertificateException: Issuer class type invalid.
at sun.security.x509.X509CertInfo.setIssuer(X509CertInfo.java:860)
at sun.security.x509.X509CertInfo.set(X509CertInfo.java:403)
at certchain.CertificateChainGeneration.createSignedCertificate(CertificateChainGeneration.java:123)
at certchain.CertificateChainGeneration.main(CertificateChainGeneration.java:56)
java.lang.NullPointerException
at certchain.CertificateChainGeneration.createSignedCertificate(CertificateChainGeneration.java:118)
at certchain.CertificateChainGeneration.main(CertificateChainGeneration.java:57)
java.lang.NullPointerException
at certchain.CertificateChainGeneration.createSignedCertificate(CertificateChainGeneration.java:118)
at certchain.CertificateChainGeneration.main(CertificateChainGeneration.java:58)
java.lang.NullPointerException
at sun.security.provider.JavaKeyStore.engineStore(JavaKeyStore.java:577)
at sun.security.provider.JavaKeyStore$JKS.engineStore(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineStore(KeyStoreDelegator.java:195)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineStore(JavaKeyStore.java:70)
at java.security.KeyStore.store(KeyStore.java:1377)
at certchain.CertificateChainGeneration.storeKeyAndCertificateChain(CertificateChainGeneration.java:85)
at certchain.CertificateChainGeneration.main(CertificateChainGeneration.java:70)