Friday, December 17, 2010

How to store a SecretKey in Java

This demo shows how to maintain a secret (symmetric) key in a java class. This key can then be used for encrypting / decrypting data that should be secret outside that class but must be transported. The Cipher used here is DESede, other ciphers could be used as well.

When using a KeyGenerator each time the class is initialized, the encrypted messages can not be read by a another process. Therefore the SecretKey is generated once, and then revived when the class is loaded.

** IMPORTANT **
Note that the SecretKey is now in your java source file, and will be in the compilation result. Your secrets can be read by anyone who can access your source or your binaries.


Generating the key

SecretKey key = KeyGenerator.getInstance("DESede").generateKey();
BigInteger num = new BigInteger(1, key.getEncoded());
System.out.println("Key: "+ num.toString())


Copy the resulting string (a big number)


Making the SecretKey available


public class YourClass {
private static String algorithm = "DESede";
private static byte[] encodedKey = new BigInteger("[[[[ Post the big number here ]]]]", 16).toByteArray();
}


Using the encoded SecretKey


DESedeKeySpec keySpec = new DESedeKeySpec(encodedKey);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
SecretKey key = keyFactory.generateSecret(keySpec);

Cipher cipher = Cipher.getInstance(algorithm);
Cipher decipher = Cipher.getInstance(algorithm);

cipher.init(Cipher.ENCRYPT_MODE, key);
decipher.init(Cipher.DECRYPT_MODE, key);


Encrypting and decrypting


String message = "Hello World";
byte[] encryptedBytes = cipher.doFinal(message.getBytes());
String encryptedMessage = Base64.encode(encryptedBytes);

// Transport the base64 string, for example over http

byte[] messageToDecrypt = Base64.decode(encryptedMessage);
byte[] decryptedBytes = decipher.doFinal(messageToDecrypt);
String decryptedMessage = new String(decryptedBytes);
System.out.println(decryptedMessage);


References



1 comment:

  1. i get a number format exception when I am trying to conver the big integrer back to SecretKey
    private static byte[] encodedKey = new BigInteger("[[[[ Post the big number here ]]]]", 16).toByteArray();

    ReplyDelete