AES256 decryption in iOS - tutorial with swift

Hello, I am looking for a *** tutorial/sample code*** for adding functionality of AES 256 decrytion/encryption into ios 13 app using swift 4+.


I have looked into many places without much success and I would prefer to use Apple framework instead of for example https://github.com/krzyzanowskim/CryptoSwift


I have searched for this information for some time so any help would be very valuable. Thank you.

I found the the following sample code: https://developer.apple.com/documentation/cryptokit/performing_common_cryptographic_operations

howerver, I am looking for AES256 encryption/decryption examples. Any help would be very useful. Thank you.

What flavour of AES?

If you want to do AES-ECB or AES-CBC, you’ll need CommonCrypto. If want to do AES-GCM (which is generally what I recommend) you’ll need Apple CryptoKit.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn, Thank you for quick response. I am interested in all three flavours (AES-ECB, AES-CBC, AES-GCM) for AES-256.

where can I find code examples of each flavour with swift binding / ios13 ? Thank you in advance.

The best (IMO, but I’m biased :-) examples of using CommonCrypto for AES-ECB and AES-CBC are in the CryptoCompatibility sample code.

Note These are in Objective-C, and converting them to Swift is a bit tricky. Pasted in below is an example of such a conversion.

For an example of encrypting with AES-GCM:

  1. Get the Performing Common Cryptographic Operations playground.

  2. Switch to the Encrypting Data page.

  3. Change

    ChaChaPoly
    to
    AES.GCM
    .
  4. Add an exclamation mark to the end of line 26 (the

    combined
    property on
    AES.GCM
    returns an optional value [1] whereas the same property on
    ChaChaPoly
    is non-optional).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] You get back

nil
if the
nonce
has the wrong size.
import Foundation
import CommonCrypto

final class QCCAESCryptor: Operation {

    init(plainText: Data, key: Data) {
        self.op = CCOperation(kCCEncrypt)
        self.input = plainText
        self.key = key
        super.init()
    }

    init(cypherText: Data, key: Data) {
        self.op = CCOperation(kCCDecrypt)
        self.input = cypherText
        self.key = key
        super.init()
    }

    private let op: CCOperation
    let input: Data
    let key: Data

    var iv: Data? = nil

    private(set) var result: Result<Data, Error>? = nil

    private override init() {
        fatalError()
    }

    override func main() {
        self.result = Result<Data, Error> {
            guard
                self.input.count.isMultiple(of: kCCBlockSizeAES128),
                [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256].contains(self.key.count),
                self.iv.flatMap({ $0.count == kCCBlockSizeAES128 }) ?? true
            else {
                throw NSError(domain: Self.errorDomain, code: kCCParamError, userInfo: nil)
            }
            var result = Data(count: self.input.count)
            let ecbMode = self.iv == nil
            let effectiveIV = self.iv ?? Data(count: kCCBlockSizeAES128)
            var resultCount = 0
            let err = self.input.withUnsafeBytes { inputBuf in
                self.key.withUnsafeBytes { keyBuf in
                    effectiveIV.withUnsafeBytes { ivBuf in
                        result.withUnsafeMutableBytes { resultBuf in
                            CCCrypt(
                                self.op,
                                CCAlgorithm(kCCAlgorithmAES128),
                                CCOptions(ecbMode ? kCCOptionECBMode : 0),
                                keyBuf.baseAddress!,
                                keyBuf.count,
                                ecbMode ? nil : ivBuf.baseAddress!,
                                inputBuf.baseAddress!,
                                inputBuf.count,
                                resultBuf.baseAddress!,
                                resultBuf.count,
                                &resultCount
                            )
                        }
                    }
                }
            }
            guard err == kCCSuccess else {
                throw NSError(domain: Self.errorDomain, code: kCCParamError, userInfo: nil)
            }
            result.count = resultCount
            return result
        }
    }

    static let errorDomain = "QCCAESCryptorErrorDomain"
}
You can check README for AES examples: https://github.com/krzyzanowskim/CryptoSwift#aes

the simplest form is this one-liner:

Code Block swift
let encrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(plaintext)


AES-256 requires 32 bytes long key.
More complete example (AES-256-CBC), with a key generation out of password would be something along the lines.

Code Block swift
let password: [UInt8] = Array("s33krit".utf8)
let salt: [UInt8] = Array("nacllcan".utf8)
/* Generate a key from a `password`. Optional if you already have a key */
let key = try PKCS5.PBKDF2(
password: password,
salt: salt,
iterations: 4096,
keyLength: 32, /* AES-256 */
variant: .sha256
).calculate()
/* Generate random IV value. IV is public value. Either need to generate, or get it from elsewhere */
let iv = AES.randomIV(AES.blockSize)
/* AES cryptor instance */
let aes = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
/* Encrypt Data */
let inputData = Data()
let encryptedBytes = try aes.encrypt(inputData.bytes)
let encryptedData = Data(encryptedBytes)
/* Decrypt Data */
let decryptedBytes = try aes.decrypt(encryptedData.bytes)
let decryptedData = Data(decryptedBytes)


beside README, there's playground you can take a look at CryptoSwift.playground
AES256 decryption in iOS - tutorial with swift
 
 
Q