Using HMAC-based Key Derivation Function to create Authentication Message Codes in Swift
Hallo mensen, Leo Hier.
This is my first post abroad, now writing from Netherlands! 🎉🎉🎉 I was missing to write here and talk to you.
Now I'm more or less settle down for a bit and I have time to post a really quick article about iOS and Cryptography. Today will talk about a key derivation function using CryptoKit. This comes handy when you have to share secrets between two recipients. We will derive a symmetric key from some info ( and that can be random and public for everyone) and after that we will just create a authentication code to a message so everyone can assure that message/data is trustworthy.
Let's code but first...
The painting I choose today is Man Writing a Letter (1662-1665), from Gabriël Metsu. Born at 1629 and died at 1667 was a Dutch painter of history paintings, still lifes, portraits, and genre works. He was "a highly eclectic artist, who did not adhere to a consistent style, technique, or one type of subject for long periods". Only 14 of his 133 works are dated.
I choose because is my first post in Netherlands, so a Dutch painter is more than appropriate. And secondly the post is talking about how to ensure that the message content wasn't modified. So a man writing a letter is suitable because in the old days they used to use was and a signed ring to ensure that the content of a letter wasn't modified from the sender to the receiver.
You want to create a message authentication string using SHA256 and the key creation is based on the same hash function using HMAC-based Key Derivation Function
Let's first explain what HMAC-based Key Derivation Function is. This is just one form of a KDF, Key derived Function. In short terms is just a function that you use some Data to input and it gives you a pseudorandom symmetric key as output. As wikipedia says:
A key derivation function (KDF) is a cryptographic hash function that derives one or more secret keys from a secret value such as a main key, a password, or a passphrase using a pseudorandom function. KDFs can be used to stretch keys into longer keys or to obtain keys of a required format, such as converting a group element that is the result of a Diffie–Hellman key exchange into a symmetric key for use with AES. Keyed cryptographic hash functions are popular examples of pseudorandom functions used for key derivation.
Our workflow will be this:
1 - every interested part has to know the key input material AND the key generation function, in this case is HKDF( HMAC-based Key Derivation Function). 2 - You generate the key using the input material and the HKDF. 3 - Use the key in an HMAC with any hash function that you want ( in our case is SHA256 for both derivation and and authentication code creation) to create the authentication code 4 - Send the code and the authentication code together for anyone who wants to assert if the message wasn't modified.
Let's start creating the symmetric key based on some input.
First we need the input material. This should be shared with both ends, this string can and should be public because if not, no one can verify the authentication code later. This is because we are not giving the symmetric key for anyone. This will be done only sharing the string input material.
let secretPassword = "inputMaterialString".data(using: .utf8)! // Mark 1 let hkdfResultKey = HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: secretPassword), outputByteCount: 151) // Mark 2
With the code above you on Mark 1 we just create a Data from a String. This String is exactly what we talk in the workflow as the "Key Input Material". So when we talk about sharing the key input material, this is what we are talking about. The mark 2 is where we use the HKDF CryptoKit Struct to call the deriveKey static function to generate a 151 byte long symmetric Key that we can use to do other cryptography operations such as create an authentication code for any Data. There are two inputs to the function on Mark 2: the first one is the Data that you are using as input material for you key and the second is the size in Bytes of the key you want to generate.
To test if the size is right just print the value divided by 8 :
print("The generated key size (in bytes): ",hkdfResultKey.bitCount/8)
So yeah the most difficult part is gone, now you can use your symmetric as you want. Today we will use it to create an authentication code that you can use to ensure that the message didn't change.
Let's create a message to be verified and the authentication code:
let trustfulMessage = "The message that would be verified by the authentication code".data(using: .utf8)! let authenticationCode = HMAC<SHA256>.authenticationCode(for: trustfulMessage, using: hkdfResultKey) // Mark 2 print("\(authenticationCode.description)")
The result is:
The code above demonstrates how you can generate an authentication code in Mark 2 and you just need to input a Data struct and the key we generate above.
So now if someone want to check if the message was modified, he can use the input material to generate a key like us and generate the authentication code. As no one else will know how to derive the key, WE ARE SAFE! And... it's done!
Very cool isn't it?
The whole code you can check below and test in your playgrounds:
import CryptoKit let secretPassword = "inputMaterialString".data(using: .utf8)! let hkdfResultKey = HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: secretPassword), outputByteCount: 151) print("The generated key size (in bytes): ",hkdfResultKey.bitCount/8) let trustfulMessage = "The message that would be verified by the authentication code".data(using: .utf8)! let authenticationCode = HMAC<SHA256>.authenticationCode(for: trustfulMessage, using: hkdfResultKey) print("\(authenticationCode.description)")
There's a way to derive keys using CryptoKit from almost every kind of input. This way you can create very complex cryptography operations with just a few steps.
That's all my people, I hope you liked this as I liked writing. If you want to support this blog you can Buy Me a Coffee or just leave a comment saying hello.
Thanks for the reading and... That's all folks.
Interested in reading more such articles from Leonardo Maia Pugliese?
Support the author by donating an amount of your choice.