Azure 存储的客户端加密和 Azure Key VaultClient-Side Encryption and Azure Key Vault for Azure Storage

概述Overview

用于 .NET Nuget 包的 Azure 存储客户端库 支持在上传到 Azure 存储之前加密客户端应用程序中的数据,以及在下载到客户端时解密数据。The Azure Storage Client Library for .NET Nuget package supports encrypting data within client applications before uploading to Azure Storage, and decrypting data while downloading to the client. 此库还支持与 Azure 密钥保管库 集成,以便管理存储帐户密钥。The library also supports integration with Azure Key Vault for storage account key management.

有关使用客户端的加密和 Azure Key Vault 引导完成加密 Blob 的过程的分步教程,请参阅使用 Azure Key Vault 在 Azure 存储中加密和解密 BlobFor a step-by-step tutorial that leads you through the process of encrypting blobs using client-side encryption and Azure Key Vault, see Encrypt and decrypt blobs in Azure Storage using Azure Key Vault.

有关使用 Java 的客户端加密,请参阅 Azure 存储的 Java 客户端加密For client-side encryption with Java, see Client-Side Encryption with Java for Azure Storage.

通过信封技术加密和解密Encryption and decryption via the envelope technique

加密和解密的过程遵循信封技术。The processes of encryption and decryption follow the envelope technique.

通过信封技术加密Encryption via the envelope technique

通过信封技术加密的工作方式如下:Encryption via the envelope technique works in the following way:

  1. Azure 存储客户端库生成内容加密密钥 (CEK),这是一次性使用对称密钥。The Azure storage client library generates a content encryption key (CEK), which is a one-time-use symmetric key.

  2. 使用此 CEK 对用户数据进行加密。User data is encrypted using this CEK.

  3. 然后,使用密钥加密密钥 (KEK) 对此 CEK 进行包装(加密)。The CEK is then wrapped (encrypted) using the key encryption key (KEK). KEK 由密钥标识符标识,可以是非对称密钥对或对称密钥,还可以在本地托管或存储在 Azure 密钥保管库中。The KEK is identified by a key identifier and can be an asymmetric key pair or a symmetric key and can be managed locally or stored in Azure Key Vaults.

    存储客户端库本身永远无法访问 KEK。The storage client library itself never has access to KEK. 该库调用密钥保管库提供的密钥包装算法。The library invokes the key wrapping algorithm that is provided by Key Vault. 用户可以根据需要选择使用自定义提供程序进行密钥包装/解包。Users can choose to use custom providers for key wrapping/unwrapping if desired.

  4. 然后,将已加密的数据上传到 Azure 存储服务。The encrypted data is then uploaded to the Azure Storage service. 已包装的密钥以及一些附加加密元数据要么存储为元数据(在 Blob 上),要么以内插值替换已加密的数据(消息队列和表实体)。The wrapped key along with some additional encryption metadata is either stored as metadata (on a blob) or interpolated with the encrypted data (queue messages and table entities).

通过信封技术解密Decryption via the envelope technique

通过信封技术解密的工作方式如下:Decryption via the envelope technique works in the following way:

  1. 客户端库假定用户在本地或 Azure 密钥保管库中管理密钥加密密钥 (KEK)。The client library assumes that the user is managing the key encryption key (KEK) either locally or in Azure Key Vaults. 用户不需要知道用于加密的特定密钥。The user does not need to know the specific key that was used for encryption. 但是,可以设置和使用一个密钥解析程序,将不同的密钥标识符解析为密钥。Instead, a key resolver which resolves different key identifiers to keys can be set up and used.
  2. 客户端库下载已加密数据以及存储在服务中的任何加密材料。The client library downloads the encrypted data along with any encryption material that is stored on the service.
  3. 然后,使用密钥加密密钥 (KEK) 对已包装的内容加密密钥 (CEK) 进行解包(解密)。The wrapped content encryption key (CEK) is then unwrapped (decrypted) using the key encryption key (KEK). 这里同样,客户端库无法访问 KEK。Here again, the client library does not have access to KEK. 它只是调用自定义提供程序或 Key Vault 提供程序的解包算法。It simply invokes the custom or Key Vault provider's unwrapping algorithm.
  4. 然后,使用内容加密密钥 (CEK) 解密已加密的用户数据。The content encryption key (CEK) is then used to decrypt the encrypted user data.

加密机制Encryption Mechanism

存储客户端库使用 AES 来加密用户数据。The storage client library uses AES in order to encrypt user data. 具体而言,是使用 AES 的加密块链接 (CBC) 模式。Specifically, Cipher Block Chaining (CBC) mode with AES. 每个服务的工作方式都稍有不同,因此我们会在此讨论其中每个服务。Each service works somewhat differently, so we will discuss each of them here.

BlobBlobs

目前,客户端库仅支持整个 Blob 的加密。The client library currently supports encryption of whole blobs only. 具体而言,用户使用 UploadFrom 方法或 OpenWrite 方法时支持加密。Specifically, encryption is supported when users use the UploadFrom methods or the OpenWrite method. 对于下载,支持完整下载和范围下载。For downloads, both complete and range downloads are supported.

在加密过程中,客户端库生成 16 字节的随机初始化向量 (IV) 和 32 字节的随机内容加密密钥 (CEK) 并将使用此信息对 Blob 数据执行信封加密。During encryption, the client library will generate a random Initialization Vector (IV) of 16 bytes, together with a random content encryption key (CEK) of 32 bytes, and perform envelope encryption of the blob data using this information. 然后,已包装的 CEK 和一些附加加密元数据将与服务上的已加密 Blob 一起存储为 Blob 元数据。The wrapped CEK and some additional encryption metadata are then stored as blob metadata along with the encrypted blob on the service.

Warning

若要针对 Blob 编辑或上传自己的元数据,需确保此元数据已保留。If you are editing or uploading your own metadata for the blob, you need to ensure that this metadata is preserved. 如果在没有此元数据的情况下上传新元数据,则已包装的 CEK、IV 和其他元数据会丢失,而 Blob 内容永远无法再检索。If you upload new metadata without this metadata, the wrapped CEK, IV, and other metadata will be lost and the blob content will never be retrievable again.

下载已加密的 Blob 需要使用 DownloadTo/BlobReadStream 便捷方法检索整个 Blob 的内容。Downloading an encrypted blob involves retrieving the content of the entire blob using the DownloadTo/BlobReadStream convenience methods. 将已包装的 CEK 解包,与 IV(在本示例中存储为 Blob 元数据)一起使用将解密后的数据返回给用户。The wrapped CEK is unwrapped and used together with the IV (stored as blob metadata in this case) to return the decrypted data to the users.

下载已加密 Blob 中的任意范围(DownloadRange 方法)需要调整用户提供的范围,获取少量可用于成功解密所请求范围的附加数据。Downloading an arbitrary range (DownloadRange methods) in the encrypted blob involves adjusting the range provided by users in order to get a small amount of additional data that can be used to successfully decrypt the requested range.

所有 Blob 类型(块 Blob、页 Blob 和追加 Blob)都可以使用此方案进行加密/解密。All blob types (block blobs, page blobs, and append blobs) can be encrypted/decrypted using this scheme.

队列Queues

由于队列消息可以采用任何格式,客户端库定义一个自定义格式,其在消息文本中包括初始化向量 (IV) 和已加密的内容加密密钥 (CEK)。Since queue messages can be of any format, the client library defines a custom format that includes the Initialization Vector (IV) and the encrypted content encryption key (CEK) in the message text.

在加密过程中,客户端库将生成 16 字节的随机 IV 和 32 字节的随机 CEK,并使用此信息对队列消息文本执行信封加密。During encryption, the client library generates a random IV of 16 bytes along with a random CEK of 32 bytes and performs envelope encryption of the queue message text using this information. 然后,将已包装的 CEK 和一些附加加密元数据添加到已加密的队列消息中。The wrapped CEK and some additional encryption metadata are then added to the encrypted queue message. 此修改后的消息(如下所示)存储在服务中。This modified message (shown below) is stored on the service.

<MessageText>{"EncryptedMessageContents":"6kOu8Rq1C3+M1QO4alKLmWthWXSmHV3mEfxBAgP9QGTU++MKn2uPq3t2UjF1DO6w","EncryptionData":{…}}</MessageText>

在解密过程中,将从队列消息中提取已包装的密钥并将其解包。During decryption, the wrapped key is extracted from the queue message and unwrapped. 还会从队列消息中提取 IV,与解包的密钥一起使用来对队列消息数据进行解密。The IV is also extracted from the queue message and used along with the unwrapped key to decrypt the queue message data. 请注意,加密元数据很少(不到 500 个字节),因此虽然它计入队列消息的 64KB 限制,但影响应是可管理的。Note that the encryption metadata is small (under 500 bytes), so while it does count toward the 64KB limit for a queue message, the impact should be manageable.

Tables

客户端库支持对插入和替换操作的实体属性进行加密。The client library supports encryption of entity properties for insert and replace operations.

Note

当前不支持合并。Merge is not currently supported. 由于属性的子集可能以前已使用不同的密钥加密,因此只合并新属性和更新元数据会导致数据丢失。Since a subset of properties may have been encrypted previously using a different key, simply merging the new properties and updating the metadata will result in data loss. 合并需要进行额外的服务调用以从服务中读取预先存在的实体,或者需要为属性使用一个新密钥,由于性能方面的原因,这两种方案都不适用。Merging either requires making extra service calls to read the pre-existing entity from the service, or using a new key per property, both of which are not suitable for performance reasons.

表数据加密的工作方式如下:Table data encryption works as follows:

  1. 用户指定要加密的属性。Users specify the properties to be encrypted.
  2. 客户端库为每个实体生成 16 个字节的随机初始化向量 (IV) 和 32 个字节的随机内容加密密钥 (CEK),并通过为每个属性派生新的 IV 对要加密的单独属性执行信封加密。The client library generates a random Initialization Vector (IV) of 16 bytes along with a random content encryption key (CEK) of 32 bytes for every entity, and performs envelope encryption on the individual properties to be encrypted by deriving a new IV per property. 加密的属性存储为二进制数据。The encrypted property is stored as binary data.
  3. 然后,已包装的 CEK 和一些附加加密元数据将存储为两个附加保留属性。The wrapped CEK and some additional encryption metadata are then stored as two additional reserved properties. 第一个保留属性 (_ClientEncryptionMetadata1) 是一个字符串属性,保存有关 IV、版本和已包装密钥的信息。The first reserved property (_ClientEncryptionMetadata1) is a string property that holds the information about IV, version, and wrapped key. 第二个保留属性 (_ClientEncryptionMetadata2) 是一个二进制属性,保存有关已加密属性的信息。The second reserved property (_ClientEncryptionMetadata2) is a binary property that holds the information about the properties that are encrypted. 第二个属性 (_ClientEncryptionMetadata2) 中的信息本身是已加密。The information in this second property (_ClientEncryptionMetadata2) is itself encrypted.
  4. 由于加密需要这两个附加保留属性,用户现在可能只有 250 个自定义属性,而不是 252 个。Due to these additional reserved properties required for encryption, users may now have only 250 custom properties instead of 252. 实体的总大小必须小于 1 MB。The total size of the entity must be less than 1 MB.

请注意,只有字符串属性可以加密。Note that only string properties can be encrypted. 如果要对其他类型的属性进行加密,必须将它们转换为字符串。If other types of properties are to be encrypted, they must be converted to strings. 加密的字符串作为二进制属性存储在服务中,并在解密之后转换回字符串。The encrypted strings are stored on the service as binary properties, and they are converted back to strings after decryption.

对于表,除了加密策略以外,用户还必须指定要加密的属性。For tables, in addition to the encryption policy, users must specify the properties to be encrypted. 可以通过指定 [EncryptProperty] 特性(适用于从 TableEntity 派生的 POCO 实体)或在请求选项中指定加密解析程序来完成此操作。This can be done by either specifying an [EncryptProperty] attribute (for POCO entities that derive from TableEntity) or an encryption resolver in request options. 加密解析程序是一个委托,它接受分区键、行键和属性名称并返回一个布尔值以指示是否应加密该属性。An encryption resolver is a delegate that takes a partition key, row key, and property name and returns a Boolean that indicates whether that property should be encrypted. 在加密过程中,客户端库会使用此信息来确定是否应在写入到网络时加密属性。During encryption, the client library will use this information to decide whether a property should be encrypted while writing to the wire. 该委托还可以围绕如何加密属性实现逻辑的可能性。The delegate also provides for the possibility of logic around how properties are encrypted. (例如,如果 X,则加密属性 A,否则加密属性 A 和 B。)请注意,在读取或查询实体时,不需要提供此信息。(For example, if X, then encrypt property A; otherwise encrypt properties A and B.) Note that it is not necessary to provide this information while reading or querying entities.

批处理操作Batch Operations

在批处理操作中,将对该批处理操作中的所有行使用同一 KEK,因为客户端库仅允许每个批处理操作使用一个选项对象(因此是一个策略/KEK)。In batch operations, the same KEK will be used across all the rows in that batch operation because the client library only allows one options object (and hence one policy/KEK) per batch operation. 但是,客户端库会为批处理中的每行在内部生成一个新的随机 IV 和随机 CEK。However, the client library will internally generate a new random IV and random CEK per row in the batch. 用户还可以选择通过在加密解析程序中定义此行为来加密批处理中的每个操作的不同属性。Users can also choose to encrypt different properties for every operation in the batch by defining this behavior in the encryption resolver.

查询Queries

Note

由于实体已加密,因此不能运行根据已加密属性进行筛选的查询。Because the entities are encrypted, you cannot run queries that filter on an encrypted property. 如果尝试运行,结果将会不正确,因为该服务会尝试将已加密的数据与未加密的数据进行比较。If you try, results will be incorrect, because the service would be trying to compare encrypted data with unencrypted data.

若要执行查询操作,必须指定一个能够解析结果集中的所有密钥的密钥解析程序。To perform query operations, you must specify a key resolver that is able to resolve all the keys in the result set. 如果查询结果中包含的实体不能解析为提供程序,则客户端库将引发错误。If an entity contained in the query result cannot be resolved to a provider, the client library will throw an error. 对于执行服务器端投影的任何查询,在默认情况下,客户端库将为所选列添加特殊的加密元数据属性(_ClientEncryptionMetadata1 和 _ClientEncryptionMetadata2)。For any query that performs server-side projections, the client library will add the special encryption metadata properties (_ClientEncryptionMetadata1 and _ClientEncryptionMetadata2) by default to the selected columns.

Azure Key VaultAzure Key Vault

Azure 密钥保管库可帮助保护云应用程序和服务使用的加密密钥和机密。Azure Key Vault helps safeguard cryptographic keys and secrets used by cloud applications and services. 有关详细信息,请参阅什么是 Azure 密钥保管库?For more information, see What is Azure Key Vault?.

存储客户端库使用密钥保管库核心库,以便在整个 Azure 上提供一个通用框架进行管理密钥。The storage client library uses the Key Vault core library in order to provide a common framework across Azure for managing keys. 用户还可以从使用密钥保管库扩展库中获得其他好处。Users also get the additional benefit of using the Key Vault extensions library. 扩展库围绕简单无缝的对称/RSA 本地和云密钥提供程序以及使用聚合和缓存提供有用的功能。The extensions library provides useful functionality around simple and seamless Symmetric/RSA local and cloud key providers as well as with aggregation and caching.

接口和依赖项Interface and dependencies

有三个密钥保管库包:There are three Key Vault packages:

  • Microsoft.Azure.KeyVault.Core 包含 IKey 和 IKeyResolver。Microsoft.Azure.KeyVault.Core contains the IKey and IKeyResolver. 它是没有依赖项的小型包。It is a small package with no dependencies. 用于 .NET 的存储空间客户端库将其定义为一个依赖项。The storage client library for .NET defines it as a dependency.
  • Microsoft.Azure.KeyVault 包含密钥保管库 REST 客户端。Microsoft.Azure.KeyVault contains the Key Vault REST client.
  • Microsoft.Azure.KeyVault.Extensions 包含扩展代码,其中包括加密算法和 RSAKey 和 SymmetricKey 的实现。Microsoft.Azure.KeyVault.Extensions contains extension code that includes implementations of cryptographic algorithms and an RSAKey and a SymmetricKey. 它依赖于 Core 和 KeyVault 命名空间,并提供用于定义聚合解析程序(在用户想要使用多个密钥提供程序时)和缓存密钥解析程序的功能。It depends on the Core and KeyVault namespaces and provides functionality to define an aggregate resolver (when users want to use multiple key providers) and a caching key resolver. 虽然存储客户端库不直接依赖于此包,但是如果用户想要使用 Azure 密钥保管库来存储其密钥或通过密钥保管库扩展来使用本地和云加密提供程序,则他们将需要此包。Although the storage client library does not directly depend on this package, if users wish to use Azure Key Vault to store their keys or to use the Key Vault extensions to consume the local and cloud cryptographic providers, they will need this package.

密钥保管库专为高价值主密钥设计,每个密钥保管库的限流限制的设计也考虑了这一点。Key Vault is designed for high-value master keys, and throttling limits per Key Vault are designed with this in mind. 使用密钥保管库执行客户端加密时,首选模型是使用在密钥保管库中作为机密存储并在本地缓存的对称主密钥。When performing client-side encryption with Key Vault, the preferred model is to use symmetric master keys stored as secrets in Key Vault and cached locally. 用户必须执行以下操作:Users must do the following:

  1. 脱机创建一个机密并将其上传到密钥保管库。Create a secret offline and upload it to Key Vault.
  2. 使用机密的基标识符作为参数来解析机密的当前版本进行加密,并在本地缓存此信息。Use the secret's base identifier as a parameter to resolve the current version of the secret for encryption and cache this information locally. 使用 CachingKeyResolver 进行缓存;用户不需要实现自己的缓存逻辑。Use CachingKeyResolver for caching; users are not expected to implement their own caching logic.
  3. 创建加密策略时,使用缓存解析程序作为输入。Use the caching resolver as an input while creating the encryption policy.

有关密钥保管库用法的详细信息,请查看 加密代码示例More information regarding Key Vault usage can be found in the encryption code samples.

最佳实践Best practices

仅在用于 .NET 的存储空间客户端库中提供加密支持。Encryption support is available only in the storage client library for .NET. Windows Phone 和 Windows 运行时当前不支持加密。Windows Phone and Windows Runtime do not currently support encryption.

Important

使用客户端加密时,请注意以下要点:Be aware of these important points when using client-side encryption:

  • 读取或写入到已加密的 Blob 时,请使用完整 Blob 上传命令和范围/完整 Blob 下载命令。When reading from or writing to an encrypted blob, use whole blob upload commands and range/whole blob download commands. 避免使用协议操作(如“放置块”、“放置块列表”、“写入页”、“清除页”或“追加块”)写入到已加密的 Blob,否则可能会损坏已加密的 Blob 并使其不可读。Avoid writing to an encrypted blob using protocol operations such as Put Block, Put Block List, Write Pages, Clear Pages, or Append Block; otherwise you may corrupt the encrypted blob and make it unreadable.
  • 对于表,存在类似的约束。For tables, a similar constraint exists. 请注意,不要在未更新加密元数据的情况下更新已加密的属性。Be careful to not update encrypted properties without updating the encryption metadata.
  • 如果在已加密的 Blob 上设置元数据,则可能会覆盖解密所需的与加密相关的元数据,因为设置元数据不是累加性的。If you set metadata on the encrypted blob, you may overwrite the encryption-related metadata required for decryption, since setting metadata is not additive. 这也适用于快照;避免在创建已加密的 Blob 的快照时指定元数据。This is also true for snapshots; avoid specifying metadata while creating a snapshot of an encrypted blob. 如果必须设置元数据,则一定要调用 FetchAttributes 方法首先获取当前加密元数据,并在设置元数据时避免并发写入。If metadata must be set, be sure to call the FetchAttributes method first to get the current encryption metadata, and avoid concurrent writes while metadata is being set.
  • 对于仅使用加密数据的用户,在默认请求选项中启用 RequireEncryption 属性。Enable the RequireEncryption property in the default request options for users that should work only with encrypted data. 有关详细信息,请参阅下文。See below for more info.

客户端 API/接口Client API / Interface

在创建 EncryptionPolicy 对象时,用户可以只提供密钥(实现 IKey)、只提供解析程序(实现 IKeyResolver),或两者都提供。While creating an EncryptionPolicy object, users can provide only a Key (implementing IKey), only a resolver (implementing IKeyResolver), or both. IKey 是使用密钥标识符标识的基本密钥类型,它提供了包装/解包逻辑。IKey is the basic key type that is identified using a key identifier and that provides the logic for wrapping/unwrapping. IKeyResolver 用于在解密过程中解析密钥。IKeyResolver is used to resolve a key during the decryption process. 它定义了 ResolveKey 方法,该方法根据给定的密钥标识符返回 IKey。It defines a ResolveKey method that returns an IKey given a key identifier. 由此,用户能够在多个位置中托管的多个密钥之间进行选择。This provides users the ability to choose between multiple keys that are managed in multiple locations.

  • 对于加密,始终使用该密钥,而没有密钥将导致错误。For encryption, the key is used always and the absence of a key will result in an error.
  • 对于解密:For decryption:
    • 如果指定为获取密钥,则调用密钥解析程序。The key resolver is invoked if specified to get the key. 如果指定了解析程序,但该解析程序不具有密钥标识符的映射,则会引发错误。If the resolver is specified but does not have a mapping for the key identifier, an error is thrown.
    • 如果未指定解析程序,但指定了密钥,则在该密钥的标识符与所需密钥标识符匹配时使用该密钥。If resolver is not specified but a key is specified, the key is used if its identifier matches the required key identifier. 如果标识符不匹配,则会引发错误。If the identifier does not match, an error is thrown.

本文中的代码示例演示如何设置加密策略和使用加密数据,但不演示如何使用 Azure Key Vault。The code examples in this article demonstrate setting an encryption policy and working with encrypted data, but do not demonstrate working with Azure Key Vault. GitHub 上的加密示例演示了针对 Blob、队列和表的更详细端到端方案,以及 Key Vault 集成。The encryption samples on GitHub demonstrate a more detailed end-to-end scenario for blobs, queues and tables, along with Key Vault integration.

RequireEncryption 模式RequireEncryption mode

用户可以选择启用这样的操作模式,要求加密所有上传和下载行为。Users can optionally enable a mode of operation where all uploads and downloads must be encrypted. 在此模式下,尝试在没有加密策略的情况下上传数据或下载在服务中未加密的数据,将导致在客户端上失败。In this mode, attempts to upload data without an encryption policy or download data that is not encrypted on the service will fail on the client. 请求选项对象的 RequireEncryption 属性控制此行为。The RequireEncryption property of the request options object controls this behavior. 如果应用程序要加密存储于 Azure 存储中的所有对象,则可以在服务客户端对象的默认请求选项上设置 RequireEncryption属性。If your application will encrypt all objects stored in Azure Storage, then you can set the RequireEncryption property on the default request options for the service client object. 例如,将 CloudBlobClient.DefaultRequestOptions.RequireEncryption 设置为 true,要求对通过该客户端对象执行的所有 blob 操作进行加密。For example, set CloudBlobClient.DefaultRequestOptions.RequireEncryption to true to require encryption for all blob operations performed through that client object.

Blob 服务加密Blob service encryption

创建 BlobEncryptionPolicy 对象并在请求选项中对其进行设置(使用 DefaultRequestOptions 基于每个 API 或在客户端级别设置)。Create a BlobEncryptionPolicy object and set it in the request options (per API or at a client level by using DefaultRequestOptions). 其他所有事项均由客户端库在内部处理。Everything else will be handled by the client library internally.

// Create the IKey used for encryption.
 RsaKey key = new RsaKey("private:key1" /* key identifier */);

 // Create the encryption policy to be used for upload and download.
 BlobEncryptionPolicy policy = new BlobEncryptionPolicy(key, null);

 // Set the encryption policy on the request options.
 BlobRequestOptions options = new BlobRequestOptions() { EncryptionPolicy = policy };

 // Upload the encrypted contents to the blob.
 blob.UploadFromStream(stream, size, null, options, null);

 // Download and decrypt the encrypted contents from the blob.
 MemoryStream outputStream = new MemoryStream();
 blob.DownloadToStream(outputStream, null, options, null);

队列服务加密Queue service encryption

创建 QueueEncryptionPolicy 对象并在请求选项中对其进行设置(使用 DefaultRequestOptions 基于每个 API 或在客户端级别设置)。Create a QueueEncryptionPolicy object and set it in the request options (per API or at a client level by using DefaultRequestOptions). 其他所有事项均由客户端库在内部处理。Everything else will be handled by the client library internally.

// Create the IKey used for encryption.
 RsaKey key = new RsaKey("private:key1" /* key identifier */);

 // Create the encryption policy to be used for upload and download.
 QueueEncryptionPolicy policy = new QueueEncryptionPolicy(key, null);

 // Add message
 QueueRequestOptions options = new QueueRequestOptions() { EncryptionPolicy = policy };
 queue.AddMessage(message, null, null, options, null);

 // Retrieve message
 CloudQueueMessage retrMessage = queue.GetMessage(null, options, null);

表服务加密Table service encryption

除了创建加密策略和在请求选项上设置它以外,还必须在 TableRequestOptions 中指定 EncryptionResolver,或在实体上设置 [EncryptProperty] 特性。In addition to creating an encryption policy and setting it on request options, you must either specify an EncryptionResolver in TableRequestOptions, or set the [EncryptProperty] attribute on the entity.

使用解析程序Using the resolver

// Create the IKey used for encryption.
 RsaKey key = new RsaKey("private:key1" /* key identifier */);

 // Create the encryption policy to be used for upload and download.
 TableEncryptionPolicy policy = new TableEncryptionPolicy(key, null);

 TableRequestOptions options = new TableRequestOptions()
 {
    EncryptionResolver = (pk, rk, propName) =>
     {
        if (propName == "foo")
         {
            return true;
         }
         return false;
     },
     EncryptionPolicy = policy
 };

 // Insert Entity
 currentTable.Execute(TableOperation.Insert(ent), options, null);

 // Retrieve Entity
 // No need to specify an encryption resolver for retrieve
 TableRequestOptions retrieveOptions = new TableRequestOptions()
 {
    EncryptionPolicy = policy
 };

 TableOperation operation = TableOperation.Retrieve(ent.PartitionKey, ent.RowKey);
 TableResult result = currentTable.Execute(operation, retrieveOptions, null);

使用特性Using attributes

如上所述,如果实体实现了 TableEntity,则可以使用 [EncryptProperty] 特性修饰属性,而不用指定 EncryptionResolver。As mentioned above, if the entity implements TableEntity, then the properties can be decorated with the [EncryptProperty] attribute instead of specifying the EncryptionResolver.

[EncryptProperty]
 public string EncryptedProperty1 { get; set; }

加密和性能Encryption and performance

注意,加密存储数据会导致额外的性能开销。Note that encrypting your storage data results in additional performance overhead. 必须生成内容密钥和 IV,内容本身必须进行加密,并且其他元数据必须进行格式化并上传。The content key and IV must be generated, the content itself must be encrypted, and additional meta-data must be formatted and uploaded. 此开销将因所加密的数据量而有所变化。This overhead will vary depending on the quantity of data being encrypted. 我们建议客户在开发过程中始终测试其应用程序的性能。We recommend that customers always test their applications for performance during development.

后续步骤Next steps