Please see updated section below striked out section. I have left the striked out section to give context to the comments and to show how not to do for security purposes
I have worked it out using CryptoSwift
func testEnc() throws {
//has to be 16 characters
//ivKey is only hardcoded for use of this example
let ivKey = "tEi1H3E1aj26XNro"
let message = "Test Message"
let password = "pass123"
//key has to be 32 characters so we pad the password
let aesKey = password.padding(toLength: 32, withPad: "0", startingAt: 0)
let encrypted = try message.encryptToBase64(cipher: AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7))
//returns: beQ7u8hBGdFYqNP5z4gBGg==
let decrypted = try encrypted?.decryptBase64ToString(cipher: AES(key: aesKey, iv: ivKey, blockMode: .CBC, padding: .pkcs7))
//returns: Test Message
assert(message == decrypted)
}
UPDATE
The above methodology, while it will work, is insecure; please read comments on this answer for more information
Based on the comments and feedback, I have written a new example that uses the framework RNCryptor
To encryp and decrypt messages I use the following 2 methods.
func encryptMessage(message: String, encryptionKey: String) throws -> String {
let messageData = message.data(using: .utf8)!
let cipherData = RNCryptor.encrypt(data: messageData, withPassword: encryptionKey)
return cipherData.base64EncodedString()
}
func decryptMessage(encryptedMessage: String, encryptionKey: String) throws -> String {
let encryptedData = Data.init(base64Encoded: encryptedMessage)!
let decryptedData = try RNCryptor.decrypt(data: encryptedData, withPassword: encryptionKey)
let decryptedString = String(data: decryptedData, encoding: .utf8)!
return decryptedString
}
In my use case I needed to be able to handle encryption and decryption based off a password that could be changed without having to re-encrypt everything.
What I did is generated a random 32 character string and encrypted that with the password. If the user changes their password, they simply decrypt the key with the old password and re-encrypt it with the new password. This ensure that all existing content can be decrypted while still being secured by the user's password.
To generate the encryption key is use the following method:
func generateEncryptionKey(withPassword password:String) throws -> String {
let randomData = RNCryptor.randomData(ofLength: 32)
let cipherData = RNCryptor.encrypt(data: randomData, withPassword: password)
return cipherData.base64EncodedString()
}
Note: You would only generate this encryption key for the user once as it would then be stored somewhere where the user can return it using their password.