1

I'm trying to decrypt a string in swift that was encrypted by a third party using AES ECB with a 256bit key and a 128bit initialization vector.

This is my swift code:

struct AES {

    private let key: Data
    private let iv: Data

    init?(key: String, iv: String) {
        guard key.count == kCCKeySizeAES128 || key.count == kCCKeySizeAES256, let keyData = key.data(using: .utf8) else {
            debugPrint("Error: Failed to set a key.")
            return nil
        }
    
        guard iv.count == kCCBlockSizeAES128, let ivData = iv.data(using: .utf8) else {
            debugPrint("Error: Failed to set an initial vector.")
            return nil
        }
    
    
        self.key = keyData
        self.iv  = ivData
    }

    func encrypt(string: String) -> Data? {
        return crypt(data: string.data(using: .utf8), option: CCOperation(kCCEncrypt))
    }

    func decrypt(data: Data?) -> String? {
        guard let decryptedData = crypt(data: data, option: CCOperation(kCCDecrypt)) else {
            return nil
        }
        return String(decoding: decryptedData, as: UTF8.self) // LINE XY
    }

    func crypt(data: Data?, option: CCOperation) -> Data? {
        guard let data = data else { return nil }
    
        let cryptLength = data.count + key.count
        var cryptData   = Data(count: cryptLength)
    
        var bytesLength = Int(0)
    
        let status = cryptData.withUnsafeMutableBytes { cryptBytes in
            data.withUnsafeBytes { dataBytes in
                iv.withUnsafeBytes { ivBytes in
                    key.withUnsafeBytes { keyBytes in
                    CCCrypt(option, CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), keyBytes.baseAddress, key.count, ivBytes.baseAddress, dataBytes.baseAddress, data.count, cryptBytes.baseAddress, cryptLength, &bytesLength)
                    }
                }
            }
        }
    
        guard Int32(status) == Int32(kCCSuccess) else {
            debugPrint("Error: Failed to crypt data. Status \(status)")
            return nil
        }
    
        cryptData.removeSubrange(bytesLength..<cryptData.count)
        return cryptData
    }
}

Example secrets im using:

    let key256   = "gVkYp3s6v9y$B&E)H@MbQeThWmZq4t7w"   // 32 bytes for AES256
    let iv       = "v8y/B?E(H+MbQeTh"                   // 16 bytes for initialization vector

This snippet works:

    let content = "Hello, world!"
    
    let aes256 = AES(key: key256, iv: iv)
    let encrypted = aes256?.encrypt(string: content)
    let result = aes256?.decrypt(data: encrypted) // works fine
    
    assert(content == result, "not equal!")

Now im trying to decrypt my third party string, that was encrypted using this dart package with the same settings:

    guard let fileUrl = Bundle.main.url(forResource: "inputBase64", withExtension: "txt") else { fatalError() }
    
    let base64Content = try String(contentsOf: fileUrl, encoding: .utf8)
    let data = Data(base64Encoded: base64Content, options: .ignoreUnknownCharacters)
    let result = aes256?.decrypt(data: data) // crashes my xcode

This freezes my entire xcode window as soon as it reaches the line i marked with // LINE XY in the first code block.

What could cause this crash and are there any other solutions? Thanks!

Jannik
  • 635
  • 1
  • 6
  • 14
  • I'm running into the same problem, would be great if someone could help! – KNV Aug 03 '22 at 05:47
  • This appears to be an incomaptability issue between Swift and Dart code (since encryption and decryption with the Swift code works). So obviously the Dart code is needed to understand the reason for the incompatibility. Your information *...that was encrypted using this dart package...* is not enough because there are many ways to implement an encryption. – Topaco Aug 03 '22 at 10:30
  • It would also be helpful if, for a given plaintext and key, you post the ciphertext created with the Dart code and the ciphertext created with the Swift code. – Topaco Aug 03 '22 at 10:32

0 Answers0