AWS Encryption SDK for Python 예제 코드 - AWS Encryption SDK

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

AWS Encryption SDK for Python 예제 코드

다음 예제에서는 AWS Encryption SDK for Python를 사용하여 데이터를 암호화 및 복호화하는 방법을 보여줍니다.

이 섹션의 예제에서는 2.0.x 이상 버전의 AWS Encryption SDK for Python를 사용하는 방법을 보여줍니다. 이하 버전을 사용하는 예제의 경우 GitHub의 aws-encryption-sdk-python 리포지토리의 릴리스 목록에서 해당하는 릴리스를 찾을 수 있습니다.

문자열 암호화 및 복호화

다음 예제에서는 AWS Encryption SDK를 사용하여 문자열을 암호화 및 복호화하는 방법을 보여줍니다. 이 예제에서는 AWS Key Management Service(AWS KMS)의 AWS KMS key를 마스터 키로 사용합니다.

암호화할 때 StrictAwsKmsMasterKeyProvider 생성자는 키 ID, 키 ARN, 별칭 이름 또는 별칭 ARN을 사용합니다. 복호화할 때는 키 ARN이 필요합니다. 이 경우 keyArn 파라미터는 암호화 및 복호화에 사용되므로 해당 값은 키 ARN이어야 합니다. AWS KMS 키의 ID에 대한 자세한 내용은 AWS Key Management Service 개발자 가이드키 식별자를 참조하세요.

# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Example showing basic encryption and decryption of a value already in memory.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy def cycle_string(key_arn, source_plaintext, botocore_session=None): """Encrypts and then decrypts a string under an &KMS; key. :param str key_arn: Amazon Resource Name (ARN) of the &KMS; key :param bytes source_plaintext: Data to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ # Set up an encryption client with an explicit commitment policy. If you do not explicitly choose a # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Create an AWS KMS master key provider 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) # Encrypt the plaintext source data ciphertext, encryptor_header = client.encrypt(source=source_plaintext, key_provider=master_key_provider) # Decrypt the ciphertext cycled_plaintext, decrypted_header = client.decrypt(source=ciphertext, key_provider=master_key_provider) # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext assert cycled_plaintext == source_plaintext # Verify that the encryption context used in the decrypt operation includes all key pairs from # the encrypt operation. (The SDK can add pairs, so don't require an exact match.) # # In production, always use a meaningful encryption context. In this sample, we omit the # encryption context (no key pairs). assert all( pair in decrypted_header.encryption_context.items() for pair in encryptor_header.encryption_context.items() )

바이트 스트림 암호화 및 복호화

다음 예제에서는 AWS Encryption SDK를 사용하여 바이트 스트림을 암호화 및 복호화하는 방법을 보여줍니다. 이 예제에서는 AWS를 사용하지 않습니다. 정적이고 일시적인 마스터 키 공급자를 사용합니다.

암호화할 때 이 예제에서는 디지털 서명(AES_256_GCM_HKDF_SHA512_COMMIT_KEY)이 없는 대체 알고리즘 제품군을 사용합니다. 이 알고리즘 제품군은 데이터를 암호화하고 복호화하는 사용자를 동등하게 신뢰할 수 있는 경우에 적합합니다. 그런 다음 복호화할 때 예제는 decrypt-unsigned 스트리밍 모드를 사용하는데, 서명된 사이퍼텍스트가 발견되면 실패합니다. decrypt-unsigned 스트리밍 모드는 AWS Encryption SDK 버전 1.9.x 및 2.2.x에 도입되었습니다.

# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Example showing creation and use of a RawMasterKeyProvider.""" import filecmp import os import aws_encryption_sdk from aws_encryption_sdk.identifiers import Algorithm, CommitmentPolicy, EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider class StaticRandomMasterKeyProvider(RawMasterKeyProvider): """Randomly generates 256-bit keys for each unique key ID.""" provider_id = "static-random" def __init__(self, **kwargs): # pylint: disable=unused-argument """Initialize empty map of keys.""" self._static_keys = {} def _get_raw_key(self, key_id): """Returns a static, randomly-generated symmetric key for the specified key ID. :param str key_id: Key ID :returns: Wrapping key that contains the specified static key :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` """ try: static_key = self._static_keys[key_id] except KeyError: static_key = os.urandom(32) self._static_keys[key_id] = static_key return WrappingKey( wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, wrapping_key=static_key, wrapping_key_type=EncryptionKeyType.SYMMETRIC, ) def cycle_file(source_plaintext_filename): """Encrypts and then decrypts a file under a custom static master key provider. :param str source_plaintext_filename: Filename of file to encrypt """ # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Create a static random master key provider key_id = os.urandom(8) master_key_provider = StaticRandomMasterKeyProvider() master_key_provider.add_master_key(key_id) ciphertext_filename = source_plaintext_filename + ".encrypted" cycled_plaintext_filename = source_plaintext_filename + ".decrypted" # Encrypt the plaintext source data # We can use an unsigning algorithm suite here under the assumption that the contexts that encrypt # and decrypt are equally trusted. with open(source_plaintext_filename, "rb") as plaintext, open(ciphertext_filename, "wb") as ciphertext: with client.stream( algorithm=Algorithm.AES_256_GCM_HKDF_SHA512_COMMIT_KEY, mode="e", source=plaintext, key_provider=master_key_provider, ) as encryptor: for chunk in encryptor: ciphertext.write(chunk) # Decrypt the ciphertext # We can use the recommended "decrypt-unsigned" streaming mode since we encrypted with an unsigned algorithm suite. with open(ciphertext_filename, "rb") as ciphertext, open(cycled_plaintext_filename, "wb") as plaintext: with client.stream(mode="decrypt-unsigned", source=ciphertext, key_provider=master_key_provider) as decryptor: for chunk in decryptor: plaintext.write(chunk) # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source # plaintext assert filecmp.cmp(source_plaintext_filename, cycled_plaintext_filename) # Verify that the encryption context used in the decrypt operation includes all key pairs from # the encrypt operation # # In production, always use a meaningful encryption context. In this sample, we omit the # encryption context (no key pairs). assert all( pair in decryptor.header.encryption_context.items() for pair in encryptor.header.encryption_context.items() ) return ciphertext_filename, cycled_plaintext_filename

여러 마스터 키 공급자를 사용하는 바이트 스트림 암호화 및 복호화

다음 예제에서는 두 개 이상의 마스터 키 공급자와 함께 AWS Encryption SDK를 사용하는 방법을 보여줍니다. 둘 이상의 마스터 키 공급자를 사용하면 하나의 마스터 키 공급자를 복호화에 사용할 수 없는 경우 중복성이 생성됩니다. 이 예제에서는 AWS KMS key 및 RSA 키 페어를 마스터 키로 사용합니다.

이 예제는 디지털 서명이 포함된 기본 알고리즘 제품군을 사용하여 암호화합니다. 스트리밍할 때 AWS Encryption SDK는 무결성 검사를 거친 후 디지털 서명을 확인하기 전에 일반 텍스트를 릴리스합니다. 서명이 확인될 때까지 일반 텍스트를 사용하지 않도록 이 예제에서는 일반 텍스트를 버퍼링하고 복호화 및 확인이 완료될 때만 디스크에 씁니다.

# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Example showing creation of a RawMasterKeyProvider, how to use multiple master key providers to encrypt, and demonstrating that each master key provider can then be used independently to decrypt the same encrypted message. """ import filecmp import os from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa import aws_encryption_sdk from aws_encryption_sdk.identifiers import CommitmentPolicy, EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider class StaticRandomMasterKeyProvider(RawMasterKeyProvider): """Randomly generates and provides 4096-bit RSA keys consistently per unique key id.""" provider_id = "static-random" def __init__(self, **kwargs): # pylint: disable=unused-argument """Initialize empty map of keys.""" self._static_keys = {} def _get_raw_key(self, key_id): """Retrieves a static, randomly generated, RSA key for the specified key id. :param str key_id: User-defined ID for the static key :returns: Wrapping key that contains the specified static key :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` """ try: static_key = self._static_keys[key_id] except KeyError: private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend()) static_key = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) self._static_keys[key_id] = static_key return WrappingKey( wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA1_MGF1, wrapping_key=static_key, wrapping_key_type=EncryptionKeyType.PRIVATE, ) def cycle_file(key_arn, source_plaintext_filename, botocore_session=None): """Encrypts and then decrypts a file using an AWS KMS master key provider and a custom static master key provider. Both master key providers are used to encrypt the plaintext file, so either one alone can decrypt it. :param str key_arn: Amazon Resource Name (ARN) of the &KMS; key (http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html) :param str source_plaintext_filename: Filename of file to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ # "Cycled" means encrypted and then decrypted ciphertext_filename = source_plaintext_filename + ".encrypted" cycled_kms_plaintext_filename = source_plaintext_filename + ".kms.decrypted" cycled_static_plaintext_filename = source_plaintext_filename + ".static.decrypted" # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Create an AWS KMS master key provider kms_kwargs = dict(key_ids=[key_arn]) if botocore_session is not None: kms_kwargs["botocore_session"] = botocore_session kms_master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) # Create a static master key provider and add a master key to it static_key_id = os.urandom(8) static_master_key_provider = StaticRandomMasterKeyProvider() static_master_key_provider.add_master_key(static_key_id) # Add the static master key provider to the AWS KMS master key provider # The resulting master key provider uses AWS KMS master keys to generate (and encrypt) # data keys and static master keys to create an additional encrypted copy of each data key. kms_master_key_provider.add_master_key_provider(static_master_key_provider) # Encrypt plaintext with both AWS KMS and static master keys with open(source_plaintext_filename, "rb") as plaintext, open(ciphertext_filename, "wb") as ciphertext: with client.stream(source=plaintext, mode="e", key_provider=kms_master_key_provider) as encryptor: for chunk in encryptor: ciphertext.write(chunk) # Decrypt the ciphertext with only the AWS KMS master key # Buffer the data in memory before writing to disk. This ensures verfication of the digital signature before returning plaintext. with open(ciphertext_filename, "rb") as ciphertext, open(cycled_kms_plaintext_filename, "wb") as plaintext: with client.stream( source=ciphertext, mode="d", key_provider=aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) ) as kms_decryptor: plaintext.write(kms_decryptor.read()) # Decrypt the ciphertext with only the static master key # Buffer the data in memory before writing to disk to ensure verfication of the signature before returning plaintext. with open(ciphertext_filename, "rb") as ciphertext, open(cycled_static_plaintext_filename, "wb") as plaintext: with client.stream(source=ciphertext, mode="d", key_provider=static_master_key_provider) as static_decryptor: plaintext.write(static_decryptor.read()) # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext assert filecmp.cmp(source_plaintext_filename, cycled_kms_plaintext_filename) assert filecmp.cmp(source_plaintext_filename, cycled_static_plaintext_filename) # Verify that the encryption context in the decrypt operation includes all key pairs from the # encrypt operation. # # In production, always use a meaningful encryption context. In this sample, we omit the # encryption context (no key pairs). assert all( pair in kms_decryptor.header.encryption_context.items() for pair in encryptor.header.encryption_context.items() ) assert all( pair in static_decryptor.header.encryption_context.items() for pair in encryptor.header.encryption_context.items() ) return (ciphertext_filename, cycled_kms_plaintext_filename, cycled_static_plaintext_filename)

데이터 키 캐싱을 사용하여 메시지 암호화

다음은 AWS Encryption SDK for Python에서 데이터 키 캐싱을 사용하는 방법을 나타낸 예제입니다. 필요한 용량 값으로 로컬 캐시(LocalCryptoMaterialsCache) 인스턴스를 구성하고 캐시 보안 임계값을 사용하여 캐싱 암호 자료 관리자(캐싱 CMM) 인스턴스를 구성하는 방법을 보여주도록 설계되었습니다.

매우 기본적인 이 예제는 고정된 문자열을 암호화하는 함수를 생성합니다. 이 함수를 사용하여 AWS KMS key, 필요한 캐시 크기(용량), 최대 수명 값을 지정할 수 있습니다. 데이터 키 캐싱의 보다 복잡한 실제 예제는 데이터 키 캐싱 예제 코드 섹션을 참조하세요.

이 예제는 선택 사항이지만 암호화 컨텍스트를 추가 인증 데이터로 사용하기도 합니다. 암호화 컨텍스트로 암호화된 데이터를 복호화할 때는 호출자에게 일반 텍스트 데이터를 반환하기 전에 암호화 컨텍스트가 예상한 것과 같은지를 애플리케이션이 확인해야 합니다. 암호화 컨텍스트는 모든 암호화 또는 복호화 작업의 모범 사례 요소이지만 데이터 키 캐싱에서는 특별한 역할을 합니다. 자세한 내용은 암호화 컨텍스트: 캐시 항목을 선택하는 방법을 참조하세요.

# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Example of encryption with data key caching.""" import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy def encrypt_with_caching(kms_key_arn, max_age_in_cache, cache_capacity): """Encrypts a string using an &KMS; key and data key caching. :param str kms_key_arn: Amazon Resource Name (ARN) of the &KMS; key :param float max_age_in_cache: Maximum time in seconds that a cached entry can be used :param int cache_capacity: Maximum number of entries to retain in cache at once """ # Data to be encrypted my_data = "My plaintext data" # Security thresholds # Max messages (or max bytes per) data key are optional MAX_ENTRY_MESSAGES = 100 # Create an encryption context encryption_context = {"purpose": "test"} # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Create a master key provider for the &KMS; key key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_arn]) # Create a local cache cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity) # Create a caching CMM caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager( master_key_provider=key_provider, cache=cache, max_age=max_age_in_cache, max_messages_encrypted=MAX_ENTRY_MESSAGES, ) # When the call to encrypt data specifies a caching CMM, # the encryption operation uses the data key cache specified # in the caching CMM encrypted_message, _header = client.encrypt( source=my_data, materials_manager=caching_cmm, encryption_context=encryption_context ) return encrypted_message