Azure Table 不使用 KeyVault 的存储客户端加密

Azure Table Storage Client Side Encryption WITHOUT Using KeyVault

我有一些敏感信息需要加密并存储在 Azure Table 存储中。老实说,从一种天真的方法来看,对所有值使用相同的 AES 密钥可能就足够了,因为我绝不会接近加密足够的数据以便某人进行任何有意义的密码分析的方法。但是,我知道最好的做法是限制同一​​对称密钥的使用。

最近,Microsoft 通过 Azure KeyVault 为 Azure Table 存储发布了客户端加密。它允许您生成 RSA 密钥并将其存储在 KeyVault 中,客户端库将为 table 存储中的每一行生成一个新的对称密钥,并使用您的 RSA 密钥加密对称密钥。这是完美的,因为没有办法对密文进行差分密码分析,因为它们都使用不同的密钥。它特别好,因为他们的库完成了所有的管道工作,你所要做的就是从 KeyVault 中获取你的 RSA 密钥,用 EncryptPropertyAttribute 装饰你指定的属性,它会处理其他所有事情。

问题就在这里……我个人觉得 KeyVault 的使用和管理有点笨拙。您必须使用 powershell 在您的应用程序和 keyvault 之间设置 oauth 身份验证,这看起来存储单个 RSA 密钥的开销很大。如果我们有数百个密钥要存储,我可以想象它会更有用。

有没有办法在不将 RsaKey 存储在 KeyVault 中的情况下使用 Microsoft 的所有客户端加密代码?

我花了一些时间才找到它,但是是的,您可以将 RSA 密钥存储在 KeyVault 之外。您只需要使用 RsaKey 构造函数重载,它接受您从任何您认为谨慎的地方获取的 RSACryptoServiceProvider 。我从 web.config 中取出我的。但是,我确保我的生产 RsaCsp 没有存储在源代码管理中,我直接将它添加到 Azure Web 应用程序配置屏幕中。

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;
        }

    }
}

Microsoft.Azure.KeyVault.Cryptography中,RsaKey构造函数发生了变化。 现在它不从RSACryptoServiceProvider导入密钥,而是直接使用它,并在Dispose()方法中处理它。所以用法将更改为:

    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);
        }
    }

请注意,RSACryptoServiceProvider 的实例未被释放。 还要注意 RsaKeyIDisposable.