队列的客户端加密
用于 .NET 和 Python 的 Azure 队列存储客户端库支持在上传到 Azure 存储之前加密客户端应用程序中的数据,并在下载到客户端时解密数据。 这些客户端库还支持与 Azure Key Vault 集成,以便管理存储帐户密钥。
重要
Azure 存储同时支持服务端和客户端加密。 对于大多数场景,Azure 建议使用服务端加密功能,以便于保护数据。 若要详细了解服务端加密,请参阅静态数据的 Azure 存储加密。
关于客户端加密
Azure 队列存储客户端库使用 AES 来加密用户数据。 客户端库中提供了两个版本的客户端加密:
- 版本 2 使用 AES 的伽罗瓦计数器模式 (GCM) 模式。
- 版本 1 结合使用加密块链接 (CBC) 模式与 AES。
警告
由于客户端库的 CBC 模式实现中存在安全漏洞,因此不再建议使用版本 1 客户端加密。 有关此安全漏洞的详细信息,请参阅 Azure 存储更新 SDK 中的客户端加密以解决安全漏洞。 如果当前正在使用版本 1,建议更新应用程序以使用版本 2,并迁移数据。 有关进一步指导,请参阅以下部分:缓解应用程序中的安全漏洞。
缓解应用程序中的安全漏洞
由于在队列存储客户端库的 CBC 模式实现中发现了安全漏洞,因此 Azure 建议立即执行以下一项或多项操作:
考虑使用服务端加密功能,而不是客户端加密。 有关服务端加密功能的详细信息,请参阅静态数据的 Azure 存储加密。
如果需要使用客户端加密,请将应用程序从客户端加密 v1 迁移到客户端加密 v2。
下表总结了在选择将应用程序迁移到客户端加密 v2 时需要执行的步骤:
客户端加密状态 | 建议的操作 |
---|---|
应用程序将客户端加密与仅支持客户端加密 v1 的客户端库版本配合使用。 | 更新应用程序以使用支持客户端加密 v2 的客户端库版本。 有关受支持版本的列表,请参阅客户端加密的 SDK 支持矩阵。 更新代码以使用客户端加密 v2。 |
应用程序将客户端加密与支持客户端加密 v2 的客户端库版本配合使用。 | 更新代码以使用客户端加密 v2。 |
此外,Azure 建议执行以下步骤来帮助保护数据:
- 将存储帐户配置为使用专用终结点来保护虚拟网络 (VNet) 和存储帐户之间通过专用链接的所有流量。 有关详细信息,请参阅对 Azure 存储使用专用终结点。
- 仅限制对特定网络的网络访问。
客户端加密的 SDK 支持矩阵
下表显示了哪些版本的适用于 .NET 和 Python 的客户端库支持哪些版本的客户端加密:
.NET | Python | |
---|---|---|
客户端加密 v2 和 v1 | 版本 12.11.0 及更高版本 | 版本 12.4.0 及更高版本 |
仅客户端加密 v1 | 版本 12.10.0 及更早版本 | 版本 12.3.0 及更早版本 |
如果应用程序将客户端加密与早期版本的 .NET 或 Python 客户端库配合使用,则必须首先将代码升级到支持客户端加密 v2 的版本。 接下来,必须使用客户端加密 v2 解密和重新加密数据。 可以根据需要在迁移代码时并行使用支持客户端加密 v2 的客户端库版本和更早版本的客户端库。
客户端加密的工作原理
Azure 队列存储客户端库使用信封加密来加密和解密客户端上的数据。 信封加密使用一个或多个其他密钥来加密密钥。
队列存储客户端库依赖于 Azure Key Vault 来保护用于客户端加密的密钥。 有关 Azure Key Vault 的详细信息,请参阅什么是 Azure Key Vault?。
通过信封技术加密和解密
通过信封技术加密的工作方式如下:
Azure 存储客户端库生成内容加密密钥 (CEK),这是一次性使用对称密钥。
使用此 CEK 对用户数据进行加密。
然后,使用密钥加密密钥 (KEK) 对此 CEK 进行包装(加密)。 KEK 由密钥标识符标识,可以是非对称密钥对或对称密钥。 可在本地管理 KEK 或将其存储在 Azure Key Vault 中。
Azure 存储客户端库本身永远无法访问 KEK。 该库调用密钥保管库提供的密钥包装算法。 用户可以根据需要选择使用自定义提供程序进行密钥包装/解包。
然后,将加密数据上传到 Azure 队列存储。 通过已加密数据插入包装的密钥和一些其他加密元数据。
通过信封技术解密的工作方式如下:
- Azure 存储客户端库假定用户在本地或 Azure Key Vault 中管理 KEK。 用户不需要知道用于加密的特定密钥。 但是,可以设置和使用一个密钥解析程序,将不同的密钥标识符解析为密钥。
- 客户端库下载存储在 Azure 存储中的已加密数据以及任何加密材料。
- 然后使用 KEK 解包(解密)包装的 CEK。 在此过程中,客户端库无权访问 KEK,但仅调用 Azure Key Vault 或其他密钥存储的解包算法。
- 客户端库使用 CEK 解密已加密的用户数据。
消息加密/解密
由于队列消息可以采用任何格式,客户端库定义一个自定义格式,其在消息文本中包括初始化向量 (IV) 和已加密的内容加密密钥 (CEK)。
在加密过程中,客户端库将生成 16 字节的随机 IV 和 32 字节的随机 CEK,并使用此信息对队列消息文本执行信封加密。 然后,将已包装的 CEK 和一些附加加密元数据添加到已加密的队列消息中。 修改后的消息将存储在服务中。
<MessageText>{"EncryptedMessageContents":"6kOu8Rq1C3+M1QO4alKLmWthWXSmHV3mEfxBAgP9QGTU++MKn2uPq3t2UjF1DO6w","EncryptionData":{…}}</MessageText>
在解密过程中,将从队列消息中提取已包装的密钥并将其解包。 还将从队列消息中提取 IV,与解包的密钥一起使用来对队列消息数据进行解密。 加密元数据很少(500 字节以下),因此虽然它计入队列消息的 64-KB 限制,但影响应是可管理的。 加密的消息采用 Base64 编码,如上面的代码片段所示,它将扩展正在发送的消息的大小。
由于队列中的消息生存期较短,因此没有必要在更新为客户端加密 v2 后解密和重新加密队列消息。 在正常的队列消耗过程中,将轮换任何不太安全的消息。
客户端加密和性能
请记住,加密存储数据会导致额外的性能开销。 在应用程序中使用客户端加密时,客户端库必须安全生成 CEK 和 IV、加密内容本身、与所选密钥存储通信以进行密钥封装,以及设置其他元数据的格式并上传它们。 此开销因所加密的数据量而有所变化。 我们建议客户在开发过程中始终测试其应用程序的性能。