OpenSSL for iOS & Swift the Easy Way

I’m currently working on outfitting an app I’m working on to be able to validate receipts to verify purchases of the app.

Little did I know, this adventure would introduce the need to understand how to use cryptography in order to work with the receipt.

Cryptography library needed

In order to even “open” the receipt itself, we’ve got to work with something called a “PKCS #7 container”. Once we get the container open, we need to be able to validate Apple’s certificate that they use to sign every purchase of every app.

All of this requires the use of a cryptography library, and OpenSSL seems to be the common choice, due to its being open source.

I found that figuring out what to do to get OpenSSL into my project was harder than I wanted it to be. It turns out that there are a few to do this, but I wanted the easiest to implement (and the easiest to maintain). The options I was able to identify are:

  • Build the binaries for each platform yourself. To do this you’ve got to make sure you build for both the simulator and the device by running special config routines and using makefiles and what-not. It seemed error-prone, and I’m not confident enough in my ability to know whether or not I’ve done it right.
  • Download a pre-built static library – however, this introduces a risk that I wasn’t really willing to take. How do I trust that pre-built library? If there’s a vulnerability there, how do I easily upgrade the library to the patched version? Every recommendation I’ve seen thus far says, “Always build your own static library, rather than download it already-built from somewhere”.
  • Cocoapods. Simply put, this was the easiest route for me.

OpenSSL for iOS with Cocoapods

How easy is it to get started with OpenSSL for iOS with Cocoapods?

Pretty easy.

If you don’t have Cocoapods yet, you can head over to Cocoapods.org and follow their instructions for installing. It’s literally one command at the terminal:

sudo gem install cocoapods

Once Cocoapods is installed, open your project in Xcode and add a new empty file (File -> New File -> Other -> Empty) called Podfile.

In its contents, you simply add a reference to the OpenSSL library:

Note that there are several ‘OpenSSL’ Cocoapod specs out there to choose from. I originally tried one that looked like it was for iOS (OpenSSL-iOS), but I was never able to get Swift code to recognize the C functions and types.

The one that seemed to still pull the source from openssl.org and build it when the pod is installed was simply named ‘OpenSSL’ and I’ve verified that my Swift code can ‘see’ the C code without running into ‘unresolved identifier’ compiler errors.

Once the Podfile is created and configured, save it and close Xcode. Then head to the Terminal.

Navigate to your Xcode project folder where the Podfile is located and run pod install.

Once it’s finished doing its thing (be patient… it took several minutes for me), you can open the new .xcworkspace file that Cocoapods created for you. You’ll have everything in your project configured to depend on the OpenSSL library through the new Pods project that’s been added to your Workspace.

Bridging header

In order to use OpenSSL with Swift, you’re going to need to create an Objective-C bridging header to access the functionality provided in the OpenSSL libraries.

If you don’t already have an Objective-C bridging header, it’s simple to get one added automatically by Xcode for you:

  • Choose File -> New -> File
  • Choose Source under iOS (on the left
  • Choose Objective-C File
  • Name it “bridge” (or anything, really – it’s a dummy file that you’ll delete after Xcode generates the bridging header)
  • Choose Next, and then Create

Xcode will prompt you to create the bridging header – you should let it. Once it’s created, you can delete “bridge.m” (the Objective-C .m file that you just created in the steps above).

Within the bridging header, you can insert some #import statements to make the OpenSSL library components visible to your Swift project. For example, to start off, you could flesh out the bridging header with a couple of OpenSSL header files:

Xcode 7 & Bitcode

When you build and run your newly configured project in the Simulator, things are going to work fine.

When you build it for your device, however, it will fail.

…Pods/OpenSSL/lib/libcrypto.a(bio_lib.o)’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

At the time of this writing, there is somthing in OpenSSL that doesn’t support Xcode 7’s Bitcode feature. Eventually (hopefully) they’ll fix it, but for now, if you want to use OpenSSL in a Swift project using Xcode 7, you’ll have to turn off Bitcode.

Click on your project, and then click on your app target under ‘Targets’ in the project settings window.

Find Build Options and set Enable Bitcode to ‘No’

If you try re-building against the device with this setting set to ‘No’, it should build and run without issue.

Wrapping up

That’s all there is to getting OpenSSL built and added as a reference in your app. Now will come the fun part of using it with Swift, but I will save that for another entry.

  • Miker Qiu

    Hello, I am recently on the same topic as you, trying to link the openSSL to swift but disappointedly found that there is no “standard” package. Such an easy and helpful instruction you wrote. My question now is, how do you use it in the actual programming. Will it be like using commands the same as they used to be in Objective-C?

    • Andrew Bancroft

      Hey Michael!

      I know we conversed a bit over e-mail, but I thought I’d post a reply here for the sake of anyone else who may be reading through the comments.

      —–

      Once you’ve put in some #include statements in your bridging header, you should be able to access the OpenSSL functions and types that are public within that .h file. To know what you can call, you can browse the .h file in your Pods project (CocoaPods adds this automatically when you install a pod). I needed to use a function in there that starts with “BIO_” so I started typing that in my main View Controller’s viewDidLoad function and Xcode’s auto-complete picked up on this and displayed functions from the OpenSSL library.

      Then, as you found out, you do have to explicitly include the bridge file in your project’s build settings: Click primary project node -> Build Settings tab -> Swift Compiler – Code Generation section -> Objective-C Bridging Header

  • vipul kumar

    I am trying to use openssl in swift app but getting header file error. Openssl is working fine in Objective C . Please suggest it , How to use in swift app

    • Andrew Bancroft

      Hi Vipul,

      Can you give any more detail on which header file the error is occurring in?

  • Pingback: Preparing to Test Receipt Validation for iOS - Andrew Bancroft()

  • Ben

    Got a header file error from importing openssl/pem.h: Expected ‘)’. Apparently it’s in rsa.h line 96, which is:

    int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);

    • That Peachey Thing

      did you find a solution for this?

      • Ben

        Nope, I gave up

        • Cenox Kang

          simply just add // in front of line
          No need when opening PKCS7.

    • The problem is the “*I” pointer is colliding with another symbol for another library, namely it can be found on . To fix this, you need to edit rsa.h and change this line:

      int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);

      To:

      int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx);

      (Or any other symbol name for that “const BIGNUM *i” symbol).

      Another solution is to add “#undef I” in the same header (rsa.h), but I prefer to edit the variable name in that pointer.

      • Scott Wilson-Billing

        Thanks, was looking for this 👍

  • Pingback: Loading a Receipt for Validation with Swift - Andrew Bancroft()

  • Noura Rizk

    After installing OpenSSl from cocoapods, workspace file wasn’t created, I’m using xcode 8 swift 3? I never had this issue before, could you please help. Thanks..

  • It looks like we just have to build the library with Bitcode enabled. If I could find the original repo for this pod I could try to contribute that. It’s been two years, I don’t think they will add bitcode support on their own.

  • Pingback: Receipt Validation - Verifying a Receipt Signature in Swift - Andrew Bancroft()