Tuesday, 2 June 2015

Symmetric Key Encryption between JAVA and IOS

There has been a exponential increase in REST services implementation between IOS/Android devices and Java Middleware, This has become the solution architecture for most applications which provide support on IOS/Android devices and also provide interface on web using java web application.



To make the communication secure it is necessary that this REST messages are made secure. This can be achieved using symmetric encryption mechanism.





Previous posts of encryption/decryption with symmetric and asymmetric key, works well when both applications are JAVA based.

When dealing with symmetric key encryption in my previous post, I have used the symmetric key which is generated by KeyGenerator class. Generating the same symmetric key in IOS and Android may not be possible. For that reason we can use a symmetric key which is custom and self generated. Lets take a look at the example below in Java which encrypts and decrypts data using self defined symmetric key

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

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


public class SymmetricKey {

  private static final byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

  
  public static void main(String[] args) throws Exception {

  
    //16 digit custom key
    String symmetricKey = "1234567890123456";
   
   System.out.println("key : "+symmetricKey);
   
   //Encrypt Data
   String encryptedData = encryptWithAESKey("asd", symmetricKey);
   
   System.out.println("Encrypted Data : " + encryptedData);
   
   //Decrypt Data
   System.out.println("Decrypted Data : " +decryptWithAESKey(encryptedData, symmetricKey));

  }

Encrypt data using the Symmetric Key
  public static String encryptWithAESKey(String data, String key) throws 
    NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
    UnsupportedEncodingException, InvalidAlgorithmParameterException {

   // Generate symmetric key
   SecretKey secKey = new SecretKeySpec(key.getBytes("UTF-8"),"AES");

   Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
   
   // Encrypt data using the symmetric Key
   cipher.init(Cipher.ENCRYPT_MODE, secKey, new IvParameterSpec(iv));
   byte[] newData = cipher.doFinal(data.getBytes());
   
   return Base64.encodeBase64String(newData);
  }

This above encrypted data can be send from a JAVA web application or a Android device to a IOS or Android device using REST service.

IOS/Andriod devices can then decrypt the data.

Note: The IOS and Android devices should be aware of the symmetric key used (asd)

Below is the code to decrypt the same in Android device.

Decrypt data using the Symmetric Key

  public static String decryptWithAESKey(String inputData, String key) throws
    NoSuchAlgorithmException,
    NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
    BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {

   Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

   // Generate symmetric key
   SecretKey secKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

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

  }
}

Above code uses custom symmetric key which is 16 byte that is 128 bit.

To run this program you will need common-codec jar.

The output is given below:

key : 1234567890123456
Encrypted Data : /NQ0CPduJmT340u95NowDA==
Decrypted Data : asd


Assymetric Key Ecnryption :
The problem here is that both the parties the one sending the encrypted data and one decrypting the data should be aware about the common symmetric key String. "asd" in this case

And if that String is misplaced or lost any application will be able to decrypt the data being transmitted. So the symmetric key used here is not secured.

Another more secured option would be to combine symmetric and asymmetric key encryption.

First the sender and receiver will generate asymmetric key (Public and Private) pair. The sender which could be a IOS or Android device should have the Public Key. The sender will generate a random number and encrypt it using the public key and send it to the receiver. The receiver will than decrypt the key using the private key. 

So now both parties will have decrypted symmetric key string.

Then the sender can use the above code to encrypt the data using symmetric key and send it to receiver. The receiver will than decrypt data with symmetric key. The receiver now can also send encrypted data back to the sender using the same symmetric key.



Below is the IOS code to encrypt a random String using Public Key. It uses FbEncrypt Library.

NSString *symmetricKey=[self generateRandomKey];
    NSString *strCreateXmlForKey=[NSString stringWithFormat:@"45678123I%@",symmetricKey];
    [User sharedInstance].privateSecKey=symmetricKey;
    
    NSString *certPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"crt"];
    
    NSData *certificateData = [[NSData alloc] initWithContentsOfFile:certPath];
    CFDataRef certDataRef =(__bridge CFDataRef)certificateData;
    SecCertificateRef myCertificate = SecCertificateCreateWithData(NULL, certDataRef);

    
    if(myCertificate ==nil || myCertificate ==NULL)
    {
        return;
    }
    
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;
    SecTrustCreateWithCertificates(myCertificate, myPolicy, &myTrust);
    SecKeyRef publicKey = SecTrustCopyPublicKey(myTrust);
    
    NSData *dataSymmetricKey = [strCreateXmlForKey dataUsingEncoding:NSUTF8StringEncoding];
    const void *bytesSymmetricKey = [dataSymmetricKey bytes];
    
    uint8_t *symmetricKeyText = (uint8_t*)bytesSymmetricKey;
    uint8_t symmetricCipherText[1024];
    size_t  symmetricCipherLength = 1024;
    SecKeyEncrypt(publicKey,
                                    kSecPaddingPKCS1,
                                    symmetricKeyText,
                                    strlen( (char*)symmetricKeyText ) + 1,
                                    symmetricCipherText,
                                    &symmetricCipherLength);



For more on Encryption/Decryption, read below blogs. 

No comments:

Post a Comment

Share the post