Hello! This is the first post in a series of articles about Cryptography in iOS. We will start by addressing symmetric cryptography. In the next articles, we will talk about asymmetric cryptography and how to share keys between iOS and the rest of the world (i.e: OpenSSL).

Why Adding Cryptography To Your Apps

Many developers feel they don’t have to deal with cryptography in their Apps. Even if you are working with a REST API from a remote server, usually sticking to HTTPS solves most secure communication issues, and Apple “Protected mode” and the hardware/software encryption combo do the rest.

However, there are many situations where you want to add that extra layer of security to your App.

Maybe you need to manage confidential communications or documents. Perhaps you are building the iOS frontend for an existing application, whose communication involves ciphered documents/messages.

Perhaps you are working in an App where security is important, or perhaps you just want to add an extra level of security and privacy to your data (which is always a good thing).

About Symmetric Cryptography in Swift and CommonCrypto

Whatever your reason for adding cryptography to your application, the Security Framework and CommonCrypto are the reference frameworks for Cocoa (both in iOS and OS X) for these duties. The CommonCrypto package deals with symmetric encryption, hashes, and digests.

However, CommonCrypto uses an old C-Style API that’s been showing signs of aging for years. Besides, now with Swift, it is even more cumbersome to integrate into modern iOS applications.

Concretely, the strongly typed nature of Swift makes dealing with the different data types of CCCrypt (the main encryption/decryption functions of the framework for symmetric cryptography) less than optimal. Let’s have a look at the definition of CCCrypt:

CCCrypt(op: CCOperation, alg: CCAlgorithm, options: CCOptions, key: UnsafePointer<Void>, keyLength: Int, iv: UnsafePointer<Void>, dataIn: UnsafePointer<Void>, dataInLength: Int, dataOut: UnsafeMutablePointer<Void>, dataOutAvailable: Int, dataOutMoved: UnsafeMutablePointer<Int>)

The CCCrypt Function, Heart of CommonCrypto

The signature of the Objective-C function (more precisely, the C version of the function) was different from the point of view of types involved:

CCCryptorStatus CCCrypt(
 CCOperation op,          // operation: kCCEncrypt or kCCDecrypt
 CCAlgorithm alg,         // algorithm: kCCAlgorithmAES128... 
 CCOptions options,       // operation: kCCOptionPKCS7Padding...
 const void *key,         // key
 size_t keyLength,        // key length
 const void *iv,          // initialization vector (optional)
 const void *dataIn,      // input data
 size_t dataInLength,     // input data length
 void *dataOut,           // output data buffer
 size_t dataOutAvailable, // output data length available
 size_t *dataOutMoved)    // real output data length generated

In the good old Objective-C days, one would simply use the predefined constants for operation, algorithm, and options, like “kCCAlgorithm3DES” for instance. Also, you will specify the different arrays and sizes without worrying much about their exact types (i.e: ints to size_t variables, or”char *” buffers where “void *” ones were expected). It was not the best of practices, but it worked and required some castings at most.

However, in Swift, we have taken the “C” of Objective-C out of the equation, and we need some more work to prepare our Swift and Cocoa variables for CommonCrypto:

Of Operations, Algorithms, And Options

Symmetric cryptography is one of the simplest ways for sending and receiving ciphered data in Apps. There is only one key that’s used both to cipher the clear text and decipher the encrypted one. Conversely, in asymmetric cryptography, a public-private pair of keys are used.

There are many different algorithms for symmetric cryptography, and all of them can have different options. These three main concepts: operation used (encrypt/decrypt), algorithm (AES, DES, RC4…) and options are mapped to the CommonCrypto concepts CCOperation, CCAgorithm and CCOptions respectively.

CCOperation, CCAlgorithm, and CCOption are mere wrappers for uint32_t (that’s it, an unsigned int stored using 32 bits). Thus, we can build them directly with the appropriate CommonCrypto constants:

let operation = CCOperation(kCCEncrypt)
let algorithm = CCAlgorithm(kCCAlgorithmAES)
let options = CCOptions(kCCOptionPKCS7Padding | kCCOptionECBMode)

Unsafe pointers

Unsafe pointers are the abstraction used in Swift to manage C-pointers. Swift tries to distance itself from any kind of pointers or C-style memory management. As a result, you should not need to use them unless you are accessing old-style APIs (like CommonCrypto). However,  in our case it’s certainly useful having at least a basic understanding of how to deal with them:

There are two types of pointers defined in Swift: UnsafePointers and UnsafeMutablePointers. The first ones are used for constant buffers, i.e: pointers to memory areas that are constant and not subject to change. The second ones are for the mutable memory areas.

So strictly from a C perspective, you would translate an UnsafePointer to a “const type *” buffer and an UnsafeMutablePointer to a “type *” buffer (excuse the use of the word “buffer” in this context, it’s just an old habit ;).

The type of the pointer is declared in < > signs immediately after the pointer type declaration, so if you want to declare a pointer to a “void *”, you would do it with UnsafeMutablePointer. If you were to declare a pointer to an old “const unsigned char *” buffer, you would use UnsafePointer<UInt8>.

Dealing With C Types in Swift

While Apple does offer a translation from pure C-types to Swift types here, it’s important to note that those types (like CChar, CInt, CUnsignedLongLong…) are not used in the definition of UnsafePointers, using the native swift types instead. This leaves us with some ambiguity as to where one type should be used or not. Fortunately, a little delving inside Swift’s types definitions give us some handful insights:

typealias CShort = Int16
typealias CSignedChar = Int8
typealias CUnsignedChar = UInt8
typealias CUnsignedInt = UInt32
typealias CUnsignedLong = UInt
typealias CUnsignedLongLong = UInt64
typealias CUnsignedShort = UInt16

Thankfully we don’t need to take memory management of UnsafePointers and UnsafeMutablePointers into account when dealing with them. Not, at least, as long as you get the memory from a valid Cocoa object like NSData. In this case, memory is automatically managed (and bridged) by Swift. If you have your raw data to encrypt/decrypt and your keys in NSData, it is easy to get a UnsafePointer or UnsafeMutablePointer by calling data.bytes or data.mutableBytes respectively.

Getting The Address Of A Variable In Swift

Another way of getting the UnsafePointer for a variable, useful when you are dealing with output variables (that need the memory address) is by means of the “&” sign (like you did in C). Thus, you will use a “&” sign to go from an Int to an Unsafe(Mutable)Pointer<Int>.

We can use this technique in CCCrypt by passing the address of an “Int” variable to the last parameter: “dataOutMoved”, to store the number of bytes affected by the operation.

Note that a let variable will produce an UnsafePointer<Type> whereas a var one will produce an UnsafeMutablePointer<Type>.

In summary, we now know everything we need to call CCCrypt with our everyday Swift objects.

Bridging

CommonCrypto has not been exposed to pure Swift (yet?), so in order to use it, we need to build a bridging header and make an import of CommonCrypto the old Objective-C way:

#import <CommonCrypto/CommonCrypto.h>

SymmetricCryptor

Recently I needed to work with symmetric cryptography for the project I’m currently working on.  In order to make it easier for me to encrypt and decrypt data, I built a SymmetricCryptor class (please excuse the terrible name) to help me from having to “translate” all my data to the proper CommonCrypto types.

You can use it to encrypt or decrypt with a single, convenient call:

let sc = SymmetricCryptor(algorithm: .AES128, options: CCOptions(kCCOptionPKCS7Padding))
cypher.setRandomIV()
do { let cypherText = try sc.crypt(string: clearText, key: key) } catch { print("Error while encrypting: \(error)") }

While CommonCrypto provides several algorithms and options, I wanted to address the common encryption configurations usually found when dealing with ciphering/deciphering.

For example, when using RC4, you can use 40 or 128 bits keys (known as RC4_40 and RC4_128 respectively). Same goes for the different variants of AES (128b, 256b…).

That’s why I defined an enum called SymmetricCryptorAlgorithm, that defines complete configurations (like AES 256) rather than just mere algorithms, as defined in the cipher specs by Apple. Thus, it contains information about the length of the key or the block size, easily manageable as a unit.

You can find the SymmetricCryptor class alongside a demo project showcasing how easy it’s to use the class for symmetric cryptography operations here, in my GitHub repository.

ezgif-755330533

Where To Go Next

This was the first episode in a series of tutorials about Cryptography in iOS. In this article, we learned about how to use Symmetric Cryptography in Swift. I also shared SymmetricCryptor, a ready-to-use-class to deal with symmetric cryptography operations.

In the next article, we will talk about asymmetric cryptography in Swift, and I will also share some useful classes and sample code ready to use for your projects. Did you find this article useful? Let me know your thoughts in the comments below.