Generate certificate in Java -- Store certificate in KeyStore

  Pi Ke        2014-08-20 03:56:39       31,759        10          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

Trong bài viết trước, chúng ta đã giải thích cách tạo chuỗi chứng chỉ trong Java. Sau khi tạo chuỗi, chúng ta cần lưu trữ nó ở đâu đó để có thể sử dụng sau này khi thực hiện giao tiếp SSL thực tế, hoặc trong kho khóa hoặc kho lưu trữ đáng tin cậy. Bài viết này sẽ hướng dẫn bạn cách lưu trữ khóa riêng và chuỗi chứng chỉ liên quan của nó trong tệp kho khóa.

nhiều loại kho khóa trong Java, trong bài viết này, chúng ta sẽ chọn JKS để chứng minh cách lưu trữ chuỗi chứng chỉ. Khi lưu trữ mục khóa riêng vào kho khóa, chúng ta cũng cần lưu trữ chuỗi chứng chỉ liên quan của nó. Thông thường, chúng ta cần đặt cho mục nhập một bí danh để xác định mục nhập đó. Dưới đây là đoạn mã để lưu trữ một mục vào kho khóa:

KeyStore keyStore=KeyStore.getInstance("jks");
keyStore.load(null,null);

keyStore.setKeyEntry(alias, key, password, chain);
keyStore.store(new FileOutputStream(keystore),password);

Đầu tiên, chúng ta sẽ tải một kho khóa trống, nếu bạn đã có kho khóa, có thể thay thế:

keyStore.load(null,null);

bằng

keyStore.load(new FileInputStream(keystore),password);

Sau khi tải kho khóa, chúng ta có thể đặt mục nhập bằng cách gọi setKeyEntry và truyền bí danh, khóa riêng, mật khẩu bảo vệ khóa và chuỗi chứng chỉ liên quan. Sau đó, chúng ta gọi keyStore.store() để lưu trữ mục nhập. Lưu ý rằng trong một số kho khóa phần cứng, chúng ta không cần gọi phương thức keyStore.store() để lưu kho khóa, phương thức setKeyEntry() sẽ tự động đặt mục nhập vào phần cứng.

Chúng ta có thể truy xuất chuỗi chứng chỉ từ kho khóa bằng cách gọi

phương thức keyStore.getCertificateChain() với bí danh đã chỉ định.

Certificate[] certs=keyStore.getCertificateChain(alias);

Dưới đây là một chương trình hoạt động được chứng minh cách lưu trữ và truy xuất chuỗi chứng chỉ.

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;
	}
}

Chúng ta sẽ đề cập đến các phần mở rộng khác nhau của chứng chỉ trong bài viết tiếp theo.

JAVA  CERTIFICATE CHAIN  KEYSTORE 

       

  RELATED


  10 COMMENTS


Anonymous [Reply]@ 2017-11-21 07:57:35

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)

Ke Pi [Reply]@ 2017-11-21 11:45:21

Which version of Java you are using? 

Anonymous [Reply]@ 2017-11-22 08:50:52

thanks its resolved now !

but i can u tell me how i convert jks file in .cert file i want to deploy certificate chain file in my browser.

please let me now ASAP .

Ke Pi [Reply]@ 2017-11-22 10:43:36

You can simply use the keytool provided by JDK. 

To list all certificates, run

keytool -list -keystore test.jks -rfc

To list a certificate or certificate chain with specific alias, run

keytool -list -alias leaf -keystore test.jks -rfc

You simply need to copy the below portion to a cert file.

-----BEGIN CERTIFICATE-----

MIICmjCCAligAwIBAgIESf24ljALBgcqhkjOOAQDBQAwDTELMAkGA1UEAxMCQ0EwHhcNMTUxMjE3

MTI0NDUxWhcNMTYwMzE2MTI0NDUxWjAPMQ0wCwYDVQQDEwRMZWFmMIIBuDCCASwGByqGSM44BAEw

ggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbL

m1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNa

FpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7L

vKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwW

eotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFM

O/7PSSoDgYUAAoGBAJeZBwSThPLWJgKqGGYovL+867P4e+U3rjYvQtYMuX1cS+dEds3hxgWGUlcW

6/ss43N2L1XG2jn5okiwL5JDGShmVkIqZ00ndjhGpDx86pj8p6VvNlFjvKU+huLk5OnLqdgtBZzE

xvw/qJ2RA332POV88hpOwo4nzoYOpXXnx9pio0IwQDAfBgNVHSMEGDAWgBQkZybun0K+v86ei02O

Hr2vl4I95DAdBgNVHQ4EFgQUIxnQWEhrQUsOJEI6/2A4afFjERIwCwYHKoZIzjgEAwUAAy8AMCwC

FAJsk2SwPh1svZwmTqOmrEbtf3OqAhQyoNCxJff8HfTktjOSqutkjme43w==

-----END CERTIFICATE-----

 

Anonymous [Reply]@ 2018-01-03 01:44:04

How do you solved this exception?

Vivek [Reply]@ 2018-09-25 09:56:06

I am getting below exceptions, when executing the given code :

 

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 testsample.Cert.createSignedCertificate(Cert.java:114)

at testsample.Cert.main(Cert.java:47)

java.lang.NullPointerException

at testsample.Cert.createSignedCertificate(Cert.java:109)

at testsample.Cert.main(Cert.java:48)

java.lang.NullPointerException

at testsample.Cert.createSignedCertificate(Cert.java:109)

at testsample.Cert.main(Cert.java:49)

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 testsample.Cert.storeKeyAndCertificateChain(Cert.java:76)

at testsample.Cert.main(Cert.java:61)

 

 

Please help, I am using jdk 1.8.162 version.

Vivek [Reply]@ 2018-09-26 13:04:00

I am able to execute the code and it is working fine. But when I am trying to list the certificates using KeyTool with command "keytool -list -keystore test.jks -rfc" then I am getting below message :

 

Enter keystore password:

Keystore type: JKS

Keystore provider: SUN

 

 

Your keystore contains 0 entries

 

 

It is not showing any entry, please help

Ke Pi [Reply]@ 2018-09-27 09:52:02

The output shows that the keystore contains no entry. Are you sure you saved the keystore correctly? Also can you add -v when you run the list command.

ankit [Reply]@ 2019-04-06 03:33:05

will itworkwith java 9 and latest versions..

i believe sun.security is not supported by java 9

Ankit [Reply]@ 2019-04-06 03:35:06

pl help me with latest codes for self signed X509 certificate generation on java 9 or latest versions..



  RANDOM FUN

Amazon Washing Service?