The need for software security in client-side applications has never been greater.
That’s an easy statement to make, and it quickly becomes justified by the stream of news stories about malware targeting mobile apps, compromised desktop applications, and websites leaking credit card information.
Our lives are increasingly managed through online services and mobile apps. That means all the sensitive—and often highly private—data that defines who we are passes through our computers and phones. No wonder people take it seriously.
The challenge isn’t restricted to consumer apps. The same techniques that are used against consumer apps are also used to attack professional software—enabling the theft of business secrets.
This means cryptography is required to protect sensitive data.
Software engineers and security architects understand the need to encrypt sensitive data at rest and in transit. The techniques and protocols to achieve that are well understood. But how do you protect the cryptographic keys that unlock the data?
If you look online, you’ll find a few different definitions of cryptography, but they all center around the idea that “Cryptography is the application of mathematical operations to keep information secure by transforming it into a form that unintended recipients cannot understand.”
Keeping information secure means two things: firstly, keeping it private, and secondly, ensuring its integrity—ensuring the data hasn’t been corrupted or influenced.
At a high level, cryptographic algorithms—the encapsulation of those mathematical operations—take two inputs: the data to be operated on and the key. In non-scientific terms, the algorithms combine the two together. The key brings a uniqueness to the operation, stopping anyone from just running the decrypt algorithm to decipher the data. Therefore, keeping the key secret is the crucial part to protecting the privacy and integrity of the data.
If the key can be uncovered, then the data is no longer secure.
What does that mean for client-side applications? Well, very simply, it means the key must never be in the clear within the app.
This is because all software is vulnerable to reverse engineering.
Reverse engineering falls into two broad categories: static analysis and dynamic analysis.
Static analysis involves cracking the app open and looking at its code. Open source tools are readily available to do this. A popular example is Jadx which takes about five minutes to see the code of any Android app. If you’ve put secrets in there, any attacker will find them.
Dynamic analysis is looking at the code and memory while the app is running. Developers commonly do this when debugging their apps. But attackers can do it with published apps, too. In an attacker’s hands, this can reveal a lot of detail about the behavior of the app - from what data is in memory, to looking at network traffic before it enters the encrypted transit pipe. While it requires slightly more skill than static analysis, all the tools and training materials are freely available to download.
That means developers should never have sensitive data, like crypto keys, in the clear—not in code and not in memory. It doesn’t take any dark web magic to find them, just a little time with Google.
We’ve established that you can’t hard-code cryptographic keys into your apps. Furthermore, methods to generate the keys in-app, or over-the-air provisioning of keys, will be vulnerable to dynamic analysis.
Thankfully the problem isn’t new and isn’t unique. Technologies exist specifically to solve it.
The three most common options available to developers are:
All three have their pros and cons, which are discussed in more detail in the next article in this series.
Director of Product Management, Neal Michie, discussed this subject at Droidcon San Francisco on the 8th of June 2023.