Azure Storage is one of the most widely used services in the Microsoft Azure cloud, and is the Azure equivalent of the AWS S3 service. Most users of the service know that it is wise to encrypt sensitive data before storing it in the cloud. In this post, we will look at how that can be done using the Azure Java SDK, and will use the Cryptosense Analyzer Platform to gain insight into how the Azure SDK encrypts your data.
Note that in this post we are only talking about client-side encryption, where the sensitive data is encrypted locally, before being sent to the server. Server-side encryption is also available, but this is only applied to the data at rest, so the data is decrypted (briefly) on Azure servers each time it is accessed. When using Azure Storage, as the API documentation explains, client side encryption can be enforced by changing a setting in your application, causing anyy unencrypted upload to be rejected.
Client side Encryption in the Azure Java SDK
The Azure Java SDK uses the envelope encryption technique to protect data. When the client sends data to the server, it encrypts the data with a unique data key. The data key is itself wrapped (encrypted) using a ‘master key’. The encrypted data key is sent and stored on the server as metadata for the encrypted file. When the client wants to download the data from the server, it gets the encrypted data along with the encrypted data key. The client unwraps the data key using the master key and decrypts the data using the data key.
However, we still have to manage the master key: the Azure SDK can use master keys stored locally or stored in the Azure Key Vault (or a mixture of both). The main difference between using local or Key Vault master keys is the location where the data key wrapping happens (the encryption of the file contents always happens on the client):
- If the master key is stored in the Azure Key Vault, the content key is wrapped/unwrapped inside the Key Vault: therefore the master key never leaves the Key Vault
- If the master key is stored locally, the wrapping/unwrapping happens locally
Under the Hood
The Azure SDK documentation gives some information on what encryption modes are used for client-side encryption, but find out what algorithms are actually being used we can use the Cryptosense Analyzer Platform.
We have 3 use cases to test:
- Encryption using a local symmetric master key.
- Encryption using a local asymmetric master key.
- Encryption using a master key stored in the Azure Key Vault.
After running all three tests, the first thing we can see is that in all three cases the file contents is encrypted using AES-CBC mode with PKCS5 padding. This is a worry, because these modes don’t guarantee that the ciphertext has not been tampered with, and can often lead to padding oracle attacks on the underlying plaintext if the application is not extremely careful about treating decryption errors.
Analyzer output showing encryption of the file contents
There are a couple of ways to mitigate this problem. Generally, AES_CBC should be replaced by an authenticated mode (such as AES-CCM or AES-GCM). However, the Azure documentation specifies that AES-CBC is used in order to allow ranged download of the content, so this is not an option for the SDK. In this case, authentication using HMAC over the ciphertext can provide the same security.
Looking at the rest of the results, we can see that HMAC authentication is performed over the HTTP request. However, the SDK does not perform HMAC authentication over the ciphertext. Using dynamic analysis allows us to see what really happens in the application, and this is an example of where that is useful.
By looking at the stack trace, we can see that HMAC is performed on a HTTP request
The next thing we can check is the wrapping and unwrapping of the data key. If we store the master key in the Key Vault, we do not see any key wrapping, which shows that the data key is correctly wrapped inside the Key Vault rather than the master key being made available to the local code.
When we use a local key, we can see the wrapping being performed. The algorithm used depends on the key: if the key is symmetric, AES KW is used; if the key is asymmetric, RSA/ECB/OAEPWithSHA1AndMGF1Padding is used. Both of these methods are considered secure.
The call arguments show us that AES Wrap is for an AES master key
The call arguments show us that RSA/ECB/OAEPWithSHA1AndMGF1Padding is used for an RSA master key
Control your crypto
In this post we investigated how client side encryption actually works when using Azure Storage.
You can use Cryptosense Analyzer to check that all cryptography in our applications – including cloud SDKs – is secure and compliant. For a demo get in touch here.