Tuesday, 11 March 2014

Symmetric and Asymmetric key Encryption with Key tool

This post explains the concept of combining symmetric key and asymmetric key encryption with the use of key tool. For example which does this without the keytool refer here


Below video explains the concept in more detail



The keytool commands to create keystore and trustore and mentioned below

C:\Users\hunaid.husain\do>keytool -genkeypair -alias mykey -keyalg RSA -keysize 1024 -storetype jceks -validity 365 -keypass password -keystore ppkeystore.jck -storepass password -dname "cn=localhost, ou=Verisign, o=MyComp Inc, l=Foster City, st=California, c=US"

C:\Users\hunaid.husain\do>keytool -export -alias mykey -storetype jceks -keystore ppkeystore.jck -storepass password -file mykey.crt
Certificate stored in file 

C:\Users\hunaid.husain\do>keytool -importcert -alias mykey -file mykey.crt -keystore pptruststore.jck -keypass password -storepass password
Owner: CN=localhost, OU=Verisign, O=MyComp Inc, L=Foster City, ST=California, C=US
Issuer: CN=localhost, OU=Verisign, O=MyComp Inc, L=Foster City, ST=California, C=US
Serial number: ac90555
Valid from: Tue Mar 11 10:45:42 IST 2014 until: Wed Mar 11 10:45:42 IST 2015
Certificate fingerprints:
         MD5:  34:57:99:EE:F9:57:EF:10:A6:B3:B6:08:64:E6:6C:32
         SHA1: 75:50:DC:24:82:7F:82:ED:25:43:1C:71:45:A9:76:01:67:46:E3:89
         SHA256: C9:DE:CB:6B:E5:2E:6F:FA:4C:00:09:CD:A9:8A:48:D7:56:D1:B4:8B:EA:15:35:6D:4C:5F:34:1E:DC:EC:3E:1B
         Signature algorithm name: SHA256withRSA
         Version: 3

Extensions:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 84 BE 05 1C BC FB 6A CC   EE 28 F0 56 D0 5C 73 67  ......j..(.V.\sg
0010: C0 A4 CE 60                                        ...`
]
]
Trust this certificate? [no]:  yes
Certificate was added to keystore

Please note that in this example the symmetric key is generated programmatically and not using Keytool.

For a maven project you will need the apache-common-codec jar as a dependency or else just download the jar and paste it in the folder which is in the classpath.

Maven dependency:
<dependency>
 <groupId>commons-codec</groupId>
 <artifactId>commons-codec</artifactId>
 <version>1.8</version>
</dependency>

Java Main Class

package symmetric_assymetric_signature;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class Symmetric_AsymmetricKey {

 public static void main(String[] args) throws KeyStoreException,
   NoSuchAlgorithmException, CertificateException, IOException,
   NoSuchPaddingException, IllegalBlockSizeException,
   BadPaddingException, InvalidKeyException,
   UnrecoverableKeyException, NoSuchProviderException,
   SignatureException {

  /**
   * At the client side
   */
  KeyStoreUtil keyStoreUtil = new KeyStoreUtil();
  // Generate Symmetric key
  byte[] symmetrickey = keyStoreUtil.generateSessionKey();
  // Encrypt data by symmetric key
  String data = "ABC";
  System.out.println("Data : " + data);
  String encryptedData = keyStoreUtil.encryptWithAESKey(data,
    symmetrickey);
  System.out.println("encryptedData : " + encryptedData);

  // Encrypt symmetric key using trustore
  String encryptedKey = keyStoreUtil.encryptKey(symmetrickey, "mykey");
  System.out.println("encryptedKey : " + encryptedKey);



  // Decrypt symmteric key using keystore
  String decryptedKey = keyStoreUtil.decryptKey(encryptedKey, "mykey");
  System.out.println("decryptedKey : " + decryptedKey);

  // Decrypt data using decrypted symetric key

  System.out.println("Decrypted Data : "
    + keyStoreUtil.decryptWithAESKey(encryptedData, decryptedKey));

 }
}


Keytool Utility Class

package symmetric_assymetric_signature;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class KeyStoreUtil {

 private static KeyStore wcTrustStore;
 private static KeyStore visaKeyStore;

 private static String visaKeyStorePass;
 private static String wcTrustStorePassword;
 private static Cipher dCipher;
 private static Cipher eCipher;

 public KeyStoreUtil() throws KeyStoreException, NoSuchAlgorithmException,
   CertificateException, IOException {

  loadTrustStore();
  loadKeyStore();
 }

 private void loadTrustStore() throws KeyStoreException,
   NoSuchAlgorithmException, CertificateException, IOException {
  wcTrustStore = KeyStore.getInstance("JCEKS");
  wcTrustStorePassword = "password";
  // String filePath = wcCryptoConfig.getTrustStoreFileLocation() +
  // File.separator + wcCryptoConfig.getTrustStoreFile();
  FileInputStream stream = new FileInputStream("pptruststore.jck");
  wcTrustStore.load(stream, wcTrustStorePassword.toCharArray());
 }

 private void loadKeyStore() throws KeyStoreException,
   NoSuchAlgorithmException, CertificateException, IOException {
  visaKeyStore = KeyStore.getInstance("JCEKS");
  visaKeyStorePass = "password";
  // String filePath = wcCryptoConfig.getKeyStoreFileLocation() +
  // File.separator + wcCryptoConfig.getKeyStoreFile();
  FileInputStream stream = new FileInputStream("ppkeystore.jck");
  visaKeyStore.load(stream, visaKeyStorePass.toCharArray());

 }

 public String decrypt(String encryptedString, String keyAlias)
   throws KeyStoreException, UnrecoverableKeyException,
   InvalidKeyException, NoSuchAlgorithmException,
   NoSuchPaddingException, IllegalBlockSizeException,
   BadPaddingException {
  Key key = visaKeyStore.getKey(keyAlias, visaKeyStorePass.toCharArray());
  dCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  dCipher.init(Cipher.DECRYPT_MODE, key);
  return new String(dCipher.doFinal(Base64.decodeBase64(encryptedString
    .getBytes())));
 }

 public String encrypt(byte[] inputString, String keyAlias)
   throws KeyStoreException, UnrecoverableKeyException,
   InvalidKeyException, NoSuchAlgorithmException,
   NoSuchPaddingException, IllegalBlockSizeException,
   BadPaddingException {
  Key key = null;
  // Key key = scsTrustStore.getKey(keyAlias, scsKeyStorePass);
  if (wcTrustStore.isCertificateEntry(keyAlias)) {
   Certificate cert = wcTrustStore.getCertificate(keyAlias);
   key = cert.getPublicKey();
  } else {
   key = wcTrustStore.getKey(keyAlias, wcTrustStorePassword
     .toCharArray());
  }

  eCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  eCipher.init(Cipher.ENCRYPT_MODE, key);
  return Base64.encodeBase64String(eCipher.doFinal(inputString));
 }

 public byte[] generateSessionKey() throws NoSuchAlgorithmException {
  KeyGenerator generator = KeyGenerator.getInstance("AES");
  generator.init(128);
  SecretKey key = generator.generateKey();
  System.out.println("key size (in bytes):" + key.getEncoded().length);
  return (key.getEncoded());
 }

 public String encryptWithAESKey(String data, byte[] key)
   throws NoSuchAlgorithmException, NoSuchPaddingException,
   InvalidKeyException, IllegalBlockSizeException,
   BadPaddingException, UnsupportedEncodingException {
  SecretKey secKey = new SecretKeySpec(key, 0, 16, "AES");
  System.out.println("Secret key size (in bytes):"
    + secKey.getEncoded().length);
  Cipher cipher = Cipher.getInstance("AES");
  cipher.init(Cipher.ENCRYPT_MODE, secKey);
  byte[] newData = cipher.doFinal(data.getBytes());
  return Base64.encodeBase64String(newData);
 }

 public String decryptWithAESKey(String inputData, String key)
   throws NoSuchAlgorithmException, NoSuchPaddingException,
   InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  Cipher cipher = Cipher.getInstance("AES");
  SecretKey secKey = new SecretKeySpec(Base64
    .decodeBase64(key.getBytes()), "AES");

  cipher.init(Cipher.DECRYPT_MODE, secKey);
  byte[] newData = cipher.doFinal(Base64.decodeBase64(inputData
    .getBytes()));
  return new String(newData);

 }

 /**
  * 
  * @param encryptedKey
  * @param keyAlias
  * @return
  * @throws KeyStoreException
  * @throws UnrecoverableKeyException
  * @throws InvalidKeyException
  * @throws NoSuchAlgorithmException
  * @throws NoSuchPaddingException
  * @throws IllegalBlockSizeException
  * @throws BadPaddingException
  */
 public String decryptKey(String encryptedKey, String keyAlias)
   throws KeyStoreException, UnrecoverableKeyException,
   InvalidKeyException, NoSuchAlgorithmException,
   NoSuchPaddingException, IllegalBlockSizeException,
   BadPaddingException {
  Key key = visaKeyStore.getKey(keyAlias, visaKeyStorePass.toCharArray());
  dCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  dCipher.init(Cipher.DECRYPT_MODE, key);
  byte[] decryptedKey = dCipher.doFinal(Base64.decodeBase64(encryptedKey
    .getBytes()));
  SecretKey secKey = new SecretKeySpec(decryptedKey, "AES");
  return new String(Base64.encodeBase64String(secKey.getEncoded()));

 }

 /**
  * 
  * @param key
  * @param keyAlias
  * @return
  * @throws KeyStoreException
  * @throws UnrecoverableKeyException
  * @throws InvalidKeyException
  * @throws NoSuchAlgorithmException
  * @throws NoSuchPaddingException
  * @throws IllegalBlockSizeException
  * @throws BadPaddingException
  */
 public String encryptKey(byte[] key, String keyAlias)
   throws KeyStoreException, UnrecoverableKeyException,
   InvalidKeyException, NoSuchAlgorithmException,
   NoSuchPaddingException, IllegalBlockSizeException,
   BadPaddingException {

  return encrypt(key, keyAlias);

 }

}


Get the source code from here

Share the post