Written for Swift 3 with Xcode 8.1
With libraries like CryptoSwift, it’s easier and easier to use encryption in your code. But there are also some common mistakes not to fall into when using cryptography!
The rest of this article will use CryptoSwift as an example.
1. Don’t hard code your cryptographic key
Anything you put in the code is, in a way, readable by anyone. It’s always possible for an attacker to find something, even hidden in the compiled code of your application.
Plus, hardcoding a key means it’s the same encryption key for everyone, witch would make a very bad encryption system since the key is shipped with the app.
One last point is randomness. It’s primordial that a key reflect entropy. It need to be anything. The next byte of a key need to be able anything, and there is no less entropic than an UTF8 string used as a key.
You need to generate a key every time you need one, and store it locally in a safe place.
You can generate a AES256 key this way :
2. Store your keys in the Keychain
Let make things clear right now, there are no better place to store sensitive data like cryptographic keys or password than the Keychain.
It’s designed by Apple to be able to store securely password, certificates and keys. It’s also maintained by regular updates of Apple software, and finally, it uses hardware module like the Secure enclave to assure a high level of security.
TL;DR: Use the Keychain, it the most secure alternative you’ve got!
You can store and access the keychain very simply on your own when you use a wrapper like Keychain-Swift:
3. Set a correct Keychain Item Access
You may have not noticed yet, but I used an access parameter to the keychain setter in point 2.
That is needed to provide a correct level of security for your stored key. It make sure the device is unlocked, prevent backups and keychain sharing between devices, and it can also make sure the device is secured by an unlock code.
4. Use an Initialization Vector
Encrypting data is a good practice to prevent anyone to read sensitive data.
But what if analytics allow an attacker to read your data without the key, just by looking at the encrypted data?
That’s what make Initialization Vector so important!
Let say you need to encrypt a boolean, because you don’t wan’t anyone to figure out who has opt-in and who haven’t.
Let check the storage table after encryption:
|value||no IV (or shared IV)||randomized IV|
Any clue of what’s wrong ? Well, every same value, encrypted with the same key and iv result in the same cipher result.
And that’s bad for your data, because an attacker that would eventually see the data (and trust me, he will on an iOS device except if it’s in the Keychain), can perform some analytics process to deduct the decrypted data.
To prevent that, it’s important to generate a random IV for every encryption you may perform.
Of course this IV is needed to decrypt the data, along with the key. A good place to store the IV is alongside the data, yes, in the table, just like you would do with a salt for a password hash.
5. Do not use ECB block mode
The block mode you set in the AES algorithm correspond to the method used by the algorithm to perform the encryption.
The choice of a good block mode is primordial to make the encryption useful and secure.
But why is ECB a very poor choice?
ECB stand for Electronic Code Book, that encrypt every block of your input separately. The treat is that this method will encrypt the same way two same blocks, and just like the lack of Initialization Vector, makes the encryption predictable.
It can also lead to replay attacks and information leaks.
If you want to be confident about the ECB lack of security, check this example of encryption using an image, from Wikipedia.
Wow, with ECB block mode, we cannot say that the content of the picture became unpredictable and unreadable. That’s why it should never be used as a cryptographic block mode.
To prevent that, use CBC (Cipher Block Chaining) that make the next block encryption dependent from the previous one, and make the result unpredictable and randomized.
Although it’s very easy to use encryption today as a developer, it’s also very easy to make a lot of mistakes when using AES, making the whole process unsecure and, sometime, useless.
The main reason is that when dealing with encryption, it’s important to know what you do, what you’re dealing with, and also the classic errors to avoid.
I hope that your app will become a little bit more secure with what you just read!