Practical Cryptography for the Internet of Things
The Internet of Things (IoT) is starting to get a bad reputation – every day it seems like we hear of another way an insecure IoT device was compromised. One of the only ways that the IoT can become a more secure is through the proper use of cryptography. And not the home-spun, bring-your-own type of cryptography. There are a lot of stories of do-it-yourselfers underestimating what it takes to build a secure device only to end up making nothing more than a fun game for a hacker. And there’s not much of an excuse for not using tried and true, standards-compliant cryptographic algorithms with the plethora of encryption libraries available for nearly any programming language. Here is just a few practical ways modern cryptography can help make the IoT a safer, more reliable place.
Encrypted Communication Protocols
The single biggest area of use of cryptography in the internet of things is in securing the communication channels. IoT-centric communication protocols like MQTT and AMQP allow developers to use Transport Layer Security (TLS) to ensure all data sent over the network is unreadable to outside parties. TLS is the rightful heir to the better known standard known as Secure Sockets Layer (SSL), which was the long-time standard for web encryption (see HTTPS) but is now considered insecure. TLS ensures that data between two entities is not readable nor prone to manipulation by third parties.
In addition to encrypting the main data connections, it’s also important to encrypt any available secondary communication channels such as those use for maintenance or customer features. For instance, if an IoT devices comes with a web portal for use by consumers (think of a web interface for a printer) that should also come encrypted by default. If not, anyone on the same network could intercept usernames, passwords or use session data to impersonate those logged in to control these devices. For the same reason, insecure maintenance interfaces like telnet should be shuttered in favor of secure approaches like Secure Shell (SSH).
Hashed Passwords with Salt
There is a well known adage that states that the most secure systems are those with nothing to steal. Storing hashed passwords is one way to accomplish this. A hash is a cryptographic function that will take any input and create a unique, irreversible, yet consistent set of bits. Good hash algorithms are nearly impossible to reverse. In other words, once a password is hashed, you shouldn’t be able to reverse the hash to determine what the password was. However, the hash can still be used to validate submitted passwords because the same input to a hashing function will return the same output or hash. Some examples of hashing functions are MD5 (popular but no longer considered secure), SHA-256 and Blowfish.
One popular attack on hashing is to produce what’s called a rainbow table or look-up table. This is a table where every conceivable (or at least common) text input is hashed and its corresponding output is stored. This allows someone to quickly do a reverse lookup with a hash’s output. If a hacker were to retrieve a list of password hashes from a compromised system, it wouldn’t be hard to reverse these hashes to their original values using a rainbow table. This attack, however, can be mitigated through the use of what’s called a salt. The salt is a set of random data that is appended to a string before it is hashed. The salt is also stored with the hash result, but changes for every hash computed so that no two hashes would use the same salt. Because the salt makes passwords (if that’s what you’re hashing) so much longer and more random, it renders rainbow tables useless. It is too computationally intensive to generate rainbow tables on every large, random string.
Private Key Authentication
Private key cryptography is asymmetric encryption which provides two keys, one public and one private. If data is encrypted with the private key, it can only be decrypted with the public key, and vice versa. Keeping the private key private then allows a single machine to securely communicate with the outside world or authenticate with remote machines. This bit of cryptographic functionality is particularly well suited for a couple aspects of IoT infrastructure.
The first is the authentication of a single machine that joins an IoT network. For example, an end node may need to connect to a central MQTT broker to publish data upstream. Using private key authentication gives each machine a secret and unique identifier when joining the network (eliminating the oft-used insecure global credential approach) and due to their length are virtually impossible to brute force (which is where a machine is programmed to guess values).
The second area where private keys can help in IoT is in the verification of messages between devices. A hash or other integrity-checking algorithm would be computed on a message (such as a firmware image) and then encrypted with a private key and appended to the message. Then that check is decrypted by the message receiver with the public key, which proves that it could only have been generated by the holder of the private key. Finally, the result of the integrity-check is validated to ensure the message was not compromised or altered in transit. This sort of electronic signature can be useful in situations where a secure communication channel is unavailable.
Signed Firmware and Secure Boot
The electronic signature approach described in the previous section is also something that can be used for secure boot and the signing of firmware images. This so-called signature ensures that an authorized user or machine has put its stamp of approval on the firmware before its executed. It makes it much harder for a malicious individual to create rogue firmware and hijack a machine – they wouldn’t be able to sign the code they’ve created.
Secure boot is the feature that utilizes this, ensuring that any code that is set to run on a device is appropriate singed. The very first bits of code a device will run after it is booted includes functionality to compute and verify the electronic signature. Furthermore, the use of a private key infrastructure (PKI) with secure boot gives maintainers a pathway to remediation in the event that the secret key used to sign code is compromised.
Now on to Resource-Constrained Devices
This is all well and good, you might think, but if you work in IoT for any length of time, you will come across situations where you are using resource-constrained devices at the edge. These devices have restricted power, processing, memory and can give developers some big technical hurdles. Unfortunately, modern cryptography can be a resource hog and so the question naturally arises: How do we build devices that are safe and secure while also meeting the constraints placed on them?
Don’t dismay! Smart compromises can be made in these environments. For instance, if data integrity is important but not necessarily the secrecy of the data, then full-encryption of data streams can be forgone for a simpler scheme where a hash is computed with a shared, secret salt – a poor man’s electronic signature, you might say. This would allow the receiving system to validate the data and ensure, with some confidence, that the data was generated by authorized machines. It’s less than ideal but might be an acceptable risk in some environments. This is just one example, but the idea is that with some creativity and a good working knowledge of cryptography, you can effectively balance these risks and security within IoT systems.