Encryption of password generated in Android app and Java back end are same however in iOS I have tried using CryptoSwift and CommonCrypto and other code available but didn't get desired output matching with other two and hence posting the question. Please let me know any similar counter code/class is there in iOS for generating same output or Let me know whats missing in my code. Thanks in advance.
Here is Android Code
private static byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8 };
private static final Integer ITERATRION_COUNT = 65536;
private static final Integer KEY_LENGTH = 256;
public static String encrypt(String strToEncrypt, String password) throws Exception {
String encryptedText = null;
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATRION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
encryptedText= Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
}
}catch (Exception e) {
e.printStackTrace();
return null;
}
return encryptedText;
}
I also took help from ChatGPT but the code converted encrypted string is only half matched.
iOS Code –
func encryptString(strToEncrypt: String, password: String) -> String? {
let salt: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8]
let saltData = Data(salt)
let passwordData = password.data(using: .utf8)!
// Key derivation using PBKDF2
var key = Data(repeating: 0, count: kCCKeySizeAES256)
let keyLength = key.count
let keyDerivationResult = key.withUnsafeMutableBytes { keyBytes in
saltData.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password, passwordData.count,
saltBytes.baseAddress!.assumingMemoryBound(to: UInt8.self), saltData.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
65536, // rounds
keyBytes.baseAddress!.assumingMemoryBound(to: UInt8.self), keyLength
)
}
}
guard keyDerivationResult == kCCSuccess else { return nil }
// Encryption
guard let dataToEncrypt = strToEncrypt.data(using: .utf8) else { return nil }
let algorithm = CCAlgorithm(kCCAlgorithmAES)
let options = CCOptions(kCCOptionPKCS7Padding)
var numBytesEncrypted = 0
var encryptedData = Data(count: dataToEncrypt.count + kCCBlockSizeAES128)
let encryptedDataLength = encryptedData.count
let cryptStatus = encryptedData.withUnsafeMutableBytes { encryptedBytes in
dataToEncrypt.withUnsafeBytes { dataToEncryptBytes in
key.withUnsafeBytes { keyBytes in
CCCrypt(CCOperation(kCCEncrypt), algorithm, options,
keyBytes.baseAddress, key.count, nil,
dataToEncryptBytes.baseAddress, dataToEncrypt.count,
encryptedBytes.baseAddress, encryptedDataLength,
&numBytesEncrypted)
}
}
}
guard cryptStatus == kCCSuccess else { return nil }
encryptedData.removeSubrange(numBytesEncrypted..<encryptedData.count)
// Convert to Base64
return encryptedData.base64EncodedString()
}
The expected result is:
Uname / Pwd: [email protected] / test123
{"username":"EwYSS++oSbP1Kj7dPjd9wAqVK4FRvxfte29eUVRyzGI=","password":"jUJ/qlcGOOz/9USYQKNnOQ==","isDebug":true}}