0
votes

I want encrypt and decrypt in Android and IOS and PHP.

In android and in PHP using

  • Encryption type: AES
  • Encryption Mode: CBC
  • Padding : PKCS7Padding
  • Hash Algorithm: SHA-256

when i encrypt and decrypt on android it works perfectly. but when I try to decrypt IOS or PHP encrypted String that is in Base64 or Hex2Binary. On android it decrypt string but first 16 character for IOS case and 19 character for PHP code it doest not decrypt showing other characters. I am pasting android code

            // Ignore this line this is for encoding
            //String input = "Congratulation, You've sucessfully decoded!";

            final byte[] iv = new byte[16];
            Arrays.fill(iv, (byte) 0x00);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

            // When I tried with this its gives "pad block corrupted" exception else work as above i told

            /*byte[] key = CommonUtilities.encryptionKey.getBytes("UTF-8");
            System.out.println(key.length);
            MessageDigest sha = MessageDigest.getInstance("SHA-256");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16); // use only first 128 bit
            System.out.println(key.length);
            System.out.println(new String(key,"UTF-8"));
            SecretKeySpec secretKey = new SecretKeySpec(key, "AES");*/

            // encryptionKey = "12345678901234561234567890123456"; Same in IOS and PHP
            SecretKeySpec skeySpec = new SecretKeySpec(CommonUtilities.encryptionKey.getBytes("UTF-8"), "AES");
            Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

            // Ignore these lines these are for encoding
            /*ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] dstBuff = ecipher.doFinal(input.getBytes("UTF-8"));              
            System.out.println("encrypted: " + new String(dstBuff, "UTF-8")); 
            String enbin2hex = com.byte2hex(dstBuff);    
            String en = Base64.encodeToString(dstBuff, Base64.DEFAULT);*/    


            // this is Hex2Binay that IOS gives me to decrypt
            // Original Text: "hello shani how are you doing , Stuck in encryption ?"
            String strBin2Hex = "30BEF4AB063D0D72F91D8D11A7ADEE1B1EC58F67C4D9CC20F59FB56B8B23B7C665198CFF805897BD1AFB82E578AC82C6C18C0EA909E17540D0B95A81E8446168";



            ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] de = ecipher.doFinal(com.hex2Byte(strBin2Hex));  

            //de = removeTrailingNulls(de);
            //int bytesDecryptedAfter = de.length;

            System.out.println("decrypted: " + new String(de, "UTF-8"));
            // Decrypted String "igohj&t`hnh"kkr&are you doing , Stuck in encryption ?"

Here you can see unable to decrypt full string "hello shani how " missing characters.

In IOS using

  • AES256
  • kCCOptionPKCS7Padding

    // IOS encrypt code
    - (NSData *)AES256EncryptWithKey:(NSString *)key {
    char keyPtr[kCCKeySizeAES256+1];     bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
    
    
    
    
    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
     NSUInteger dataLength = [self length];
    
     //See the doc: For block ciphers, the output size will always be less than or
     //equal to the input size plus the size of one block.
     //That's why we need to add the size of one block here
     size_t bufferSize = dataLength + kCCBlockSizeAES128;
     void *buffer = malloc(bufferSize);
    
     size_t numBytesEncrypted = 0;
     CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      "0000000000000000" /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);
     if (cryptStatus == kCCSuccess) {
         //the returned NSData takes ownership of the buffer and will free it on deallocation
         return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
     }
    
     free(buffer); //free the buffer;
     return nil;
     }
    

Any idea what i am doing wrong.

Thanks for you time

1
Arrays.fill(iv, (byte) 0x00) on Android; and "0000000000000000" on iOS are not equal. "0000000000000000" is equal to Arrays.fill(iv, (byte) 0x20) because '0' symbol isn't 0 code.Petro Korienev
Thanks for your reply I tried with 0x20 still same string. it does not give full original textShan Xeeshi
Means problem is in Initialisation Vector. Isn't it?Shan Xeeshi
That's the first issue i see. Probably there are another like: no CBC option in iOS code, algorithm is AES128 but key size is AES256Petro Korienev
I updated code of IOS any idea nowShan Xeeshi

1 Answers

3
votes

I see the issues:

  • Cipher mode (CBC in android code) isn't specified on iOS
  • Algorithm is specified explicitly on iOS (AES128), and not on Android
  • Algorithm does not accord to the key size on iOS 128/256.
  • Initial vector is different

So, instead of

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                  keyPtr, kCCKeySizeAES256,
                                  "0000000000000000" /* initialization vector (optional) */,
                                  [self bytes], dataLength, /* input */
                                  buffer, bufferSize, /* output */
                                  &numBytesEncrypted);
 if (cryptStatus == kCCSuccess) {
     //the returned NSData takes ownership of the buffer and will free it on deallocation
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
 }

I would try

char iv[kCCBlockSizeAES128 + 1]; bzero(iv, sizeof(iv))
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding,
                                  keyPtr, kCCKeySizeAES128,
                                  iv,
                                  [self bytes], dataLength, /* input */
                                  buffer, bufferSize, /* output */
                                  &numBytesEncrypted);
 if (cryptStatus == kCCSuccess) {
     //the returned NSData takes ownership of the buffer and will free it on deallocation
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
 }

Ensure, that Android also uses AES128