Secret Key Import in Java Keystore by Key Replacement Method
Join the DZone community and get the full member experience.
Join For FreeIf you are a programmer and have to deal with cryptography issues, you've surely heard about keywords such as encryption, decryption and key management. The last key word, key management, is defined as a group of operations such as generating, exchanging, storing and protecting security artifacts (i.e. keys and certificates). Security artifacts are essential parts of any cryptography operations. Without effective management of such valuable resources, the system can be easily compromised by attackers.
Java supports key management by introducing two utilities; Java Keys Store or JKS as short and Java Keytool Utility. Java Key Store is a handy and safe storage to store keys and certificates. Java key store API describes methods and properties of Java keystore class which makes it possible to work with keystore file programmatically. To manage keys and certificates, Java provides a second utility named Java Keytool Utility. Keytool utility is included and delivered with JDK (Java Development Kit) distributions. The Keytool manual introduces and describes various commands and options that are available and provides by Java Keytool utility. Key management is feasible by services that are offered by both Java keystore and Java Keytool utility together.
The Key management that Java provides is covering most of programming scenarios. Unfortunately there is only one limitation. Java Keytool utility as the main key management unit does not support any means to import custom created keys to Java keystore. It only supports key generation which results in auto generated keys. This is a major shortcoming in situations where there must be key exchange between application peers. In such situations key specifications are specific to the security models which are agreed between developers. Sometimes the keys are byte streams which are not accompanied with any certificates. These streams are defined as cryptography artifacts and must be protected and saved by Java keystore.
One solution to this problem is to use third party utilities such as Openssl. Openssl utility offers a mechanism which is a hack to the unavailability of key import in Java Keytool utility. The trick is to save keys in PKCS12 format using the Openssl utility, and treating the created artifact as a new keystore. Fortunately Java Keytool utility supports key store merge option. The created keystore by Openssl utility then can be merged into any Java keystore by Java Keytool utility.
Unfortunately I could not succeed in following this solution. One reason could be that my key had customized specifications such as size and value, plus there was no certificate available to accompany it as well. It seemed that there was no other way to overcome such limitation. I found a solution, pretty easy and quick that helped me achieving the result I wanted without being dependent on any third party tools. One advantage of this method is the use of current options that are offered by both Keytool and Java Keystore utilities. Let’s name this method “Key Replacement”.
Firstly a new key must be created, for example, a secret key. The secret key will be auto generated by the Keytool utility and will be saved under a known ALIAS inside a new key store or in an existing one. Open your command prompt and issue the following command:
keytool -genseckey -alias mykey -keyalg DES -keysize 56 -storetype jceks -keystore <PATH>
Make sure you have set your Java runtime environment correctly. Description and details of the above command and options can be found on Keytool manual. After issuing the above command, you will be asked to provide a password for the keystore. If the keystore already exists, provide its password; otherwise enter a password to be set for the newly created keystore. If the operation was successful, you can list the keystore entries by issuing the following command:
keytool -list -v -storetype JCEKS -keystore <PATH TO EXISTING KEY STORE>
The result of list command will be a list of keystore's entries. In our case, the record we seek is something like :
Keystore type: JCEKS Keystore provider: SunJCE Your keystore contains 1 entry Alias name: mykey Creation date: Sep 30, 2013 Entry type: SecretKeyEntry
As you can see the newly created key is represented by the alias we have set. This key is auto generated by Java Keytool utility. We are one step closer to what we needed. We have created a key entry with the alias we want. The final step is to change the key entry value with our customized value. Remaining steps consists of, locating the target key entry inside the keystore by its alias and change its value with our own value programmatically. The following simple java program will do the job.
KeyStore ks = KeyStore.getInstance("JCEKS"); char[] password = "PASSWORD TO KEYSATORE".toCharArray(); java.io.FileInputStream fis = null; try { ks.load(new FileInputStream("PATH TO KEY STORE"), password); } finally { if (fis != null) { fis.close(); } } SecretKey mySecretKey = new SecretKeySpec(Util.hex2byte("5A5A5A5A5A5A5A5A"), 0, Util.hex2byte("5A5A5A5A5A5A5A5A").length, "DES"); KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey); ks.setEntry("mykey", skEntry, new KeyStore.PasswordProtection(password)); java.io.FileOutputStream fos = null; try { fos = new java.io.FileOutputStream("PATH TO KEYSTORE"); ks.store(fos, password); } finally { if (fos != null) { fos.close(); } }
This java program will:
· Open the keystore.
· Load the key store prior to any operation.
· Build a secret key with desired specs (Custom value and Custom length).
· Replace the value of target key by using the setEntry() method of keystore object by providing its alias and a new key value.
· Finally close and save the keystore object.
To double check the modification, use the following code to locate and display the modified key value by loading the keystore object again.
try { ks.load(new FileInputStream("PATH TO KEY SOTRE"), password); } finally { if (fis != null) { fis.close(); } } Key key = ks.getKey("mykey ", password); System.out.println("-----BEGIN PRIVATE KEY-----"); System.out.println(new BASE64Encoder().encode(key.getEncoded())); System.out.println("-----END PRIVATE KEY-----");
The steps are straight forward:
· Load the key store object.
· Load the target key by using the getKey() method and specifying its alias.
· Fetch the key value and output its value in PEM format (Base 64 encoding).
Voila! That’s our key.
This article shows some simple steps which can be used to import a custom created secret key to java keystore. Hope this article will be helpful in cases where the tools such as Openssl utility has no use.
Sam,
Opinions expressed by DZone contributors are their own.
Comments