带有加密SDK的KMS - 如何进行信封加密?

问题描述 投票:0回答:1

我目前正在使用 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,如果这有什么区别的话。

python amazon-web-services encryption amazon-kms
1个回答
0
投票

数据密钥缓存需要在加密时启动。就其本身而言,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”类型密钥。)

© www.soinside.com 2019 - 2024. All rights reserved.