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