Here's my take on cryptographic agility intended for application developers.
To start, let's review a definition of what cryptographic agility means or requires.
A security system is considered crypto agile if its cryptographic algorithms or parameters can be replaced with ease and is at least partly automated.
- Cryptographic agility
I believe there is a gradient of cryptographic agility:
- You have no idea what crypto is in your system;
- You have an idea of what crypto is in place but any changes require significant effort;
- You have complete track of your crypto and you have reliable transition plans should any changes be required;
- And any changes to your crypto can be managed with configuration to initiate and complete transitions between cryptographic algorithms.
The inability to adjust your cryptography would be the opposite of agile.
What are the experts saying about crypto agility?
Take a listen to Cryptographic Agility: Anticipating, Preparing for and Executing Change from RSA Conference 2020. From this I learned Microsoft found 50 distinct implementations of MD5 in the windows code base. Quite a few interesting recounts are described in this panel.
What do you have to say about crypto agility?
I am only going to talk about what I have actually done. My recommendations come from my professional experience as a developer and now manager. None of this is armchair cryptography.
The application I am responsible for has ascended from crypto-ignorance to crypto-aware with interface points ready for any cryptographic migrations. Appropriate and correctly applied modern cryptography is deployed to production and I expect that no changes will be needed for a few years.
That said, I have not gotten application level cryptography to the point where migrations may be done through configuration. Unlike X.509, application cryptography has a wide set of use cases and solutions. I believe most changes require active human intervention to safely alter and to provide high availability of service during and after the change.
What do I need to do to get as far as you have?
The first step to being agile is to take an inventory of what you are using, for what purpose, and where. When you look, you might find out that the wrong technology is being applied in your code. For example, using RSA encryption for small messages that are encrypted and decrypted on the same server. A symmetric algorithm is more appropriate.
The second step is to stay informed of what's going on in the field. Watch for updates to the tools available in your language of choice. Listen and watch for deprecated or broken algorithms just as you would with security vulnerabilities and see if you are using any of them. For example, JDK 16 added SHA3-256 support and JDK 18 disabled SHA-1 signed jars.
Oh and move away from the old dangerous stuff too! MD5 should not be touched with a 10 foot pole and SHA-1 is broken. Also Bleichenbacher's attack keeps coming back from the dead so stop using RSA.
Resist the urge to apply new algorithms for the sake of being new. You have limited resources and time. Focus on replacing what is broken and the threats you face. These migrations will consume you and your team's time and come with significant risk if done wrong.
If I have to do it multiple times anyway, why don't I find a vendor that makes an extensible turnkey solution to handle every case I have?
You're likely falling for the most expensive snake oil out there. (No offense to snakes intended!) If you are not assessing what you are using cryptography for, then you will certainly fail to integrate a vendor's solution correctly.
Okay, okay. I'll do it myself.
I just added integrity checks to my encryption but someone says it looks wrong on the internet!
Here's the latest #encryption code from #police #cyberAlarm It took me 5 seconds to spot the hilarious flaw. Now it's your turn. Welcome your thoughts @bascule @ProfWoodward @Sc00bzT @grittygrease @matthew_d_green @AlecMuffett @jedisct1 @CiPHPerCoder
Migrations are not easy. Here's some mistakes I see in this example:
- The same function is being used for different versions;
- It is subject to silent downgrade attacks because the signature can be removed;
- The same key is used for both the old and new version;
- AES-CBC is risky to implement in newer versions of anything;
- And the data does not identify and is not bound to which version and key it is encrypted with.
If I did this over again, how should I approach it?
Modify your application in such a way that different versions are delivered and processed with different code paths and that the keys used are unique and not shared. Stop using OpenSSL directly and use a library like libsodium or Google Tink. Bind the fact that this is another version to the encrypted message with authenticated encryption with associated data (AEAD). Plan a timeline for when the old version is no longer accepted and add monitoring to find out how often the old and new code paths are used. And finally verify that the migration is taking place and that the new code path reaches expected levels of use before disabling the old code. For specific recommendations, see Cryptographic Agility Questions.
If you're interested in another take about crypto agility, see: Cryptographic Agility and Superior Alternatives.