ใน โพสต์ก่อนหน้า เราได้อธิบายวิธีการสร้าง certificate chain ใน Java แล้ว หลังจากสร้าง chain แล้ว เราจำเป็นต้องเก็บไว้ที่ใดที่หนึ่งเพื่อที่จะสามารถนำมาใช้ในภายหลังเมื่อเราทำการสื่อสาร SSL จริงๆ ไม่ว่าจะอยู่ใน key store หรือ trust store โพสต์นี้จะแสดงวิธีการเก็บ private key และ certificate chain ที่เกี่ยวข้องในไฟล์ keystore
มี keystore หลายประเภทใน Java ในโพสต์นี้ เราจะเลือก JKS เพื่อสาธิตวิธีการเก็บ certificate chain เมื่อเก็บ private key entry ลงใน keystore เราจำเป็นต้องเก็บ certificate chain ที่เกี่ยวข้องด้วย โดยปกติแล้ว เราจำเป็นต้องกำหนด alias ให้กับ entry เพื่อระบุ entry ด้านล่างนี้คือโค้ดสแนปช็อตเพื่อเก็บ entry ลงใน keystore:
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);
หลังจากโหลด keystore แล้ว เราสามารถตั้งค่า entry โดยการเรียก setKeyEntry และส่ง alias, private key, รหัสผ่านการป้องกัน key และ certificate chain ที่เกี่ยวข้อง จากนั้นเราเรียก keyStore.store() เพื่อเก็บ entry โปรดทราบว่าในบาง keystore ฮาร์ดแวร์ เราไม่จำเป็นต้องเรียกใช้เมธอด keyStore.store() เพื่อบันทึก keystore เมธอด setKeyEntry() จะใส่ entry ลงในฮาร์ดแวร์โดยอัตโนมัติ
เราสามารถดึง certificate chain จาก keystore โดยการเรียก
เมธอด keyStore.getCertificateChain() พร้อมกับ alias ที่ระบุ
Certificate[] certs=keyStore.getCertificateChain(alias);
ด้านล่างนี้คือโปรแกรมที่ใช้งานได้ซึ่งสาธิตวิธีการเก็บและดึง certificate chain
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; } }
เราจะกล่าวถึงส่วนขยายต่างๆ ของ certificate ในโพสต์ต่อไป
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)