CryptoExportImportManager

A swift class for exporting and importing public keys to make iOS compatible with the outside cryptographic world.

150
35
Swift

CryptoExportImportManager

The Security framework and cryptographic functions available for iOS developers are IMHO obscure, bad documented, and thought to be used only inside iOS. Unfortunately, there is no easy way to integrate iOS in a general, heterogeneous cryptographic system due to the way the Security framework stores and retrieves the key information.

This class tries to make it easier for a developer to import public keys from an external source (i.e: a backend or server, generated by OpenSSL) or exporting the generated public keys to a format readable to external sources (i.e: openSSL or PHP (i.e: openssl_get_publickey).

Usage

Drag and drop the CryptoExportImportManager.swift file to your project, and copy if needed. Now you are ready to use it to import or export public keys:

Import public RSA keys.

Unfortunately, the Security framework provides no way for importing a public RSA key generated by, say, openSSL into iOS. This is due to the format that iOS expects the files to be. In order to import a public key, you need to generate a certificate, not a keypair with OpenSSL, and then pass this certificate to your iOS App or embed it inside iOS:

  • Generate the private key and the certificate
openssl req -newkey rsa:2048 -nodes -keyout private_key.key -x509 -days 3650 -out certificate.pem
  • Convert the certificate from PEM to DER
openssl x509 -outform der -in certificate.pem -out certificate.der
  • Check the certificate and private key
openssl x509 -text -noout -inform DER -in certificate.der
openssl rsa -check -in private_key.key

Once you have that certificate.der inside iOS, you just have to read it and get the NSData:

// first try to get the path for certificate.der
guard let certPath = NSBundle.mainBundle().pathForResource("certificate", ofType: "der") else { ... }

// now get the data from the certificate file
guard let certData = NSData(contentsOfFile: certPath) else { ... }

Then you just create an instance of CryptoImportExportManager and call its importPublicKeyReferenceFromDERCertificate(data) method:

let importExportManager = CryptoExportImportManager()
if let publicKeyRef = importExportManager.importPublicKeyReferenceFromDERCertificate(certData) {
   // use publicKeyRef to sign, decrypt, etc..
} else { ... handle error ... }

importPublicKeyReferenceFromDERCertificate(data) returns a SecKeyRef without adding it to the KeyChain.

Export Apple keys to a valid, readable format

In order to export a public key in a format that can be read and managed by external sources (PHP, Ruby, OpenSSL…) you just need to retrieve the public key bytes in a NSData by using SecItemCopyMatching, and then create an instance of CryptoImportExportManager and call its exportPublicKeyToDER(data, keyType, keySize) or exportPublicKeyToPEM(data, keyType, keySize) methods, depending on your desired output format. keyType can be either kSecAttrKeyTypeRSA or kSecAttrKeyTypeEC (the two key types allowed by Apple). Valid key sizes are 1024, 2048 and 4096 for RSA keys, and 256, 384 and 521 for EC keys (corresponding to the curves ansiX9p256r1, secpr384r1 and secp521r1).

let keyType = kSecAttrKeyTypeEC
let keySize = 256
let exportImportManager = CryptoExportImportManager()
if let exportablePEMKey = exportImportManager.exportPublicKeyToPEM(pubKeyData, keyType: keyType, keySize: keySize) {
   // send pem string to server.
} else { ... }

Note: contrary to what’s specified in the documentation for kSecECCurveSecp256r1, the curve that needs to be specified in order for the generated key to be valid is not a prime256v1 (aka secp256r1), but a ansiX9p256r1 (OID 1 2 840 10045 3 1 7).

Checking the keys:

The project comes also with a sample PHP file that would read a key obtained from the CryptoImportExportManager. You just need to copy the PEM formatted output from the export controller, save it in a file, and then call readkey.php:

php readkey.php public_key_file.pem

License

The MIT License (MIT)

Copyright © 2015 Ignacio Nieto Carvajal (http://digitalleaves.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.