The requirement – I have an application which is installed in the customer machine. This application will generate log file which I need in case I need to do debugging. I do not want the customer to view the content of the log file and mess around with it.
To do this, I need to use symmetric (e.g. AES, DES..) and asymmetric (e.g. RSA) encryptions. Symmetric encryption alone is not enough as Java program can be easily decompiled and the secret key can be easily viewed. Using asymmetric algorithm is also not efficient and slow for large amount of data.
- RSA encryption is a very time consuming algorithm, and should never be used to encrypt large amounts of data.
- The typical use for RSA is to encrypt symmetric algorithm session keys.
In my case, instead of encrypting the file with RSA,
On the client,
- I generate a secret key for a (much faster) symmetric encryption algorithm, such as AES
- Encrypt the data using AES, then use RSA to encrypt the AES key using the public key generated beforehand.
- Send both the encrypted session key and the encrypted data to the server.
On the server,
- Decrypt the session key with the corresponding RSA private key, and then use it to decrypt the AES encrypted data.
So here goes the code….
First, I generate the public and private keys for RSA
// Generate public and private keys RSAKeyManager keyMan = new RSAKeyManager(); keyMan.generateKeyPair(); RSAPublicKey publicKey = keyMan.getPublicKey(); RSAPrivateKey privateKey = keyMan.getPrivateKey(); String modulus = keyMan.getModulusAsHex(); String exponent = keyMan.getPrivateExponentAsHex(); // Store module and exponent in a secured file. // Pass modulus to the client
I stored the private key in my server and distribute the public key in my client application.
In the client application, I use AES to encrypt the log file content
// AES to encrypt the log file long startTime = System.currentTimeMillis(); String logFile = readLogFile(FOLDER_PATH + "sample.txt"); AESUtils aesUtils = new AESUtils(); byte secretKey = aesUtils.generateSecretKey(); String hexSecretKey = aesUtils.getSecretyKey(); String encryptedHexContent = new String(Hex.encodeHex(aesUtils.encrypt(logFile))); System.out.println( "Encrypted content in hex: " + encryptedHexContent); long endTime = System.currentTimeMillis(); System.out.println( "Encryption time: " + (endTime - startTime) / 1000);
Then save the encrypted secret key and content in text files and send over
// Should save the hexSecretyKey // and encrypted hex content in text file RSAEncryptor encryptor = new RSAEncryptor(modulus); String encryptedHexSecretKey = encryptor.encryptString(hexSecretKey); // Store encryptedHexSecretKey and // encryptedHexSecretKey in files
On the server side, decrypt the secret key using the private key stored, and then use the secret key to decode the content
// On our side startTime = System.currentTimeMillis(); // Decrypt the RSA encrypted secrety key using our Private Key RSADecryptor decryptor = new RSADecryptor(modulus, exponent); hexSecretKey = decryptor.decryptText(encryptedHexSecretKey); // Un-hex the hex secrety key secretKey = Hex.decodeHex(hexSecretKey.toCharArray()); // Now we have the original secret key, decode the content // Un-hex the content byte encryptedContent = Hex.decodeHex(encryptedHexContent.toCharArray()); aesUtils.setSecretKey(secretKey); byte originalContent = aesUtils.decrypt(encryptedContent); System.out.println( "Original content: " + new String(originalContent)); endTime = System.currentTimeMillis(); System.out.println( "Decryption time: " + (endTime - startTime) / 1000);
NOTE: RSA encryption classes are modified from http://owlroost.com/wpblog/quick-guide-to-rsa-encryption-and-decryption-using-the-jce/