iOS using CryptoSwift Encryption AES/CBC/PKCS5PADDING Equivalent encryption with java not working properly

4.5k views Asked by At

I am building a swift application where I need to have AES/CBC/PKCS5PADDING Encryption type. To encrypt API params and decrypt API response.

I have successfully added in android java and that works fine. Now I am trying to implement the same formate type of encryption 'AES/CBC/PKCS5PADDING' cipher size 16 in swift.

Problem: I am getting different encryption result for both android and iOS

Example: String: Hi how are u

Encrypted String for android: +A3p093WWrXU3Ey9i/Lv1Q==

Encrypted String for swift(iOS): Bp23PQX6yaCghvKFTieJDw==

Swift Implementation

import Foundation
import CommonCrypto

func aesEncrypt(key: String, iv: String, message: String) throws -> String{
    let data = message.data(using: .utf8)!
    // let enc = try AES(key: key, iv: iv, padding: .pkcs5).encrypt([UInt8](data))
    let enc = try AES(key: Array(key.utf8), blockMode: CBC(iv: Array(iv.utf8)), padding: .pkcs5).encrypt([UInt8](data))
    let encryptedData = Data(enc)
    return encryptedData.base64EncodedString()
}

func aesDecrypt(key: String, iv: String, message: String) throws -> String {
    let data = NSData(base64Encoded: message, options: NSData.Base64DecodingOptions(rawValue: 0))!
    let dec = try AES(key: key, iv: iv, padding: .pkcs5).decrypt([UInt8](data))
    let decryptedData = Data(dec)
    return String(bytes: decryptedData.bytes, encoding: .utf8) ?? "Could not decrypt"
}

Android Implementation

package com.example.uribanew.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EncrytData {

private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";

private static int CIPHER_KEY_LEN = 16; //128 bits

private static String KEY   = ""; // key to use should be 16 bytes long (128 bits)
private static String IV    = ""; // initialization vector

/**
 * Encrypt data using AES Cipher (CBC) with 128 bit key
 *
 * @param data - data to encrypt
 * @return encryptedData data in base64 encoding with iv attached at end after a :
 */
public static String encrypt(String data) {

    try {
        IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
        SecretKeySpec secretKey = new SecretKeySpec(fixKey(KEY).getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance(EncrytData.CIPHER_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

        byte[] encryptedData = cipher.doFinal((data.getBytes()));

        String encryptedDataInBase64 = android.util.Base64.encodeToString(encryptedData, android.util.Base64.DEFAULT); //Base64.getEncoder().encodeToString(encryptedData);

        return encryptedDataInBase64;

    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

private static String fixKey(String key) {

    if (key.length() < EncrytData.CIPHER_KEY_LEN) {
        int numPad = EncrytData.CIPHER_KEY_LEN - key.length();

        for (int i = 0; i < numPad; i++) {
            key += "0"; //0 pad to len 16 bytes
        }

        return key;

    }

    if (key.length() > EncrytData.CIPHER_KEY_LEN) {
        return key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
    }

    return key;
}

/**
 * Decrypt data using AES Cipher (CBC) with 128 bit key
 *
 * @param data - encrypted data with iv at the end separate by :
 * @return decrypted data string
 */

public static String decrypt(String data) {

    try {
        IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
        // SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
        SecretKeySpec secretKey = new SecretKeySpec(fixKey(KEY).getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance(EncrytData.CIPHER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

        byte[] decodedEncryptedData = android.util.Base64.decode(data, android.util.Base64.DEFAULT); //Base64.getDecoder().decode(parts[0]);

        byte[] original = cipher.doFinal(decodedEncryptedData);

        return new String(original);
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
}

Please let me know why with the same encryption type I am getting different encrypted string for both android and iOS. Let me know what I am doing wrong

0

There are 0 answers