Cryptography in iOS (i): Symmetric Cryptography in Swift - Digital Leaves
996
post-template-default,single,single-post,postid-996,single-format-standard,qode-social-login-1.0,qode-restaurant-1.0,ajax_fade,page_not_loaded,,select-theme-ver-4.1,wpb-js-composer js-comp-ver-5.2,vc_responsive
Digital Leaves. Cryptography in iOS: Symmetric cryptography in Swift. Asymmetric Cryptography in Swift.

Cryptography in iOS (i): Symmetric Cryptography in Swift

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 sharing 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 in 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:

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:

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 where 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:

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 leave 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:

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 a 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:

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:

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.

 

9 Comments
  • Jonathan Andrade

    August 19, 2015 at 5:20 am Reply

    Hi! Im waiting for the asymmetric cryptography post, it will be very important to me.
    If you could put some code of how it works, I would be very thankful.
    thanks for the commonCrypto post!

  • Mohammed Janish

    September 9, 2015 at 4:48 am Reply

    I’m also waiting for asymmetric cryptography especially RSA. Eagerly waiting for it.

  • Ignacio Nieto Carvajal

    September 9, 2015 at 10:15 am Reply

    Thanks guys, I will be definitely writing it soon (when I find some free time ;). Best!

  • Greg Porterfield

    January 2, 2016 at 1:57 pm Reply

    Very helpful series, thank you. These posts are helping me fill in some gaps for some projects that I am starting.

  • Murad

    March 8, 2016 at 7:58 am Reply

    cool article thank you. however, I have 2 questions:

    (1) for the github project, in the SymmetricCryptorAlgorithm enum, you commented : “AES256 still requires 256 bits IV” in the requiredIVSize function, in contrast, you commented “AES256 still requires 128 bits IV” in requiredBlockSize function, which comment is the correct?

    (2) for the enum SymmetricCryptorAlgorithm, in ccAlgorithm function, you wrote: case AES_256: return CCAlgorithm(kCCAlgorithmAES)

    how come you use AES256 algorithm while there is no kCCAlgorithmAES256 enum value in CommonCrypto’s CCAlgorithm enum ? why do you name it AES256 in your enum ?

    • Ignacio Nieto Carvajal

      March 8, 2016 at 5:19 pm Reply

      Hi Murad, thanks. Regarding your questions:

      1) This is a typo (probably a copy&paste typo). Please excuse me. It should be “AES256 still requires 128 bits IV” in the requiredIVSize method, “AES256 still requires 128 bits blocks” in the requiredBlockSize, and “AES256 uses 256 bits key size” in the requiredKeySize method.
      2) AES 256 and AES 128 is the same algorithm. It differentiates in some parameters (like the size of the block only).

      Hope it helps.

  • Murad

    March 9, 2016 at 5:12 am Reply

    thank you Ignacio for your answers.
    after I placed your second comment in the required block size method, it became as following: case AES_256: return kCCBlockSizeAES128 // AES256 uses 256 bits block size

    it became an ambiguous comment since you return kCCBlockSizeAES128 and not kCCBlockSizeAES256 (which is not defined in CommonCrypto framework)

    • Ignacio Nieto Carvajal

      March 9, 2016 at 8:19 am Reply

      It is requiredKeySize, not requiredBlockSize. Please, have a look at the AES algorithm, and learn about it. The class will make more sense afterwards. Best regards.

Post a Comment

Before you continue...

Hi there! I created the Digital Tips List, the newsletter for Swift and iOS developers, to share my knowledge with you.


It features exclusive weekly tutorials on Swift and iOS development, Swift code snippets and the Digital Tip of the week.


Besides, If you join the list you'll receive the eBook: "Your First iOS App", that will teach you how to build your first iOS App in less than an hour with no prior Swift or iOS knowledge.

I hate spam, and I promise I'll keep your email address safe.