viggity
viggity

Reputation: 15237

Azure Table Storage Client Side Encryption WITHOUT Using KeyVault

I've got some sensitive information that I want to be encrypted and stored in Azure Table Storage. Honestly, from a naive approach, using the same AES key for all values probably would be sufficient as I would nowhere near approach having enough data encrypted in order for someone to do any meaningful cryptanalysis. But, I know that the best practice is to limit usage of the same symmetric key.

Recently, Microsoft released client side encryption for Azure Table Storage via Azure KeyVault. It allows you to generate an RSA key and store it in KeyVault and the client library will generate a new symmetric key for every row in table storage and it encrypts the symmetric key with your RSA key. This is perfect because there is no way to do differential cryptanalysis on the ciphertext since they all used different keys. It is especially nice because their library does all the plumbing, all you have to do is grab your RSA key from KeyVault, decorate your designated properties with the EncryptPropertyAttribute and it handles everything else.

Therein lies the rub... I personally find KeyVault kind of obtuse to use and manage. You have to use powershell to set up oauth authentication between your app and keyvault and it looks like a tremendous amount of overhead for storing a single RSA key. If we have hundreds of keys to store, I can imagine it would be much more useful.

Is there any way to use all of Microsoft's client side encryption code without storing the RsaKey in the KeyVault?

Upvotes: 2

Views: 1527

Answers (2)

Alexander Tarasenkov
Alexander Tarasenkov

Reputation: 21

In Microsoft.Azure.KeyVault.Cryptography, there is a change in RsaKey constructor. Now it does not import key from RSACryptoServiceProvider, but uses it directly, and disposes it in Dispose() method. So usage will change to:

    public RsaKey GetFromXmlString(string xmlString)
    {
        try
        {
            var rsaCsp = new RSACryptoServiceProvider(2048, new CspParameters() { KeyContainerName = "MyTableStorageRsaKey" });
            rsaCsp.FromXmlString(xmlString);
            rsaCsp.PersistKeyInCsp = false;
            return new RsaKey("MyTableStorageRsaKey", rsaCsp);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("Invalid rsa key xmlString provided", ex);
        }
    }

Notice that instance of RSACryptoServiceProvider is not disposed. Also notice that RsaKey is IDisposable.

Upvotes: 2

viggity
viggity

Reputation: 15237

It took me a while to find it, but yes, you can store your RSA key outside of KeyVault. You just need to use the RsaKey constructor overload that takes in an RSACryptoServiceProvider that you grab from wherever you deem prudent. I grab mine out of my web.config. However, I make sure that my production RsaCsp is not store in source control and I add it directly in the Azure Web App configuration screen.

IKey tableStorageKey = GetTableStorageKey()
_tableRequestOptions = new TableRequestOptions
{
    EncryptionPolicy = new TableEncryptionPolicy(tableStorageKey, null)
};

...

private IKey GetTableStorageKey()
{
    using (var rsaCsp = new RSACryptoServiceProvider(2048))
    {
        try
        {
            //it doesn't really matter where you get your RsaCsp from, I have mine in my webconfig
            XmlDocument doc = new XmlDocument();
            doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            XmlElement node = doc.SelectSingleNode("/configuration/MyTableStorageRsaKey") as XmlElement;

            rsaCsp.FromXmlString(node.OuterXml);

            return new RsaKey("MyTableStorageRsaKey", rsaCsp);
        }
        finally
        {
            rsaCsp.PersistKeyInCsp = false;
        }

    }
}

Upvotes: 5

Related Questions