在之前的文章中,我們已經解釋了如何在 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,如果您已經有一個 keystore,可以替換:
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{
//Generate ROOT certificate
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);
//Generate intermediate certificate
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);
//Generate leaf certificate
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";
//Store the certificate chain
storeKeyAndCertificateChain(alias, password, keystore, topPrivateKey, chain);
//Reload the keystore and display key and certificate chain info
loadAndDisplayChain(alias, password, keystore);
//Clear the 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{
//Reload the keystore
KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(new FileInputStream(keystore),password);
Key key=keyStore.getKey(alias, password);
if(key instanceof PrivateKey){
System.out.println("Get private key : ");
System.out.println(key.toString());
Certificate[] certs=keyStore.getCertificateChain(alias);
System.out.println("Certificate chain length : "+certs.length);
for(Certificate cert:certs){
System.out.println(cert.toString());
}
}else{
System.out.println("Key is not private key");
}
}
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));
//No need to add the BasicContraint for leaf cert
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)