From: https://medium.com/@joncardasis/openssl-swift-everything-you-need-to-know-2a4f9f256462
Follow
May 1, 2018 · 6 min read
Hashes and Dashes of Code.
There are little to no tutorials out there outlining how to get started with OpenSSL for macOS and iOS applications without the use of external solutions such as Cocoapods. Here I’m going to focus on how you can include OpenSSL into your project without external build systems. I will be outlining how to build and link for a macOS target, but iOS is very similar.
OpenSSL was first released in 1998 under the premise to create a free set of encryption tools for code used on the internet. Since then it has become one of the most well known (and distributed) open-source projects.
OpenSSL is a C based security library focusing on computer network security. Due to the large implementation suite it provides, from SSL and TLS to hash and cipher functions, OpenSSL has trusted implementations of some of the most popular cryptographic functions.
Integrating OpenSSL’s library into your macOS or iOS app can be…..well…a bit more than tricky when you haven’t used a library like it before.
The first thing to note is that you should never use an untrusted, precompiled version of OpenSSL in your app. Anyone can modify the source of OpenSSL with malicious code and distribute that library. Be sure to only download the library from a trusted source (i.e. https://www.openssl.org/source/) and check the hash of your download.
So we download the source. We need to compile it into a usable library. There are two options we have: a Static Library or a Dynamic Library. Like anything in Computer Science, the answer to “Which should I use?” is It Depends.
Dynamic Libraries (also known as Shared Libraries) are .so
files (or .dylib
files in macOS). All code relating to the library is this file and it is referenced by your program at run-time. Static Libraries are .a
files. Any program using a static library takes a copy of the code from the static library and makes it part of the programs compiled binary — the library becomes part of the code and is one of the first things loaded when starting the application.
Dynamic Libraries have the benefit of reducing duplicate code — if two applications want to reference the same library, they can. And an update to a system dynamic library can allow applications to always use the latest version. Static Libraries, on the other hand, increase the overall size of the binary, however, this also means that code is connected at compile time and there is no additional run-time loading overhead. All the code is just there.
Both have advantages or tradeoffs. In the interest of this guide, I have a business requirement to stay on the same version of OpenSSL for licensing purposes, therefore I am using static linking for the library (as my code will then always use the same version of the code library).
Create a folder for the OpenSSL libraries and associated file to be located in. I created an OpenSSL
folder at the top level of my project directory:
CryptoExample └ OpenSSL/ └ .gitkeep └ CryptoExample/ └ CryptoExample.xcodeproj
I add a .gitkeep
file so git will keep this directory, but we will ignore all other files in that directory in our .gitignore
:
# gitignore OpenSSL/* !OpenSSL/.gitkeep
For most projects, we can build for the i386 and x86 architectures and then combine those builds into a single library. The below script will download a version of OpenSSL (1.1.0g in this case) from their website and run a SHA256 checksum to confirm the download has not been tampered with:
(Note: run the script from your project directory)
OpenSSL build script for macOS architectures
After running the script the OpenSSL
folder will contain the libcrypto.a
and the libssl.a
libraries as well as the LICENSE file and include
directory (which includes all the header files for OpenSSL).
Let’s do this.
This is most likely the reason why you are here. You have your libraries, include headers, but how do you link everything together so you can utilize OpenSSL in your project?!
After running the above shell script your file hierarchy should look something like this:
File Hierarchy
LIBRARY_SEARCH_PATHS
to include: $(PROJECT_DIR)/OpenSSL/lib
.HEADER_SEARCH_PATHS
to include: $(SRCROOT)/OpenSSL/include
.Now we create a Swift ModuleMap in order to let the compiler know what C files we want to be associated with a custom module. Here we will call the module OpenSSL
for simplicity, however, it can be called anything.
1. Create a shim.h
file. This is an import header file which imports all OpenSSL files we need to expose.
2. Create a custom module.modulemap
:
3. Head back to your target’s Build Settings and edit IMPORT_PATHS
to include: $(SRCROOT)/$(TARGET_NAME)
. This will tell the compiler to look in our project folder for custom module maps.
4. Finally, you can import OpenSSL
(we called the module ‘OpenSSL’) into any Swift file requiring it’s usage.
Your final project hierarchy may look like the following:
build_openssl.sh CryptoExample └ AppDelegate.swift └ Assets.xcassets └ Base.lproj └ Info.plist └ Modules └ module.modulemap └ shim.h └ ViewController.swift CryptoExample.xcodeproj OpenSSL
Now we can successfully import our OpenSSL module (note that we could have named it anything). Now we run into some issues with Swift which we do not face when using Objective-C.
OpenSSL is written in C and makes use of macros. Swift, by nature, can not access C macros directly. This makes dealing with some C libraries, like OpenSSL a bit tricky. One declaration in the library is X509
which is essentially just a pointer. We can use an OpaquePointer
without issue, and I create a typealias for readability.
Take a look at the example below of how direct OpenSSL to Swift language interaction works.
Example.
Swift can make dealing with OpenSSL a bit harder than usual. If you find this to be too daunting, you have the option of wrapping all this logic in Objective-C, or exposing C declarations via Objective-C functions which can be called from Swift.
Let’s say you have the C macro to convert a hex value (e.g. 0xff0000
) to an NSColor:
#define UIColorFromRGB(rgbHex, alphaValue) \ [NSColor colorWithRed:((float)((rgbHex >> 16) & 0xFF))/255.0 \ green:((float)((rgbHex >> 8) & 0xFF))/255.0 \ blue:((float)((rgbHex >> 0) & 0xFF))/255.0 \ alpha:alphaValue]
In Objective-C the macro can be wrapped in a function and then imported to Swift:
+ (NSColor *)colorFromMacro:(int)rgb alpha:(float)alpha { return NSColorFromRGB(rgb, alpha); }
First off, I’m no lawyer. I’m a programmer with an internet connection and the requirement to cover our butts. That being said, it is good to know how and where you can use OpenSSL.
OpenSSL is fairly permissive, allowing you to include the frameworks in your application without much issue. The LICENSE
outlines exact usages, but some highlights are:
“This product includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit (http://www.openssl.org/)"
Essentially, if you use OpenSSL in your project, you should include this statement in a “Legal” section of your application.
For full details, be sure to consult your LICENSE
file included in your OpenSSL folder.
210
210 claps
WRITTEN BY
Follow
Senior Mobile Engineer @ FormHealth with more than 7 years of experience in iOS/Android/React Native | jonathancardasis.com