我目前正在使用 aws 加密 sdk 来加密和解密我的一些数据(静态加密)。
但是,当尝试一次解密大量数据时,速度非常慢。经检查,SDK似乎正在对每条数据进行HTTP调用!
我在这个子主题上发现了一篇很好的文章,其中建议有两种方法可以做到这一点。后者是信封加密,这似乎更适合我的用例。
但是,我找不到如何使用 SDK 设置此信封加密的明确示例。理想情况下,我想让 KMS 管理用于加密数据密钥的密钥。因此,只有 1 个 HTTP 调用,数据的加密/解密在本地处理。
有没有办法用SDK来做到这一点?或者我需要手动管理这个吗?
这是我的代码:
import aws_encryption_sdk
import botocore
from aws_encryption_sdk import CachingCryptoMaterialsManager, CommitmentPolicy
from flask import current_app
def get_master_key_provider():
botocore_session = botocore.session.get_session()
key_arn = current_app.config["KMS_KEY"]
kms_kwargs = dict(key_ids=[key_arn])
if botocore_session is not None:
kms_kwargs["botocore_session"] = botocore_session
master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
**kms_kwargs
)
return master_key_provider
def generate_cache(
MAX_CACHE_SIZE=10, MAX_ENTRY_MESSAGES=10, MAX_ENTRY_AGE_SECONDS=60.0
):
key_provider = get_master_key_provider()
cache = aws_encryption_sdk.LocalCryptoMaterialsCache(MAX_CACHE_SIZE)
caching_cmm = CachingCryptoMaterialsManager(
master_key_provider=key_provider,
cache=cache,
max_age=MAX_ENTRY_AGE_SECONDS,
max_messages_encrypted=MAX_ENTRY_MESSAGES,
)
return caching_cmm
class DecryptionSession:
def __init__(
self,
MAX_CACHE_SIZE=10,
MAX_ENTRY_MESSAGES=10,
MAX_ENTRY_AGE_SECONDS=60.0,
):
self._caching_cmm = generate_cache(
MAX_CACHE_SIZE, MAX_ENTRY_MESSAGES, MAX_ENTRY_AGE_SECONDS
)
self._client = aws_encryption_sdk.EncryptionSDKClient(
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
)
def decrypt_text(self, ciphertext: str):
"""Decrypts an encrypted piece of text and returns the original text"""
ciphertext_bytes = bytes.fromhex(ciphertext)
decrypted_bytes, _ = self._client.decrypt(
source=ciphertext_bytes, materials_manager=self._caching_cmm
)
decrypted_text = decrypted_bytes.decode()
return decrypted_text
我正在使用 Python SDK,如果这有什么区别的话。
数据密钥缓存需要在加密时启动。就其本身而言,SDK 将为每个明文创建一个随机数据密钥并包装该密钥(往返 KMS)。解密时,每个密文将具有不同的包装密钥,需要将其解包为数据密钥(往返 KMS)。
数据密钥缓存的工作原理是对多个明文重复使用相同的数据密钥 - 只需一次往返即可包装它。在解密多个密文时,我们可以希望它们是使用相同的数据密钥加密的。处理第一个密文需要解开数据密钥(往返),但如果后续密文来自同一批次,则缓存将已经具有解开的数据密钥。
但是请注意,如果两个明文有不同的加密上下文(如果我没记错的话),数据密钥缓存就会失效。 (这是我们应用程序中的一个问题。)
为了解决这个问题,我们引入了应用程序存储的中间密钥。此“原始 AES 密钥”( https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html ) 用于加密数百个明文。 (请注意,如上所述,SDK 为每个明文生成一个随机数据密钥,并使用中间密钥包装该数据密钥。因此,与数据密钥缓存不同,数据密钥不会被重用。此外,我们还可以使用每个明文/密文都有不同的加密上下文。)
当然,中间密钥是使用 SDK 在 KMS 密钥下进行加密的,该密钥的密文存储在应用程序的数据库中。
启动时,应用程序加载加密密钥,对其进行解密(往返 KMS)并缓存它。现在可以自由加密和解密,无需再进行 KMS 往返。缺点是该密钥在应用程序运行时保存在内存中 - 也许您不想在可以转储堆的 Java 中执行此操作。将此与 SDK 的正常操作进行比较,其中基于 KMS 的密钥永远不会离开 KMS,并且数据密钥来回发送以进行打包和解包。
总而言之,为了提高 KMS 性能,您要么需要使用单个数据密钥(数据密钥缓存)来加密许多明文,要么可以引入一个中间密钥(理解该密钥保存在应用程序的内存中 - 与“从不留下 KMS”类型密钥。)