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?
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
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.
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.
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.
- Preparing to Test Receipt Validation for iOS
- Loading a Receipt for Validation with Swift
- Extracting a PKCS7 Container for Receipt Validation with Swift
- Receipt Validation – Verifying a Receipt Signature in Swift
- Receipt Validation – Parse and Decode a Receipt with Swift
- Finalizing Receipt Validation in Swift – Computing a GUID Hash