def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None): """Encrypts and then decrypts a string under one KMS customer master key (CMK). :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK :param bytes source_plaintext: Data to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ kwargs = dict(key_ids=[key_arn]) if botocore_session is not None: kwargs["botocore_session"] = botocore_session # Set up an encryption client with an explicit commitment policy disallowing encryption with algorithms that # provide commitment client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) # Create master key provider using the ARN of the key and the session (botocore_session) kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kwargs) # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header. Note: in # order for decrypt to succeed, the key_ids value must be the key ARN of the CMK. ciphertext, encrypted_message_header = client.encrypt(source=source_plaintext, key_provider=kms_key_provider) # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header plaintext, decrypted_message_header = client.decrypt(source=ciphertext, key_provider=kms_key_provider) # Verify that the original message and the decrypted message are the same assert source_plaintext == plaintext # Verify that the encryption context of the encrypted message and decrypted message match assert all( pair in encrypted_message_header.encryption_context.items() for pair in decrypted_message_header.encryption_context.items() )
def encryptionSDKDemo(): import aws_encryption_sdk from aws_encryption_sdk.identifiers import CommitmentPolicy # # Create AWS encryption sdk client with # client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[MASTER_KEY_ARN]) # # My secret string # my_plaintext = b'This is some super secret data!' print(' Plain text to encrypt = %s \n ' % my_plaintext) # # Let's encrypt the plaintext data # print(" let's encrypt ! \n") my_ciphertext, encryptor_header = client.encrypt( source=my_plaintext, key_provider=kms_key_provider) print(' My ciphered text = %s \n ' % my_ciphertext) # # Let's decrypt the ciphertext data # print(" let's decrypt ! \n") decrypted_plaintext, decryptor_header = client.decrypt( source=my_ciphertext, key_provider=kms_key_provider) print(' My ciphered text decrypt = %s \n ' % decrypted_plaintext)
def initialize() -> DocumentBucketOperations: """ Configure a Document Bucket API automatically with resources bootstrapped by CloudFormation. """ # Load the pointers to CloudFormation resources that you just deployed state = toml.load(os.path.expanduser( config["base"]["state_file"]))["state"] # Now you have the identifiers of the CloudFormation resources loaded, # Set up your S3 Bucket for the Document Bucket bucket = boto3.resource("s3").Bucket(state["DocumentBucket"]) # Set up your DynamoDB Table for the Document Bucket table = boto3.resource("dynamodb").Table(state["DocumentTable"]) # Pull configuration of KMS resources faythe_cmk = state["FaytheCMK"] walter_cmk = state["WalterCMK"] # And the Master Key Provider configuring how to use KMS cmk = [faythe_cmk, walter_cmk] mkp = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=cmk) # Set up the API to interact with the Document Bucket using all these resources operations = DocumentBucketOperations(bucket, table, mkp) return operations
def encrypt_decrypt(key_arns, source_plaintext, botocore_session=None): """Encrypts and then decrypts a string under two KMS customer master keys (CMK). :param str key_arns: Amazon Resource Names (ARNs) of the KMS CMKs :param bytes source_plaintext: Data to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ encrypt_kwargs = dict(key_ids=key_arns) if botocore_session is not None: encrypt_kwargs["botocore_session"] = botocore_session # 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 strict master key provider that is only allowed to encrypt and decrypt using the ARN of the provided key. strict_encrypt_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**encrypt_kwargs) # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header ciphertext, encrypted_message_header = client.encrypt( source=source_plaintext, key_provider=strict_encrypt_key_provider ) # For each original master key, create a strict key provider that only lists that key and decrypt the encrypted # message using that provider. Note: in order for decrypt to succeed, the key_ids value must be the key ARN of the # CMK. for key_arn in key_arns: decrypt_kwargs = dict(key_ids=[key_arn]) if botocore_session is not None: encrypt_kwargs["botocore_session"] = botocore_session strict_decrypt_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**decrypt_kwargs) plaintext, decrypted_message_header = client.decrypt( source=ciphertext, key_provider=strict_decrypt_key_provider ) # Verify that the original message and the decrypted message are the same assert source_plaintext == plaintext # Verify that the encryption context of the encrypted message and decrypted message match assert all( pair in encrypted_message_header.encryption_context.items() for pair in decrypted_message_header.encryption_context.items() )
def encrypt_decrypt_stream(key_arn, source_plaintext_filename, botocore_session=None): """Encrypts and then decrypts streaming data under one KMS customer master key (CMK). :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK :param str source_plaintext_filename: Filename of file to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ kwargs = dict() kwargs["key_ids"] = [key_arn] if botocore_session is not None: kwargs["botocore_session"] = botocore_session # 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 master key provider using the ARN of the key and the session (botocore_session) kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( **kwargs) ciphertext_filename = source_plaintext_filename + ".encrypted" decrypted_text_filename = source_plaintext_filename + ".decrypted" # Encrypt the plaintext using the AWS Encryption SDK. with open(source_plaintext_filename, "rb") as plaintext, open(ciphertext_filename, "wb") as ciphertext: with client.stream(source=plaintext, mode="e", key_provider=kms_key_provider) as encryptor: for chunk in encryptor: ciphertext.write(chunk) # Decrypt the encrypted message using the AWS Encryption SDK. with open(ciphertext_filename, "rb") as ciphertext, open(decrypted_text_filename, "wb") as plaintext: with client.stream(source=ciphertext, mode="d", key_provider=kms_key_provider) as decryptor: for chunk in decryptor: plaintext.write(chunk) # Check if the original message and the decrypted message are the same assert filecmp.cmp(source_plaintext_filename, decrypted_text_filename) # Check if the headers of the encrypted message and decrypted message match assert all(pair in encryptor.header.encryption_context.items() for pair in decryptor.header.encryption_context.items()) return ciphertext_filename, decrypted_text_filename
def encrypt_with_caching(kms_cmk_arn, max_age_in_cache, cache_capacity): """Encrypts a string using an AWS KMS customer master key (CMK) and data key caching. :param str kms_cmk_arn: Amazon Resource Name (ARN) of the KMS customer master 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 customer master key (CMK) key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_cmk_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
def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None): """Encrypts a string under one KMS customer master key (CMK), then decrypts it using discovery mode. :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK :param bytes source_plaintext: Data to encrypt :param botocore_session: existing botocore session instance :type botocore_session: botocore.session.Session """ encrypt_kwargs = dict(key_ids=[key_arn]) if botocore_session is not None: encrypt_kwargs["botocore_session"] = botocore_session # 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 strict master key provider that is only allowed to encrypt and decrypt using the ARN of the provided key. strict_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**encrypt_kwargs) # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header ciphertext, encrypted_message_header = client.encrypt(source=source_plaintext, key_provider=strict_key_provider) # Create a second master key provider in discovery mode that does not explicitly list the key used to encrypt. # Note: The discovery_filter argument is optional; if you omit this, the AWS Encryption SDK attempts to # decrypt any ciphertext it receives. arn = arn_from_str(key_arn) decrypt_kwargs = dict(discovery_filter=DiscoveryFilter(account_ids=[arn.account_id], partition=arn.partition)) if botocore_session is not None: encrypt_kwargs["botocore_session"] = botocore_session discovery_key_provider = aws_encryption_sdk.DiscoveryAwsKmsMasterKeyProvider(**decrypt_kwargs) # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header. plaintext, decrypted_message_header = client.decrypt(source=ciphertext, key_provider=discovery_key_provider) # Verify that the original message and the decrypted message are the same assert source_plaintext == plaintext # Verify that the encryption context of the encrypted message and decrypted message match assert all( pair in encrypted_message_header.encryption_context.items() for pair in decrypted_message_header.encryption_context.items() )
def cycle_string(key_arn, source_plaintext, botocore_session=None): """Encrypts and then decrypts a string under a KMS customer master key (CMK). :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK :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. 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 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())
def test_encrypted_payload_coding(): key_id = os.environ['KEY_ID'] session = boto3.Session() mkp = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[key_id], botocore_session=session._session) payload = { 'iss': 'issuer', 'iat': 0, 'tid': 'asdf', 'exp': 0, 'token': 'jkljkl', 'action': { 'name': 'foo', 'type': 'success', 'output': {} }, 'param': False, } validate_payload_schema(payload) encoded_payload = encode_payload(payload, mkp) assert encoded_payload.startswith('2-') decoded_payload = decode_payload(encoded_payload, mkp) validate_payload_schema(decoded_payload) assert_dicts_equal(payload, decoded_payload) encoded_payload = encode_payload(payload, None) assert encoded_payload.startswith('1-') with pytest.raises(EncryptionRequired): decoded_payload = decode_payload(encoded_payload, mkp) encoded_payload = encode_payload(payload, mkp) assert encoded_payload.startswith('2-') with pytest.raises(DecryptionUnsupported): decoded_payload = decode_payload(encoded_payload, None)
def cycle_file(key_arn, source_plaintext_filename, botocore_session=None): """Encrypts and then decrypts a file using a 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 Customer Master Key (CMK) (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 a 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 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: for chunk in kms_decryptor: plaintext.write(chunk) # Decrypt the ciphertext with only the static master key 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: for chunk in static_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_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)
get_force_disable_parameters, get_disable_post_actions, is_verbose, get_header) from sfn_callback_urls.exceptions import (ReturnHttpResponse, BaseError, ActionMismatched, ParametersDisabled, PostActionsDisabled, InvalidPostActionBody, StepFunctionsError) BOTO3_SESSION = boto3.Session() STEP_FUNCTIONS_CLIENT = BOTO3_SESSION.client('stepfunctions') MASTER_KEY_PROVIDER = None if 'KEY_ID' in os.environ: MASTER_KEY_PROVIDER = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[os.environ['KEY_ID']], botocore_session=BOTO3_SESSION._session) def handler(request, context): if is_verbose(): print(f'Request: {json.dumps(request)}') timestamp = datetime.datetime.now() log_event = { 'timestamp': timestamp.isoformat(), } try: response = OrderedDict(
import boto3 import time import requests import json import os import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy from DelaySayExceptions import UserAuthorizeError from datetime import timezone, timedelta encryption_client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[os.environ['KMS_MASTER_KEY_ARN']]) # This is the format used to log dates in the DynamoDB table. DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" def encrypt_oauth_token(token): token_as_bytes = token.encode() encrypted_token, encryptor_header = encryption_client.encrypt( source=token_as_bytes, key_provider=kms_key_provider) return encrypted_token def decrypt_oauth_token(encrypted_token): token_as_bytes, decryptor_header = encryption_client.decrypt( source=encrypted_token, key_provider=kms_key_provider) token = token_as_bytes.decode() return token
import aws_encryption_sdk kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ 'arn:aws:kms:us-east-1:873559269338:key/1e1a6a81-93e0-4b9a-954b-cc09802bf3ce' ]) my_plaintext = 'This is some super secret data! Yup, sure is!' client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=aws_encryption_sdk.CommitmentPolicy. FORBID_ENCRYPT_ALLOW_DECRYPT, ) my_ciphertext, encryptor_header = client.encrypt(source=my_plaintext, key_provider=kms_key_provider) decrypted_plaintext, decryptor_header = client.decrypt( source=my_ciphertext, key_provider=kms_key_provider) assert my_plaintext == decrypted_plaintext.decode('ascii') assert encryptor_header.encryption_context == decryptor_header.encryption_context