1
votes

Guide me on this. I am facing problem with decryption of string which is encrypted by iOS "AES/CBC/PKCS7Padding". It throws exception. I want to decrypt string in android, which is encrypted in ios.

In Android i am following this structure:

For Example: 
  String text = "rzp_test_DezQO1BVMXhkZY";
  String key = "5b0904cfada01b8182bcc029b928244d"; // secret key - 128 bit key
  String iv_key ="c999cbd1f130db1d";

I want to encrypt and decrypt 'text' string mentioned above. If i do encryption and decryption from Android only. then its working fine. but if i tried to decrypt key which is encrypted in ios then it throws errors.

// Create key and cipher

Cipher dcipher, d1cipher;

      IvParameterSpec ivSpec = new IvParameterSpec(iv_key.getBytes());
      Key aesKey = new SecretKeySpec(key.getBytes(), "AES"); 

      ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
      dcipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

      ecipher.init(ENCRYPT_MODE, aesKey, ivSpec);
      dcipher.init(DECRYPT_MODE, aesKey, ivSpec);

Encryption Algo:

  public String encrypt(String str) throws Exception {
        // Encode the string into bytes using utf-8
        byte[] utf8 = str.getBytes("UTF8");

        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);

        // Encode bytes to base64 to get a string
        return Base64.encodeToString(enc, Base64.DEFAULT);
    }

Decryption Algo:

 public String decrypt(String str) throws Exception {
        // Decode base64 to get bytes
        String decrypted = "";
        try {
            byte[] dec = Base64.decode(str, Base64.DEFAULT);

            byte[] utf8 = dcipher.doFinal(dec);

            // Decode using utf-8
            decrypted = new String(utf8, "UTF8").trim();

        } catch (Exception e) {


            e.printStackTrace();
        }

        return decrypted;
    }

Its working fine in Android for both Encryption and Decryption. Check with this:

String encrypted = encrypt(text);
System.out.println("Encrypted String: " + encrypted);

String decrypted = decrypt(encrypted);
System.out.println("Decrypted String: " + decrypted);

Problem is with decrypting below encrypted string from ios, This Throws error:

   String decrypted1 = decrypt("c7076c78fc5d9d92c1d86c1500dcc0366ddf1b6e32df00ceadc911239935460d");
   System.out.println("Decrypted String1: " + decrypted1);

Error is:

W/System.err: javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
W/System.err:     at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
W/System.err:     at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:570)
W/System.err:     at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:351)
W/System.err:     at javax.crypto.Cipher.doFinal(Cipher.java:1741)
W/System.err:     at com.example.aesencryption.Activities.MainActivity1.decrypt(MainActivity1.java:178)

Anyone can please guide me on this??

In IOS:

Following functions are used.

func aesEncrypt() -> String {

        let iv: [UInt8] = Array(AES_IV.utf8)
        let key: [UInt8] = Array(AES_SECRET.utf8)

        do{
            let encrypted = try AES (key: key, blockMode: CBC(iv: iv)).encrypt([UInt8](self.data(using: .utf8)!))
            return Data(encrypted).base64EncodedString()
        }
        catch{
            print("error on encrypting data ")
            return ""
        }

    }

    func aesDecrypt() -> String {

        let iv: [UInt8] = Array(AES_IV.utf8)
        let key: [UInt8] = Array(AES_SECRET.utf8)
        do{
            guard let data = Data(base64Encoded: self) else { return "" }
            let decrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).decrypt([UInt8](data))
            return String(bytes: decrypted, encoding: .utf8) ?? self
        }
        catch{
            print("error on encrypting data ")
            return ""
        }

    }
1
Is iOS using the same PKCS7Padding to encrypt?Rodrigo Queiroz
The iOS ciphertext is hexadecimal encoded. However, decrypt in the Android code expects a Base64 encoded string (because encrypt Base64 encodes the ciphertext). So you have two possibilities: Either you convert the iOS-ciphertext to Base64, e.g. Base64.encodeToString(hexStringToByteArray("c707...460d"), Base64.DEFAULT); with hexStringToByteArray from here or you modify the Android code accordingly (so that also a hexadecimal encoding is applied).Topaco
Also, AES-256 is used (and not AES-128).Topaco
@RodrigoQueiroz I added iOS Algorithm. please have a look.Bhoomika Patel
@topaco, I added iOS Algorithm. please have a look.Bhoomika Patel

1 Answers

0
votes

I got real string by using following method.

  public static String decryptKey(String key_id) {
            // Decode base64 to get bytes
            String decrypted = "";
            try {

                Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

                dcipher.init(DECRYPT_MODE, aesKey, ivSpec);

                byte[] utf8 = dcipher.doFinal(hexToBytes(key_id));

                // Decode using utf-8
                decrypted = new String(utf8, "UTF8").trim();

            } catch (Exception e) {


                e.printStackTrace();
            }

            return decrypted;
        }

     public static byte[] hexToBytes(String str) {
            if (str == null) {
                return null;
            } else if (str.length() < 2) {
                return null;
            } else {
                int len = str.length() / 2;
                byte[] buffer = new byte[len];
                for (int i = 0; i < len; i++) {
                    buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
                }
                return buffer;
            }
        }