英文:
use Azure Blob storage encryption without keyvault
问题
在BtoB应用程序中,我想在Azure Blob存储中透明地加密数据。
然而,我们不能将密钥存储在密钥库中:
我们将生成一个对称密钥,并使用它来加密Blob存储中的数据。
然后,将使用客户的公钥加密此对称密钥,并存储在某个位置。
如果需要解密,客户将使用自己的私钥解密对称密钥。
我们找到的所有示例都使用密钥库来存储密钥。
最相关的示例是https://learn.microsoft.com/en-us/azure/storage/blobs/client-side-encryption?tabs=dotnet#blob-service-encryption。
这份文档说:您的密钥和密钥解析器实例,可以通过Azure Key Vault SDK或外部实现。
但没有文档解释如何进行"外部实现"。
我尝试了以下代码来生成KeyEncryptionKey:
var symmetricSecurityKey = new SymmetricSecurityKey(_context.EncryptionKey);
var jsonWebKey = JsonWebKeyConverter.ConvertFromSymmetricSecurityKey(symmetricSecurityKey);
jsonWebKey.AdditionalData["iv"] = Convert.ToBase64String(_context.IV);
string jsonSerializedKey = JsonSerializer.Serialize(jsonWebKey);
Azure.Security.KeyVault.Keys.JsonWebKey keyvaultKey = (Azure.Security.KeyVault.Keys.JsonWebKey)JsonSerializer.Deserialize<Azure.Security.KeyVault.Keys.JsonWebKey>(jsonSerializedKey);
keyvaultKey.KeyType = KeyType.Rsa;
var cryptoClient = new CryptographyClient(keyvaultKey);
var keyResolver = new KeyResolver(new DefaultAzureCredential());
// 我们希望从客户端库传递密钥
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V2_0)
{
KeyEncryptionKey = cryptoClient,
KeyResolver = keyResolver,
// 在调用IKeyEncryptionKey.WrapKey()时客户端库将使用的字符串值
KeyWrapAlgorithm = "RSA-OAEP"
};
它编译通过,但在执行时,对_rootContainer.UploadBlobAsync(fullPath, stream)的调用引发了此错误:
Operation WrapKey is not supported with the given key
显然,它尝试加密或解密对称密钥。
如果不指定KeyWrapAlgorithm,它会返回:
Value cannot be null. (Parameter 'KeyWrapAlgorithm)
<details>
<summary>英文:</summary>
In a BtoB application, I want to encrypt data transparently in Azure Blob storage.
However, we cannot store the keys in keyvault:
We will generate a symmetric key and use it to encrypt data in blob storage.
This symmetric key will then be encrypted using the public key of the customer and stored somewhere.
If a decryption is needed, the customer will decrypt the symmetric key using his private key.
All the samples that we have found are using keyvault to store the keys.
The most relevant sample is https://learn.microsoft.com/en-us/azure/storage/blobs/client-side-encryption?tabs=dotnet#blob-service-encryption.
This doc says: Your key and key resolver instances, either through Azure Key Vault SDK or an external implementation.
But no documentation explains how to do the "external implementation"
I tried this code for generating the KeyEncryptionKey:
var symmetricSecurityKey = new SymmetricSecurityKey(_context.EncryptionKey);
var jsonWebKey = JsonWebKeyConverter.ConvertFromSymmetricSecurityKey(symmetricSecurityKey);
jsonWebKey.AdditionalData["iv"] = Convert.ToBase64String(_context.IV);
string jsonSerializedKey = JsonSerializer.Serialize(jsonWebKey);
Azure.Security.KeyVault.Keys.JsonWebKey keyvaultKey = (Azure.Security.KeyVault.Keys.JsonWebKey)JsonSerializer.Deserialize<Azure.Security.KeyVault.Keys.JsonWebKey>(jsonSerializedKey);
keyvaultKey.KeyType = KeyType.Rsa;
var cryptoClient = new CryptographyClient(keyvaultKey);
var keyResolver = new KeyResolver(new DefaultAzureCredential());
// We want the key to be passed from
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V2_0)
{
KeyEncryptionKey = cryptoClient,
KeyResolver = keyResolver,
// String value that the client library will use when calling IKeyEncryptionKey.WrapKey()
KeyWrapAlgorithm = "RSA-OAEP"
};
It compiles, but at execution time, the call to _rootContainer.UploadBlobAsync(fullPath, stream) raises this error:
Operation WrapKey is not supported with the given key
Apparently, it tries to encrypt or decrypt the symmetric key.
If I don't specify KeyWrapAlgorithm, it returns:
Value cannot be null. (Parameter 'KeyWrapAlgorithm)
</details>
# 答案1
**得分**: 1
不确定在您的实际情况下是否相关,但您提到了“如果需要解密,客户将使用他的私钥解密对称密钥”,这似乎意味着它不是连续使用的数据。因此,这里有一个建议,它并不完全回答您的确切问题,但提出了一个实现几乎相同结果的替代路径,您需要编写的代码要少得多!
我是AxCrypt的原始作者,这是一个相当知名的文件加密应用程序。最近,我发布了一个命令行工具箱,我认为在加密/解密方面支持您的情况。它使用了与AxCrypt相同的核心加密代码,多年来一直被证明有效,使用了经过验证的强大和经过充分试验的算法和操作模式。它可以生成非对称密钥对(RSA-4096),像您描述的那样安全地包装私钥,并使用公钥加密用于加密数据的对称密钥。它实际上不会使用Azure客户端加密库,但最终效果几乎相同。Azure中的加密blob,可以使用私钥解密。
这是一个命令行实用程序,可以被脚本或C#/.NET代码调用,并具有丰富的功能集。您可以在GitHub上找到它,网址为https://github.com/xecrets/xecrets-file-cli,根据GNU GPL v3许可证发布。尽管CLI包装器最近发布,但底层加密已经在生产中使用了7多年,并且被广泛使用,因此可以被视为稳定和可靠。文档中包含了完整的示例,几乎包括您的情况。
当然,您还可以像CLI一样直接链接到底层库 - 但是那么您的代码将受到GPL要求的影响,即您的代码也必须成为GPL。如果您使用原样的CLI,这不是问题,只有CLI是并且仍然是GPL。
作为一个附带的好处,如果blob以文件的形式下载,它可以在Windows、macOS和Linux上使用命令行CLI手动解密,或者使用桌面应用程序(我们很快将发布一个,目前处于测试阶段),甚至是现有的AxCrypt,如果他们确实需要自行解密,对您的客户可能会有好处。
如果出于任何原因,您确实需要使用Azure库,那么这个建议当然就不相关了。
<details>
<summary>英文:</summary>
Not 100% sure if it's relevant depending on your actual scenario, but you do write "If a decryption is needed, the customer will decrypt the symetric key using his private key." which seems to imply that it's not data that is used continuously. So here's a suggestion that doesn't really answer your exact question, but proposes an alternate path to achieve much of the same result with much less code for you to write!
I am the original author of AxCrypt, a fairly well-known file encryption app. Recently I published a command line toolbox, that I think supports your scenario as far as the encryption/decryption goes. It uses the same core encryption code as AxCrypt, that has been proven over the years, using sound and well tried algorithms and modes of operation. It can generate asymmetric key pairs (RSA-4096), wrap the private key securely as you describe, and use the public key to encrypt a symmetric key that is used in encrypting the data. It won't actually use the Azure client encryption library, but the net effect will be pretty much the same. An encrypted blob in Azure, that can be decrypted using a private key.
It's a command line utility that can be called by scripts or C#/.NET code, and has an extensive set of features. You can find it at github at https://github.com/xecrets/xecrets-file-cli licensed under GNU GPL v3. Although the CLI wrapper is recently published the underlying cryptography has been in production for over 7 years, and used extensively so it can be regarded as stable and solid. There are complete examples in the documentation, including pretty much your scenario.
You can of course also link directly with the underlying library just like the CLI does - but then your code will be affected by the GPL requirement that your code also becomes GPL. If you use the CLI as-is this is not an issue, only the CLI is and remains GPL:ed.
As a side benefit, if the blob is downloaded as a file, it can be decrypted manually on the command line using the CLI on Windows, macOS and Linux, or using a desktop app (we're soon releasing one, it's in beta right now), and even the existing AxCrypt, which can be a benefit for your customers if they do require to decrypt it themselves.
If for whatever reason you really need to use the Azure library, then this suggestion is not relevant of course.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论