Apple recently introduced a new framework named CryptoKit at WWDC19, which makes generating hashes, encrypting data and verifying/authenticating data even easier.
Previously, the only way to use cryptography in Swift was via lower level APIs and complicated solutions. CryptoKit improves on this as it is much easier to use and doesn’t require knowledge of low level operations.
In this tutorial, we’ll explore how to perform different cryptographic operations using CryptoKit, including signing data, encrypting information, creating hashes, and performing key agreement.
Note: This tutorial requires Xcode 11 and the latest beta versions of macOS 10.15 or iOS 13, which are currently in beta, as it relies on new features or frameworks that are not available on previous versions.
As CryptoKit is built into Apple’s platforms, no installation or configuration is needed. However, Apple has a sample Swift playground that demonstrates different cryptographic operations, which I’ll use as the base for this tutorial.
I’ll include examples in this tutorial, but feel free to download the playground if you’d like to follow along and test out different examples.
If you aren’t using Apple’s sample playground, make sure to add
import CryptoKit to the top of your file to be able to use it in your code.
Hash functions generate a unique key that will stay the same as long as the input data is exactly the same. For example, this could be very useful to verify that a shared piece of data is the same.
CryptoKit makes it easy to generate different types of hashes with good collision resistance, which prevents the possibility of two different pieces of input data generating the same hash.
CryptoKit supports the
SHA512 algorithms (as well as some older, insecure algorithms that should not be used). As computers have gotten more powerful, hash sizes have continued to increase to make it harder for attackers to attempt to force collisions.
hash(using:) function on any algorithm to generate a hash for a piece of data, such as a string or a file.
Generating a hash for a file
As you can see, generating hashes for files is as easy as loading the file, selecting an algorithm, and hashing it. Apple’s Swift playground also includes an example of hashing files via a buffer.
Generating a hash for text or other data
To generate a hash for text or other data, just do the same thing as with generating file hashes, except directly with the data or by encoding the string as data.
Encrypting files allows you to achieve both authenticity and confidentiality by converting the input data into cipher text that can only be read with the original, randomly generated key that is shared between parties.
CryptoKit supports both the
ChaChaPoly algorithms, although
ChaChaPoly is preferred as it is typically faster on mobile devices.
To encrypt a file, just seal it with the chosen algorithm:
The sealed box contains 3 outputs from the operation: the
sealedBox.ciphertext (the encrypted data, always the same size as the input data), the
sealedBox.tag (used to ensure the data remains intact), and the
sealedBox.nonce (which should be different every time an encryption operation is performed, and is generated randomly if not provided during encryption).
sealedBox.combined property with the other party, which is generated from the tag, nonce, and cipher text.
Then, the receiving party, or client, can decrypt the content using the same key (which should not be shared in the same way to avoid attackers from gaining access to the key).
Creating and Validating Digital Signatures
Digital signatures are used to validate the authenticity and integrity of a message or piece of data. After signing the data with a private key, others can verify the signature using your public key.
CryptoKit has built in support for 4 different elliptic curve types, which are used to create and verify cryptographic signatures:
P256. The different types have different levels of security and speed, but
Curve25519 is typically best.
First, generate a random secure public and private key-pair, and publish the public key.
Then, sign a piece of data with the private key, such as a string.
Finally, anyone can check that the signature is indeed authentic and from you using the public key:
If anyone tries to publish a fake signature, it will be rejected when someone tries to validate it.
Performing Key Agreement
Key agreement allows multiple parties to determine a shared encryption key that can be used to sign or encrypt data that they want to exchange.
First, create a unique salt that you will use when deriving keys. Here, we are using an
if let block to avoid the salt’s encoded data from being optional, but you can also use a
guard let block instead.
Then, both users A and B generate a public and private key-pair, and publish the public key while keeping the private key secret. You can use any of the elliptic curve types from the digital signatures section, such as
User A derives a shared secret with both their private key and User B’s public key.
Then, User B performs the same operation using their private key and User A’s public key.
You can check that both of the generated keys in this example are equal like this:
Both User A and User B now have a copy of the same key that they can each use to authenticate or encrypt messages to and from each other.
In this tutorial, you explored multiple different cryptographic operations that can be performed using Apple’s new CryptoKit framework in iOS 13.
Apple has a sample Swift playground that demonstrates similar cryptographic operations as in this tutorial, which I’ve included below as a reference.
I hope this tutorial was useful and helped you to learn more about using CryptoKit. If you have any questions or feedback, feel free to send them or email me: [email protected].
Thanks for reading 🔑