Tuesday, 1 July 2014

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.

No comments:

Post a Comment