Every iOS app requires a certificate from Apple to publish apps to the App Store. The certificates are required to code sign iOS apps. Apple usually offers development certificate to distribute apps in debug mode on certain devices and distribution certificate to distribute the app to App Store. The certificate is at the core of code signing iOS apps. In the process of distributing iOS apps from Continuous Integration server, we need to host iOS distribution certificate somewhere securely. In this short post, we will cover how to encrypt and decrypt iOS certificates using openssl and security utility.
The certificate offered by Apple to distribute iOS apps are usually stored in the keychain in the macOS. The certificate has all the data that we have provided during creating certificate signing request, Apple then adds some signer data like Authority, expiry date etc. The whole certificate has the signature attached to it. In the Keychain application if you right click on the certificate and “Get Info” then you will see all this information. It should have following things
- Subject Name: This contains UserID, name, organization details and the country name of the developer.
- Issuer name: This contains Apple details like authority, organization unit that has issued the certificate and expiry date of the certificate.
- Public Key Info: This contains details of the public key like which algorithm and signature are used.
- Fingerprints: Finally it contains fingerprint details like SHA-256 and SHA-1 etc. The certificate also shows the purpose of what this certificate will be used for like code-signing or any other activity.
These details are sensitive and need to be kept secure.
In Cryptography, PKCS#12 a.k.a Public Key Cryptography Standard is the standard used to store private keys with public key certificates protected with the password. In case of the iOS Development certificate, we can export the certificate from keychain into the Personal Information Exchange a.k.a p12 formatJ ust right-click on the certificate in the Keychain Access and select Export.You will see that option to export your certificate in the .p12 format also you can encrypt this certificate with a strong password. This password is usually our CERTIFICATE_PASSWORD which we need to keep very secure.
At this stage, we have fully secured .p12 file with strong password however, we shouldn’t keep these files inside the Github repositories. The tools like Fastlane match suggest to create repositories for storing certificates but it doesn’t sound secure without encryption. It means adding just CERTIFICATE_PASSWORD isn’t enough we can further encrypt our certificates using ENCRYPTION_PASSWORD which we can use to more securely encrypt certificates in .enc format which can be put inside the GitHub repositories. We can easily do this using openssl utility.
$ openssl aes-256-cbc -k "ENCRYPTION_PASSWORD" -in path/to/certificate/certificate.p12 -out path/to/certificate/certificate.p12.enc -a
After this, we will have certificate.p12.enc file encrypted with ENCRYPTION_PASSWORD which we can able to put in the Github repositories.
Now that, we have fully encrypted certificate with very strong CERTIFICATE_PASSWORD and ENCRYPTION_PASSWORD for security purpose. It’s fairly easy to decrypt the certificate back to the .p12 format using the following command.
$ openssl aes-256-cbc -k "ENCRYPTION_PASSWORD" -in path/to/downloaded/certificate/certificate.p12.enc -d -a -out path/to/decrypted/certificate/certificate.p12
After executing this command, we will have our original certificate in the .p12 format which can be dynamically added to keychain using security tool and CERTIFICATE PASSWORD provided above. We can create new keychain for any users using following commands
$ security create-keychain -p USERNAME ios-build.keychain
$ security default-keychain -s ios-build.keychain
$ security unlock-keychain -p USERNAME ios-build.keychain
$ security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
We can now add the certificate to the newly created keychain ios-build.keychain using the following approach
$ security import /pathto/certificate.p12 -k ~/Library/Keychains/ios-build.keychain -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign
This approach of dynamically creating keychains and certificates are really useful for scripting CI/CD pipelines on cloud-based CI servers like Travis or CircleCI as they give fresh VMs for every build.
Secure Storage of Passwords
We have just covered how to use strong CERTIFICATE_PASSWORD and ENCRYPTION_PASSWORD for security purpose but the question is where to store this passwords. Here are few very important things about the security
- Never ever code the passwords in the script either strong CERTIFICATE_PASSWORD and ENCRYPTION_PASSWORD
- Always use environmental variables in the script to use the values of the secure password
- Cloud-based CI services give us the secure area where we can store the password and can be used as environmental variables while running the build.
- Self-hosted CI servers, we have to very careful about the storing these passwords. Only administrators should have access to sensitive information. The self-hosted CI servers like Xcode Server, Jenkins, TeamCity has the mechanism to securely store the password values.
It’s essential to secure those passwords so that there won’t be any chance to get those details leaked.
It’s very easy to secure the sensitive information like iOS development certificates by encrypting them with solid passwords. This can easily be achieved by learning the little bit about openssl and security command line tools. How do you encrypt your certificates? Share your thoughts with me. I am on Twitter @Shashikant86