Search code examples
iosswiftencryptionaescryptoswift

Could not decrypt a base64String using CryptoSwift


String for encryption "secret"

after encryption "64c2VjcmV0"

this is the code that works properly

    let inputNSData: NSData = input.dataUsingEncoding(NSUTF8StringEncoding)!
    let inputBytes: [UInt8] = inputNSData.arrayOfBytes()
    let key: [UInt8] = self.generateArray("secret0key000000") //16
    let iv: [UInt8] = self.generateArray("0000000000000000")  //16
    do {
        let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).encrypt(inputBytes, padding: PKCS7())    
        let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted, padding: PKCS7())   
        let decryptNsData: NSData = NSData(bytes: decrypted, length: decrypted.count)     
        let c = decryptNsData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
        let decryptedString: String = NSString(data: decryptNsData, encoding: NSUTF8StringEncoding) as! String
        print("String after decryption\t\(decryptedString)")
    } catch {
        // some error
    }

but i could not decrypt by using the same key and iv I am getting fatal error: unexpectedly found nil while unwrapping an Optional value for the encrypted string

    let key: [UInt8] = self.generateArray("secret0key000000") //16
    let iv: [UInt8] = self.generateArray("0000000000000000")  //16
    let input: String = "64c2VjcmV0"

    var encryptedStrData = NSData(base64EncodedString: input, options: NSDataBase64DecodingOptions())!
    let inputBytes: [UInt8] = encryptedStrData.arrayOfBytes()
    print("String in uint8\(inputBytes)")
    //var keyData = keyStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    //var ivData:NSData = ivStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    do{
    let decryptedTryData = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(inputBytes)
        print(decryptedTryData)
    }
    catch{

    }

I am getting fatal error: unexpectedly found nil while unwrapping an Optional value for the encrypted string


Solution

  • You are using Base64 when it is not necessary, only Base64 encode non string data.

    Here is the first test code:

    let inputBytes: [UInt8] = Array("secret".utf8)
    let key:        [UInt8] = Array("secret0key000000".utf8) //16
    let iv:         [UInt8] = Array("0000000000000000".utf8)  //16
    
    var encryptedBase64 = ""
    do {
        let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).encrypt(inputBytes, padding: PKCS7())
        let encryptedNSData = NSData(bytes: encrypted, length: encrypted.count)
        encryptedBase64 = encryptedNSData.base64EncodedStringWithOptions([])
    
        let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted, padding: PKCS7())
        let result = String(bytes: decrypted, encoding: NSUTF8StringEncoding)!
        print("result\t\(result )")
    } catch {
        // some error
    }
    print("encryptedBase64: \(encryptedBase64)")
    

    Output:

    result: secret
    encryptedBase64: 0OCxa0yJszq9MvkrWjn3wg==

    let encryptedData = NSData(base64EncodedString: encryptedBase64, options:[])!
    print("decodedData: \(encryptedData)")
    let encrypted = Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>(encryptedData.bytes), count: encryptedData.length))
    
    do {
        let decryptedData = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted)
        let decryptedString = String(bytes: decryptedData, encoding: NSUTF8StringEncoding)!
        print("decryptedString: \(decryptedString)")
    
    }
    catch{
        // some error
    }
    

    Output:

    decryptedString: secret

    Notes:

    Don't use CryptoSwift, it does not use the build-in encryption hardware and is 400 to 1000 times slower than the Apple Security.framework Common Crypto. It is also not well vetted and used non-certified encryption code.

    Don't use a string directly as the key, it is not secure. Instead derive a key from the string using PBKDK2 (Password Based Key Derivation Function).