Tuesday 1 July 2014

Tech talk...Cryptography or Encryption [Using keys]

Previous post covered how to generate keys and keystores.
This post shows how to load the private key from keystore, public key from truststore and then use them for data decryption/encryption respectively:

Load keystore: (keystorePass = password of the keystore)

KeyStore keyStore= KeyStore.getInstance("JKS");
FileInputStream fin1 = new FileInputStream("D:\\MySecurityKeys\MyKeyStore.jks");
keyStore.load(fin1, keystorePass.toCharArray());

Load the truststore: (truststorePass = password of the truststore)

KeyStore trustStore= KeyStore.getInstance("JKS");
FileInputStream fin2= new FileInputStream("D:\\MySecurityKeys\MyTrustStore.jks");
trustStore.load(fin2, truststorePass.toCharArray());

Load private key from the keystore:

Enumeration<String> aliases = keyStore.aliases();
String alias = aliases.nextElement();
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
                    new KeyStore.PasswordProtection(keystorePass.toCharArray()));
PrivateKey privateKey = keyEnt.getPrivateKey();

Load public key from the truststore:

aliases = trustStore.aliases();
alias = aliases.nextElement();
KeyStore.TrustedCertificateEntry keyEnt = (KeyStore.TrustedCertificateEntry) trustStore.getEntry(alias, null);
PublicKey publicKey = keyEnt.getTrustedCertificate().getPublicKey();

Initializing ciphers:

//the public and private keys use encryption and decryption ciphers respectively for encrypting //and decrypting the data. So, first, the ciphers need to be initiatized:
//Initializing the encryption cipher:
Cipher encryptionCipher = Cipher.getInstance("RSA");
                        encryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey);/Initializing the decryption cipher:
Cipher  decryptionCipher = Cipher.getInstance("RSA");
                        decryptionCipher.init(Cipher.ENCRYPT_MODE, privateKey);

Encryption of data:


    public byte[] encryptData(byte[] input)                throws IllegalBlockSizeException,BadPaddingException   {
        byte[] encryptedData = null;
        encryptedData = encryptionCipher.doFinal(input);
        return new Base64().encode(encryptedData);
    }

Decryption of data:


    public byte[] decryptData(byte[] inputData) throws IllegalBlockSizeException , BadPaddingException {
        byte[] decryptedData = null;
        byte[] inputBytes = new Base64().decode(inputData);
        decryptedData = decryptionCipher.doFinal(inputBytes);
        return decryptedData;
    }

Note:The Base64 encoding decoding is done to preserve the context of data when data is converted from byte to string and string to byte and encryption/decryption is done over the data. For example, if a String "Hello" were to be encrypted using the above method, the caller would say String encryptedData = new String( encryptData("Hello".getBytes()) and when decrypting back the data, he would say String decrytedData = new String(decryptData(encryptedData.getBytes()). Here, encryptedData and decryptedData are two new Strings, the final value expected on decrypting the data is "Hello". This might not be the case if proper encoding is not used. So, to preserve the value of actual data through this process, a base 64 encoding has been used here along with the encryption.

Tech talk...Cryptography or Encryption [Generating keys]

The following code snippets in java show how to generate a private and public key pair for asymmetric cryptography and how to add them to the keystore and truststore respectively:

An enum to help differentiate public and private keys:

public enum KEY_TYPE {
PUBLIC, PRIVATE
}


 Code snippet to generate the public and private keys:


  KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance("RSA");
  KeyPair keyPair = keyPairGenerator.generateKeyPair();
  KeyManager keyGenerator = new KeyManager();

  // generate a public-private key pair
  PublicKey publicKey = (PublicKey) keyGenerator.generateAndStoreKey(
"MyPublicKey", KEY_TYPE.PUBLIC, keyPair);
  PrivateKey privateKey = (PrivateKey) keyGenerator.generateAndStoreKey(
"MyPrivateKey", KEY_TYPE.PRIVATE, keyPair);


Storing the keys into files:

function generateAndStoreKey:
This function would store the keys into files:

private Key generateAndStoreKey(String keyName, KEY_TYPE keyType,
KeyPair keyPair) throws IOException {
Key key = null;
switch (keyType) {
case PUBLIC:
key = keyPair.getPublic();
break;
case PRIVATE:
key = keyPair.getPrivate();
break;
}
byte[] keyBytes = key.getEncoded();
File keyFile = new File("D:\\MySecurityKeys\" + keyName);
FileOutputStream fos = new FileOutputStream(keyFile);
fos.write(keyBytes);
fos.flush();
fos.close();

return key;
}


Adding private key to keystore:

A private key, once generated, can be added to the keystore. For this, first the keystore needs to be loaded into memory. Below is the code snippet for loading a keystore file, given its location:


FileInputStream fIn = new FileInputStream("D:\\MySecurityKeys\MyKeyStore.jks");
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, KEYSTORE_PASSWORD.toCharArray());

Once the keystore is loaded, the private key can be added into it as follows:


//Convert the private key to byte array, if the key is stored in the form of file, then 
//read the file and convert it to byte array (as is the case from our private key generation code //above). If it is available in any other format, like a string, then also, the string should be //converted to byte array.
File privateKeyFile = new File("D:\\MySecurityKeys\MyPrivtekey");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
privateKeyFile));
byte[] privKeyBytes = new byte[(int) privateKeyFile.length()];
bis.read(privKeyBytes);
bis.close();

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory
.generatePrivate(new PKCS8EncodedKeySpec(privKeyBytes));

                //generate a certificate chain out of the private key  
File certFile = new File("D:\\MySecurityKeys\MyCertificateFile");
FileInputStream fin = new FileInputStream(certFile);
CertificateFactory factory = CertificateFactory.getInstance(CERTIFICATE_TYPE);
Certificate generateCertificate = factory.generateCertificate(fin);
Certificate[] chain = new Certificate[1];
chain[0] = generateCertificate;
                
                //add the entry to the keystore
keyStore.setKeyEntry("MyPrivateKey", privateKey,
PRIVATE_KEY_PASSWORD.toCharArray(), chain);
                //store the new keystore to the file system
keyStore.store(new FileOutputStream(new File("D:\\MySecurityKeys\MyKeyStore.jks")), KEYSTORE_PASSWORD.toCharArray());
System.out.println("Added private key to keystore");
}

Adding public key to truststore:

A public key can be added to the truststore as follows:
A public key needs to be embedded inside a certificate to be stored in truststore. Following code snippet shows how to do it:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

X509Certificate[] serverChain = new X509Certificate[1];
X509V3CertificateGenerator serverCertGen = new X509V3CertificateGenerator();
X500Principal serverSubjectName = new X500Principal("CN=neha verma");
                String RANDOM = "123456789";
serverCertGen.setSerialNumber(new BigInteger(RANDOM));

serverCertGen.setIssuerDN(serverSubjectName);
serverCertGen.setNotBefore(new Date());
serverCertGen.setNotAfter(new Date());
serverCertGen.setSubjectDN(serverSubjectName);
serverCertGen.setPublicKey(publicKey);
                String CERTIFICATE_SIGNATURE_ALGO = "MD5WithRSA";
serverCertGen.setSignatureAlgorithm(CERTIFICATE_SIGNATURE_ALGO);
serverCertGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
new SubjectKeyIdentifierStructure(publicKey));
serverChain[0] = serverCertGen
.generateX509Certificate(privateKey, "BC"); // note: private key
// of CA
byte[] encodedCert = serverChain[0].getEncoded();
File certFile = new File("D:\\MySecurityKeys\MyCertificate.cert");
FileOutputStream out = new FileOutputStream(certFile);
out.write(encodedCert);
out.flush();
out.close();
}

The certificate file can be added to the truststore from command line as follows:
C:\ProgramFiles\Java\jdk1.7.0_40\bin>keytool -import -file D:\\MySecurityKeys\MyCertificate.cert -alias MyCertificate
  -keystore MyTrustStore

To see how to load and use the public key and private key generated above, you can refer to next post.

Tech talk...Cryptography or Encryption [Generating & Using Keystore/Truststore]

Keystore is used to hold the private keys.
In java, keystore can be generated from the command prompt.
This is the oracle documentation for doing the same:
http://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html

You need to go to the jre bin folder . Inside that the executable 'keytool' should be present. this is used to generate the keystore.
Here's the command to generate the keystore

keytool -keystore <keystore name> -genkey -alias <keystore-alias>

example:

keytool -keystore MyKeyStore -genkey -alias MyKeyStore

Once you enter the above command, you would be prompted for certain inputs, keep providing the inputs and finally the keystore file would be generated with a .jks extension in the bin folder.
From here, you can copy the keystore file anywhere.

An example of what all would be entered once the above command is entered:


Enter keystore password: javacaps
What is your first and last name?
[Unknown]: neha neha
What is the name of your organizational unit?
[Unknown]: Development
what is the name of your organization?
[Unknown]: self
What is the name of your City or Locality?
[Unknown]: Bangalore
What is the name of your State or Province?
[Unknown]: Karnataka
What is the two-letter country code for this unit?
[Unknown]: India
Is<CN=development.self.com, OU=Development, O=self, L=Bangalore, ST=Karnataka, 
C=India> correct?
[no]: yes

Enter key password for <MyKeyStore>
    (RETURN if same as keystore password):

Once the keystore is generated, either keys can be added to it using command prompt or using java program.To add keys using command prompt, you can further refer to the oracle documentation here: http://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html I used java program to generate and add private keys to the keystore. Refer to the next post for seeing example of how to generate Asymmetric key pairs and add them to the keystore/truststore using java.


The key store that holds the public key is generally called a truststore. A truststore can be generated in the same way as demonstrated above. For example:

keytool -keystore MyTrustStore -genkey -alias MyTrustStore