Making AES Encryption in Swift similar to Android

72 views Asked by At

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}}

0

There are 0 answers