Logo for tanaschita.com

Symmetric-key cryptography with CryptoKit for iOS

Using CryptoKit to increase security in iOS applications.

17 Jan 2022 · 4 min read

In the previous article on Public-key cryptography with CryptoKit, we already looked at asymmetric cryptography, its use cases and how we can use it to increase security in our applications. In this article, we'll do the same with symmetric-key cryptography.

In symmetric-key cryptography, the same key is used for encrypting and decrypting data. Compared to public-key encryption, it's a disadvantage because a shared secret needs to be exchanged before being able to use it. On the other hand, symmetric encryption is less complex and executes faster.

In practice, both symmetric-key cryptography and asymmetric-key cryptography are often combined to secure data. Asymmetric-key cryptography is used to exchange a shared secret, then symmetric-key cryptography is used to encrypt and decrypt the data. Let's look at how this works.

Generating and exchanging a shared secret

The exchange of a shared secret between a server and a client can be achieved with public-key cryptography:

  1. The server generates the secret key, uses the client's public key to encrypt it and sends the encrypted symmetric key to the client.
  2. The client decrypts the symmetric key using its private key.
  3. With the client and server both having the same symmetric key, they can now safely use symmetric key encryption.

After getting the symmetric key from the server, we can use CryptoKit to create a SymmetricKey type for further usage:

let keyData = Data(base64Encoded: base64EncodedKeyString)
let symmetricKey = SymmetricKey(data: keyData)

Encrypting and decrypting with symmetric key

The current state of the art in symmetric-key encryption is a cipher called AEAD. There are two AEADs commonly used: AES-GCM and ChaCha20-Poly1305 cipher.

Applying those algorithms with CryptoKit can be done in one line:

let encryptedData = try ChaChaPoly.seal(data, using: symmetricKey).combined

Or the same with AER-GCM:

let encryptedData = try AES.GCM.seal(data, using: symmetricKey).combined

Similarly simple is the decrypting process:

let sealedBox = try ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try ChaChaPoly.open(sealedBox, using: symmetricKey)

Signing with symmetric key

We already looked at signing with public-key cryptography in the previous article. Verifying the sender’s identity and the integrity of the data can also be done with symmetric-key cryptography by using HMAC, a hash-based message authentication code.

For that, we use the previously shared secret key to sign the digest of the data and then send both, the data and the signed digest to the server. The server uses the same key to validate the data.

let authenticationCode = HMAC<SHA512>.authenticationCode(for: data, using: symmetricKey)

In the code example above, authenticationCode is our signed digest that we send to the server along with the actual data.

Checking the validity of authenticationCode is similarly simple:

let isValid = HMAC<SHA512>.isValidAuthenticationCode(Data(authenticationCode),
authenticating: data,
using: symmetricKey)

And that's basically it. CryptoKit allows us to apply symmetric cryptography signing, encrypting and decrypting data with a few lines of code. That's pretty awesome!

Newsletter

Like to support my work?

Say hi

Related tags

Articles with related topics

Latest articles and tips