Cloy Monis Cloy Monis - 9 days ago 6
Swift Question

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

Answer

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).

Comments