Hello everyone, Leo here. This is the Cryptographic Keys and Swift introductory article.
Today we will introduce a very nice theme about Cryptographic Keys. iOS is heavily secure based on cryptography, which Apple introduces in iPhone 5S versions and above a dedicated subsystem (mix of hardware and software) called Secure Enclave.
For us, iOS developers, it’s very important to know the basic concepts of app security because we don’t want to leak all of our user data to the outside world. When talking about security it’s always a premise that our system will as safe as possible to corroborate in our app’s reliability efforts.
We will study what are cryptographic keys, their types and how the iOS CryptoKit framework helps us create and use them.
Let’s code, but first…
Painting of The Day
The painting is a 1505 masterpiece called St. George and the Dragon by the painter Raffaello Sanzio da Urbino. He is considered one of the great master painters, Raphael was an Italian painter and architect in the High Renaissance. Raphael, along with Michelangelo and Leonardo da Vinci, is considered the great trinity of master painters of the High Renaissance period. He was a prolific artist, and despite his death at the young age of 37, has a considerable body of work to study.
I chose this painting because the knight is using shiny armor, and that is the knight’s protection against the dragon as same as cryptography can protect us from malicious attacks.
The Problem – Cryptographic Keys and Swift
You were asked to create an app that generates various kinds of cryptographic keys.
First, let’s start with the core concepts of Cryptograph Keys. First let’s see its definition, after we will study different types of keys, and finally how to implement those in your iOS applications.
Cryptographic Keys Definition
The dictionary definition is:
Secret value used by a computer together with a complex algorithm to encrypt and decrypt messages. Since confidential messages might be intercepted during transmission or travel over public networks, they require encryption so that they will be meaningless to third parties in order to maintain confidentiality. The intended recipient, and only the recipient, must also be able to decrypt them. If someone encrypts a message with a key, only someone else with a matching key should be able to decrypt the message.
This definition is the most basic modern use case for cryptographic keys. Since the internet is a continuous information exchange, maintaining confidentiality is crucial for all participants. It’s very important that no one but you and the receiver of your are able to check the content of the messages you exchange.
When you think about cryptographic keys you can also think of real keys. Your front door key is open and closes your house for whoever has a copy of it. Therefore it’s very important only people you authorize have the key to your house.
iOS uses the Secure Enclave, which is a hardware plus software solution for iPhones since iPhone 5S. The Secure Enclave is responsible among other things to cryptograph all private data inside your iPhone. Some of your most used day-to-day features are handled by it, for example:
- Passcode change
- Enabling or disabling Touch ID or Face ID
- Adding or removing a Touch ID fingerprint or Face ID face
- Touch ID or Face ID reset
- Adding or removing an Apple Pay card
- Erase All Content and Settings
Now you can visualize how important is the role of the Secure Enclave in our lives, right? Anyone could unlock your iPhone if Face ID doesn’t work well. Or worst could use your Apple Pay to pay for unwanted things or delete everything from your iPhone with a priceless loss of your digital content.
In summary, a cryptography key is an input parameter to a cryptographic algorithm or cipher function, which uniquely encodes plaintext (messages or other information) into ciphertext during encryption, and vice versa during decryption.
Cryptographic Keys Types – Symmetric and Asymmetric
Cryptographic keys can be divided into two groups. The symmetric keys and asymmetric keys. All systems over the world use one or more likely both techniques to ensure their protection.
Let’s explain both keys using the example of encrypting a message.
Symmetric Key in Swift
If you use a symmetric key to encrypt a message and send that message, the receiver will need the same key to decrypt it. This way you need somehow to exchange this key with the other participant so it can completely decrypt the message. This can be a problem/disadvantage when you have no safe means of exchanging the symmetric key. Symmetric key advantages are the fast computing encrypt/decrypt process and it’s easy to create new symmetric keys.
Asymmetric Key in Swift
On the other hand, the asymmetric keys are a pair of keys: the public key and the private key. Different from symmetric key techniques each key only does one cryptic operation. The public key only encrypts and the private key only decrypts data.
Going back to our example, in this case, you will encrypt the message with the public key and the receiver will decrypt the message with the private key. You can do most of your applications with asymmetric keys since the public key can be freely shared around and the message won’t be able to be decrypted. If you need some private data from another source, just create an asymmetric key pair(public and private key) and send the public key to it, after that the other source will use the public key to encrypt the data and send it back to you, and finally you can decrypt that data with your private key. The disadvantages of public/private key algorithms are that generating keys is most expensive and most of the time you have to keep each of the private keys stored for each public key sent.
To sum up everything about both of the Keys types. Symmetric key encryption techniques use a single symmetric key for both processes of encryption and decryption, whereas asymmetric key(public and private) techniques use two different but related keys for encryption and decryption.
Ephemeral vs Static Cryptographic keys
The other trait about keys is related to a concept called crypto-period or lifetime. Cryptographic keys may be static (built for the long term) or ephemeral (built to be used for a single session).
Static means the encrypt and decrypt functions are only valid throughout a longer period of time, for example, one month or 2 hours. However, you have to think that the longer the period you are using it, the more susceptible it is to be attacked. It is always important to keep in mind the replacement of the keys when they are static, this is called cycling.
The Ephemeral ones are the safest a key can be. It has a single use and it’s gone. It’s impossible to revert or try to recover that. When you use it, it’s gone forever.
Apple doesn’t support this type of key natively yet but we can create our own key manager to handle that for us. You just need to create something that each time you do the decrypt operation, starts a cycling process of the keys.
For now, this is enough theory about cryptographic keys. Let’s implement them in the Playgrounds!
Code Example – Symmetric Key
First, let’s see an example of symmetric key encryption, you have to import CryptoKit
to follow this example:
let messageData = "Go Go Power Rangers!".data(using: .utf8)! // mark 1 let symmetricKey = CryptoKit.SymmetricKey.init(size: .bits256) // mark 2 print("Symmetric Key -> \(symmetricKey)") let encryptedSealedBox = try! AES.GCM.seal(messageData, using: symmetricKey, nonce: nil) // mark 3 print("Ecrypted Sealed Box Base64 text -> \(encryptedSealedBox.ciphertext.base64EncodedString())") // this decryption usually occurs in other system, so you will have to send somehow the symmetric key to it. let decriptSealedBox = try! AES.GCM.open(encryptedSealedBox, using: symmetricKey) // mark 4 print("Text decrypted -> ",String(data: decriptSealedBox, encoding: .utf8)!)
Explaining each mark:
- We have to transform any object we have into data to be able to use it in the CryptoKit framework. In this case, we are transforming the
String
“Go Go Power Rangers!” - Mark 2 is where we create the randomly generated symmetric key. This key will be used in both process of encrypting and decrypting the
messageData
. - We are using the AES algorithm to encrypt the
messageData
with symmetric key, we created in step 2 and a result is aSealedBox
object, with contains the encrypted data among other things. - Finally we
open
the sealed box, aka decrypt our message using the same key created in step 2.
Did you notice that step 3 and step 4 used the same key? This way is a symmetric algorithm, we use the same key to do all the cryptography operations.
The final result in the console is:
Code Example – Asymmetric Key
Now, let’s explore an example of asymmetric cryptography.
Copy paste the code below:
// Generate salt let randomSymmetricKey = SymmetricKey(size: .bits256) let salt = randomSymmetricKey.withUnsafeBytes { Data($0) } // Mark 1 let playerAPrivateKey = P521.KeyAgreement.PrivateKey() let playerAPublicKey = playerAPrivateKey.publicKey let playerBPrivateKey = P521.KeyAgreement.PrivateKey() let playerBPublicKey = playerBPrivateKey.publicKey // Mark 2 let playerASharedSecret = try! playerAPrivateKey.sharedSecretFromKeyAgreement(with: playerBPublicKey) let playerASymmetricKey = playerASharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: 32) // player B gets the agreement with player A let playerBSharedSecret = try! playerBPrivateKey.sharedSecretFromKeyAgreement(with: playerAPublicKey) let playerBSymmetricKey = playerBSharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: 32) // from here it's the same as the symmetric example but here we will prove that you can use different derived keys to encrypt and decrypt the message let messageData = "Go Go Power Rangers!".data(using: .utf8)! let encryptedSealedBox = try! AES.GCM.seal(messageData, using: playerASymmetricKey, nonce: nil) print("player A sent Ecrypted data derived key text -> \(encryptedSealedBox.ciphertext.base64EncodedString())") let decriptSealedBox = try! AES.GCM.open(encryptedSealedBox, using: playerBSymmetricKey) print("Player B received the Text decrypted with player B derived key -> ",String(data: decriptSealedBox, encoding: .utf8)!)
Imagine that you have two players, player A, and player B. They exchange public keys with each other and created derived symmetric keys from it (of course, the salt should be the same). And then they can exchange crypto messages that both parties will understand.
And that’s it for today!
Continue Studying Cryptography in Swift
Asymmetric key is one of the types mentioned in this article, and you can really deep dive into them in this other article about using asymmetric keys in Swift. There you will find a lot of examples on how to use asymmetric keys in Swift.
Talking about keys, you also have key-derived functions that enable you to sign messages ensuring that they weren’t corrupted or changed from the sender to the receiver. You can find a good article tutorial on that subject here.
Summary – Cryptographic Keys and Swift
Today we explore an introduction to keys in iOS development and how you can leverage the security of your app with an encryption technique. We learned about symmetric and asymmetric keys. We analyzed what are ephemeral and static keys. And in the end we did an example of both key types so you can learn by example.
That’s all my people, I hope you liked reading this article as much as I enjoyed writing it. If you want to support this blog you can Buy Me a Coffee or leave a comment saying hello. You can also sponsor posts and I’m open to freelance writing!
You can reach me on LinkedIn or Twitter and send me an e-mail through the contact page.
Thanks for reading and… That’s all folks.
Credits: