def get_multi_keyring_with_generator_and_children():
    private_key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=2048,
                                           backend=default_backend())
    return MultiKeyring(
        generator=RawAESKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_key=_WRAPPING_KEY_AES,
        ),
        children=[
            RawRSAKeyring(
                key_namespace=_PROVIDER_ID,
                key_name=_KEY_ID,
                wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
                private_wrapping_key=private_key,
                public_wrapping_key=private_key.public_key(),
            ),
            RawRSAKeyring(
                key_namespace=_PROVIDER_ID,
                key_name=_KEY_ID,
                wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
                private_wrapping_key=private_key,
                public_wrapping_key=private_key.public_key(),
            ),
        ],
    )
Beispiel #2
0
def test_private_key_cannot_encrypt():
    test_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_wrapping_key=_PRIVATE_WRAPPING_KEY,
    )
    initial_materials = EncryptionMaterials(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT)

    with pytest.raises(EncryptKeyError) as excinfo:
        test_keyring.on_encrypt(initial_materials)

    excinfo.match("A public key is required to encrypt")
def test_on_encrypt_no_public_key(raw_rsa_keyring):
    private_key = raw_rsa_private_key()
    test_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
        private_wrapping_key=private_key,
    )

    initial_materials = get_encryption_materials_without_data_encryption_key()

    with pytest.raises(EncryptKeyError) as excinfo:
        test_keyring.on_encrypt(encryption_materials=initial_materials)

    excinfo.match("A public key is required to encrypt")
Beispiel #4
0
def raw_rsa_keyring():
    return RawRSAKeyring.from_pem_encoding(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
        private_encoded_key=VALUES["private_rsa_key_bytes"][1],
    )
Beispiel #5
0
def test_public_key_only_can_encrypt():
    test_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        public_wrapping_key=_PUBLIC_WRAPPING_KEY,
    )
    initial_materials = EncryptionMaterials(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT)

    test_materials = test_keyring.on_encrypt(initial_materials)

    assert test_materials is not initial_materials
    assert test_materials.data_encryption_key is not None
    assert test_materials.encrypted_data_keys
Beispiel #6
0
def test_raw_master_key_decrypts_what_raw_keyring_encrypts(
        encryption_materials_samples):
    test_raw_rsa_keyring = RawRSAKeyring.from_pem_encoding(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_encoded_key=_PRIVATE_WRAPPING_KEY_PEM,
        public_encoded_key=_PUBLIC_WRAPPING_KEY_PEM,
    )

    # Creating an instance of a raw master key
    test_raw_master_key = RawMasterKey(
        key_id=_KEY_ID,
        provider_id=_PROVIDER_ID,
        wrapping_key=WrappingKey(
            wrapping_algorithm=_WRAPPING_ALGORITHM,
            wrapping_key=_PRIVATE_WRAPPING_KEY_PEM,
            wrapping_key_type=EncryptionKeyType.PRIVATE,
        ),
    )

    # Call on_encrypt function for the keyring
    encryption_materials = test_raw_rsa_keyring.on_encrypt(
        encryption_materials=encryption_materials_samples)

    # Check if plaintext data key encrypted by raw keyring is decrypted by raw master key
    raw_mkp_decrypted_data_key = test_raw_master_key.decrypt_data_key_from_list(
        encrypted_data_keys=encryption_materials._encrypted_data_keys,
        algorithm=encryption_materials.algorithm,
        encryption_context=encryption_materials.encryption_context,
    ).data_key

    assert encryption_materials.data_encryption_key.data_key == raw_mkp_decrypted_data_key
Beispiel #7
0
def test_invalid_wrapping_algorithm_suite(wrapping_algorithm):
    with pytest.raises(ValueError):
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=wrapping_algorithm,
            private_wrapping_key=raw_rsa_private_key(),
        )
Beispiel #8
0
def get_multi_keyring_with_no_children():
    return MultiKeyring(generator=RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
        private_wrapping_key=rsa.generate_private_key(
            public_exponent=65537, key_size=2048, backend=default_backend()),
    ))
Beispiel #9
0
def test_public_and_private_key_not_provided():
    with pytest.raises(TypeError) as exc_info:
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1)
    assert exc_info.match(
        "At least one of public key or private key must be provided.")
Beispiel #10
0
def test_invalid_parameters(key_namespace, key_name, wrapping_algorithm,
                            private_wrapping_key, public_wrapping_key):
    with pytest.raises(TypeError):
        RawRSAKeyring(
            key_namespace=key_namespace,
            key_name=key_name,
            wrapping_algorithm=wrapping_algorithm,
            private_wrapping_key=private_wrapping_key,
            public_wrapping_key=public_wrapping_key,
        )
Beispiel #11
0
def ephemeral_raw_rsa_keyring(
        size=4096, wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1):
    # type: (int, WrappingAlgorithm) -> RawRSAKeyring
    key_bytes = _generate_rsa_key_bytes(size)
    return RawRSAKeyring.from_pem_encoding(
        key_namespace="fake",
        key_name="rsa-{}".format(size).encode("utf-8"),
        wrapping_algorithm=wrapping_algorithm,
        private_encoded_key=key_bytes,
    )
Beispiel #12
0
def sample_raw_rsa_keyring_using_different_wrapping_algorithm():
    for alg in WrappingAlgorithm:
        if alg.encryption_type is EncryptionType.ASYMMETRIC:
            yield RawRSAKeyring(
                key_namespace=_PROVIDER_ID,
                key_name=_KEY_ID,
                wrapping_algorithm=alg,
                private_wrapping_key=_PRIVATE_WRAPPING_KEY,
                public_wrapping_key=_PUBLIC_WRAPPING_KEY,
            )
    pem_and_der_encoded_raw_rsa_keyring = [
        RawRSAKeyring.from_pem_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            private_encoded_key=
            _RAW_RSA_PRIVATE_KEY_PEM_ENCODED_WITHOUT_PASSWORD,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_PEM_ENCODED,
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
        RawRSAKeyring.from_pem_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            private_encoded_key=_RAW_RSA_PRIVATE_KEY_PEM_ENCODED_WITH_PASSWORD,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_PEM_ENCODED,
            password=b"mypassword",
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
        RawRSAKeyring.from_pem_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_PEM_ENCODED,
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
        RawRSAKeyring.from_der_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            private_encoded_key=
            _RAW_RSA_PRIVATE_KEY_DER_ENCODED_WITHOUT_PASSWORD,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_DER_ENCODED,
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
        RawRSAKeyring.from_der_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            private_encoded_key=_RAW_RSA_PRIVATE_KEY_DER_ENCODED_WITH_PASSWORD,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_DER_ENCODED,
            password=b"mypassword",
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
        RawRSAKeyring.from_der_encoding(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            public_encoded_key=_RAW_RSA_PUBLIC_KEY_DER_ENCODED,
            wrapping_algorithm=_WRAPPING_ALGORITHM,
        ),
    ]
    for keyring in pem_and_der_encoded_raw_rsa_keyring:
        yield keyring
def raw_rsa_keyring():
    private_key = serialization.load_pem_private_key(
        data=VALUES["private_rsa_key_bytes"][1],
        password=None,
        backend=default_backend())
    return RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
        private_wrapping_key=private_key,
        public_wrapping_key=private_key.public_key(),
    )
def ephemeral_raw_rsa_keyring(
        size=4096, wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1):
    # type: (int, WrappingAlgorithm) -> RawRSAKeyring
    private_key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=size,
                                           backend=default_backend())
    return RawRSAKeyring(
        key_namespace="fake",
        key_name="rsa-{}".format(size).encode("utf-8"),
        wrapping_algorithm=wrapping_algorithm,
        private_wrapping_key=private_key,
        public_wrapping_key=private_key.public_key(),
    )
Beispiel #15
0
def test_keypair_must_match():
    wrapping_key_a = rsa.generate_private_key(public_exponent=_PUBLIC_EXPONENT,
                                              key_size=_KEY_SIZE,
                                              backend=_BACKEND)
    wrapping_key_b = rsa.generate_private_key(public_exponent=_PUBLIC_EXPONENT,
                                              key_size=_KEY_SIZE,
                                              backend=_BACKEND)

    with pytest.raises(ValueError) as excinfo:
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=_WRAPPING_ALGORITHM,
            private_wrapping_key=wrapping_key_a,
            public_wrapping_key=wrapping_key_b.public_key(),
        )

    excinfo.match(
        "Private and public wrapping keys MUST be from the same keypair.")
Beispiel #16
0
def test_raw_keyring_decrypts_what_raw_master_key_encrypts(
        encryption_materials_samples):

    # Create instance of raw master key
    test_raw_master_key = RawMasterKey(
        key_id=_KEY_ID,
        provider_id=_PROVIDER_ID,
        wrapping_key=WrappingKey(
            wrapping_algorithm=_WRAPPING_ALGORITHM,
            wrapping_key=_PRIVATE_WRAPPING_KEY_PEM,
            wrapping_key_type=EncryptionKeyType.PRIVATE,
        ),
    )

    test_raw_rsa_keyring = RawRSAKeyring.from_pem_encoding(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_encoded_key=_PRIVATE_WRAPPING_KEY_PEM,
        public_encoded_key=_PUBLIC_WRAPPING_KEY_PEM,
    )

    raw_mkp_generated_data_key = test_raw_master_key.generate_data_key(
        algorithm=encryption_materials_samples.algorithm,
        encryption_context=encryption_materials_samples.encryption_context,
    )

    raw_mkp_encrypted_data_key = test_raw_master_key.encrypt_data_key(
        data_key=raw_mkp_generated_data_key,
        algorithm=encryption_materials_samples.algorithm,
        encryption_context=encryption_materials_samples.encryption_context,
    )

    decryption_materials = test_raw_rsa_keyring.on_decrypt(
        decryption_materials=DecryptionMaterials(
            algorithm=encryption_materials_samples.algorithm,
            encryption_context=encryption_materials_samples.encryption_context,
            verification_key=b"ex_verification_key",
        ),
        encrypted_data_keys=[raw_mkp_encrypted_data_key],
    )

    assert raw_mkp_generated_data_key.data_key == decryption_materials.data_encryption_key.data_key
def run(aws_kms_cmk, source_plaintext):
    # type: (str, bytes) -> None
    """Demonstrate configuring a keyring to use an AWS KMS CMK and an RSA wrapping key.

    :param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys
    :param bytes source_plaintext: Plaintext to encrypt
    """
    # Prepare your encryption context.
    # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
    encryption_context = {
        "encryption": "context",
        "is not": "secret",
        "but adds": "useful metadata",
        "that can help you": "be confident that",
        "the data you are handling": "is what you think it is",
    }

    # Generate an RSA private key to use with your keyring.
    # In practice, you should get this key from a secure key management system such as an HSM.
    #
    # The National Institute of Standards and Technology (NIST) recommends a minimum of 2048-bit keys for RSA.
    # https://www.nist.gov/publications/transitioning-use-cryptographic-algorithms-and-key-lengths
    #
    # Why did we use this public exponent?
    # https://crypto.stanford.edu/~dabo/pubs/papers/RSA-survey.pdf
    private_key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=4096,
                                           backend=default_backend())

    # Collect the public key from the private key.
    public_key = private_key.public_key()

    # Create the encrypt keyring that only has access to the public key.
    escrow_encrypt_keyring = RawRSAKeyring(
        # The key namespace and key name are defined by you
        # and are used by the raw RSA keyring
        # to determine whether it should attempt to decrypt
        # an encrypted data key.
        #
        # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
        key_namespace="some managed raw keys",
        key_name=b"my RSA wrapping key",
        public_wrapping_key=public_key,
        # The wrapping algorithm tells the raw RSA keyring
        # how to use your wrapping key to encrypt data keys.
        #
        # We recommend using RSA_OAEP_SHA256_MGF1.
        # You should not use RSA_PKCS1 unless you require it for backwards compatibility.
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
    )

    # Create the decrypt keyring that has access to the private key.
    escrow_decrypt_keyring = RawRSAKeyring(
        # The key namespace and key name MUST match the encrypt keyring.
        key_namespace="some managed raw keys",
        key_name=b"my RSA wrapping key",
        private_wrapping_key=private_key,
        # The wrapping algorithm MUST match the encrypt keyring.
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
    )

    # Create the AWS KMS keyring that you will use for decryption during normal operations.
    kms_keyring = AwsKmsKeyring(generator_key_id=aws_kms_cmk)

    # Combine the AWS KMS keyring and the escrow encrypt keyring using the multi-keyring.
    encrypt_keyring = MultiKeyring(generator=kms_keyring,
                                   children=[escrow_encrypt_keyring])

    # Encrypt your plaintext data using the multi-keyring.
    ciphertext, encrypt_header = aws_encryption_sdk.encrypt(
        source=source_plaintext,
        encryption_context=encryption_context,
        keyring=encrypt_keyring)

    # Verify that the header contains the expected number of encrypted data keys (EDKs).
    # It should contain one EDK for AWS KMS and one for the escrow key.
    assert len(encrypt_header.encrypted_data_keys) == 2

    # Demonstrate that the ciphertext and plaintext are different.
    assert ciphertext != source_plaintext

    # Decrypt your encrypted data separately using the AWS KMS keyring and the escrow decrypt keyring.
    #
    # You do not need to specify the encryption context on decrypt
    # because the header of the encrypted message includes the encryption context.
    decrypted_kms, decrypt_header_kms = aws_encryption_sdk.decrypt(
        source=ciphertext, keyring=kms_keyring)
    decrypted_escrow, decrypt_header_escrow = aws_encryption_sdk.decrypt(
        source=ciphertext, keyring=escrow_decrypt_keyring)

    # Demonstrate that the decrypted plaintext is identical to the original plaintext.
    assert decrypted_kms == source_plaintext
    assert decrypted_escrow == source_plaintext

    # Verify that the encryption context used in the decrypt operation includes
    # the encryption context that you specified when encrypting.
    # The AWS Encryption SDK can add pairs, so don't require an exact match.
    #
    # In production, always use a meaningful encryption context.
    assert set(encryption_context.items()) <= set(
        decrypt_header_kms.encryption_context.items())
    assert set(encryption_context.items()) <= set(
        decrypt_header_escrow.encryption_context.items())
Beispiel #18
0
def run(source_plaintext):
    # type: (bytes) -> None
    """Demonstrate an encrypt/decrypt cycle using separate public and private raw RSA keyrings.

    :param bytes source_plaintext: Plaintext to encrypt
    """
    # Prepare your encryption context.
    # Remember that your encryption context is NOT SECRET.
    # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
    encryption_context = {
        "encryption": "context",
        "is not": "secret",
        "but adds": "useful metadata",
        "that can help you": "be confident that",
        "the data you are handling": "is what you think it is",
    }

    # Generate an RSA private key to use with your keyring.
    # In practice, you should get this key from a secure key management system such as an HSM.
    #
    # The National Institute of Standards and Technology (NIST) recommends a minimum of 2048-bit keys for RSA.
    # https://www.nist.gov/publications/transitioning-use-cryptographic-algorithms-and-key-lengths
    #
    # Why did we use this public exponent?
    # https://crypto.stanford.edu/~dabo/pubs/papers/RSA-survey.pdf
    private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend())

    # Collect the public key from the private key.
    public_key = private_key.public_key()

    # The keyring determines how your data keys are protected.
    #
    # Create the encrypt keyring that only has access to the public key.
    public_key_keyring = RawRSAKeyring(
        # The key namespace and key name are defined by you
        # and are used by the raw RSA keyring
        # to determine whether it should attempt to decrypt
        # an encrypted data key.
        #
        # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
        key_namespace="some managed raw keys",
        key_name=b"my RSA wrapping key",
        public_wrapping_key=public_key,
        # The wrapping algorithm tells the raw RSA keyring
        # how to use your wrapping key to encrypt data keys.
        #
        # We recommend using RSA_OAEP_SHA256_MGF1.
        # You should not use RSA_PKCS1 unless you require it for backwards compatibility.
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
    )

    # Create the decrypt keyring that has access to the private key.
    private_key_keyring = RawRSAKeyring(
        # The key namespace and key name MUST match the encrypt keyring.
        key_namespace="some managed raw keys",
        key_name=b"my RSA wrapping key",
        private_wrapping_key=private_key,
        # The wrapping algorithm MUST match the encrypt keyring.
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
    )

    # Encrypt your plaintext data using the encrypt keyring.
    ciphertext, _encrypt_header = aws_encryption_sdk.encrypt(
        source=source_plaintext, encryption_context=encryption_context, keyring=public_key_keyring
    )

    # Demonstrate that the ciphertext and plaintext are different.
    assert ciphertext != source_plaintext

    # Try to decrypt your encrypted data using the *encrypt* keyring.
    # This demonstrates that you cannot decrypt using the public key.
    try:
        aws_encryption_sdk.decrypt(source=ciphertext, keyring=public_key_keyring)
    except AWSEncryptionSDKClientError:
        # The public key cannot decrypt.
        # Reaching this point means everything is working as expected.
        pass
    else:
        # Show that the public keyring could not decrypt.
        raise AssertionError("The public key can never decrypt!")

    # Decrypt your encrypted data using the decrypt keyring.
    #
    # You do not need to specify the encryption context on decrypt
    # because the header of the encrypted message includes the encryption context.
    decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, keyring=private_key_keyring)

    # Demonstrate that the decrypted plaintext is identical to the original plaintext.
    assert decrypted == source_plaintext

    # Verify that the encryption context used in the decrypt operation includes
    # the encryption context that you specified when encrypting.
    # The AWS Encryption SDK can add pairs, so don't require an exact match.
    #
    # In production, always use a meaningful encryption context.
    assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items())
def _raw_rsa(include_pre_sha2=True, include_sha2=True, include_mkp=True):
    wrapping_algorithms = []
    if include_pre_sha2:
        wrapping_algorithms.extend([
            WrappingAlgorithm.RSA_PKCS1, WrappingAlgorithm.RSA_OAEP_SHA1_MGF1
        ])
    if include_sha2:
        wrapping_algorithms.extend([
            WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            WrappingAlgorithm.RSA_OAEP_SHA384_MGF1,
            WrappingAlgorithm.RSA_OAEP_SHA512_MGF1,
        ])
    for wrapping_algorithm in wrapping_algorithms:
        private_keyring = ephemeral_raw_rsa_keyring(
            wrapping_algorithm=wrapping_algorithm)
        public_keyring = RawRSAKeyring(
            key_namespace=private_keyring.key_namespace,
            key_name=private_keyring.key_name,
            wrapping_algorithm=wrapping_algorithm,
            public_wrapping_key=private_keyring._private_wrapping_key.
            public_key(),
        )
        yield pytest.param(
            "keyring",
            private_keyring,
            "keyring",
            private_keyring,
            id="raw RSA keyring -- private encrypt, private decrypt -- {}".
            format(wrapping_algorithm.name),
        )
        yield pytest.param(
            "keyring",
            public_keyring,
            "keyring",
            private_keyring,
            id="raw RSA keyring -- public encrypt, private decrypt -- {}".
            format(wrapping_algorithm.name),
        )

        if not include_mkp:
            continue

        private_mkp, public_mkp = raw_rsa_mkps_from_keyring(private_keyring)

        yield pytest.param(
            "key_provider",
            build_fake_raw_key_provider(wrapping_algorithm,
                                        EncryptionKeyType.PRIVATE),
            "key_provider",
            build_fake_raw_key_provider(wrapping_algorithm,
                                        EncryptionKeyType.PRIVATE),
            id=
            "raw RSA master key provider -- private encrypt, private decrypt -- {}"
            .format(wrapping_algorithm.name),
        )
        yield pytest.param(
            "key_provider",
            build_fake_raw_key_provider(wrapping_algorithm,
                                        EncryptionKeyType.PUBLIC),
            "key_provider",
            build_fake_raw_key_provider(wrapping_algorithm,
                                        EncryptionKeyType.PRIVATE),
            id=
            "raw RSA master key provider -- public encrypt, private decrypt -- {}"
            .format(wrapping_algorithm.name),
        )

        yield pytest.param(
            "key_provider",
            private_mkp,
            "keyring",
            private_keyring,
            id=
            "raw RSA keyring -- private master key provider encrypt and private keyring decrypt -- {}"
            .format(wrapping_algorithm),
        )
        yield pytest.param(
            "key_provider",
            public_mkp,
            "keyring",
            private_keyring,
            id=
            "raw RSA keyring -- public master key provider encrypt and private keyring decrypt -- {}"
            .format(wrapping_algorithm),
        )
        yield pytest.param(
            "keyring",
            private_keyring,
            "key_provider",
            private_mkp,
            id=
            "raw RSA keyring -- private keyring encrypt and private master key provider decrypt -- {}"
            .format(wrapping_algorithm),
        )
        yield pytest.param(
            "keyring",
            public_keyring,
            "key_provider",
            private_mkp,
            id=
            "raw RSA keyring -- public keyring encrypt and private master key provider decrypt -- {}"
            .format(wrapping_algorithm),
        )
Beispiel #20
0
def run(source_plaintext):
    # type: (bytes) -> None
    """Demonstrate an encrypt/decrypt cycle using a raw RSA keyring loaded from a PEM-encoded key.

    :param bytes source_plaintext: Plaintext to encrypt
    """
    # Prepare your encryption context.
    # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
    encryption_context = {
        "encryption": "context",
        "is not": "secret",
        "but adds": "useful metadata",
        "that can help you": "be confident that",
        "the data you are handling": "is what you think it is",
    }

    # Generate an RSA private key to use with your keyring.
    # In practice, you should get this key from a secure key management system such as an HSM.
    #
    # The National Institute of Standards and Technology (NIST) recommends a minimum of 2048-bit keys for RSA.
    # https://www.nist.gov/publications/transitioning-use-cryptographic-algorithms-and-key-lengths
    #
    # Why did we use this public exponent?
    # https://crypto.stanford.edu/~dabo/pubs/papers/RSA-survey.pdf
    private_key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=4096,
                                           backend=default_backend())

    # Serialize the RSA keypair to PEM encoding.
    # This or DER encoding is likely to be what you get from your key management system in practice.
    private_key_pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption(),
    )
    public_key_pem = private_key.public_key().public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo,
    )

    # Create the keyring that determines how your data keys are protected.
    #
    # If your key is encoded using DER, you can use RawRSAKeyring.from_der_encoding
    keyring = RawRSAKeyring.from_pem_encoding(
        # The key namespace and key name are defined by you
        # and are used by the raw RSA keyring
        # to determine whether it should attempt to decrypt
        # an encrypted data key.
        #
        # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
        key_namespace="some managed raw keys",
        key_name=b"my RSA wrapping key",
        private_encoded_key=private_key_pem,
        public_encoded_key=public_key_pem,
        # The wrapping algorithm tells the raw RSA keyring
        # how to use your wrapping key to encrypt data keys.
        #
        # We recommend using RSA_OAEP_SHA256_MGF1.
        # You should not use RSA_PKCS1 unless you require it for backwards compatibility.
        wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
    )

    # Encrypt your plaintext data.
    ciphertext, _encrypt_header = aws_encryption_sdk.encrypt(
        source=source_plaintext,
        encryption_context=encryption_context,
        keyring=keyring)

    # Demonstrate that the ciphertext and plaintext are different.
    assert ciphertext != source_plaintext

    # Decrypt your encrypted data using the same keyring you used on encrypt.
    #
    # You do not need to specify the encryption context on decrypt
    # because the header of the encrypted message includes the encryption context.
    decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext,
                                                           keyring=keyring)

    # Demonstrate that the decrypted plaintext is identical to the original plaintext.
    assert decrypted == source_plaintext

    # Verify that the encryption context used in the decrypt operation includes
    # the encryption context that you specified when encrypting.
    # The AWS Encryption SDK can add pairs, so don't require an exact match.
    #
    # In production, always use a meaningful encryption context.
    assert set(encryption_context.items()) <= set(
        decrypt_header.encryption_context.items())
Beispiel #21
0
                                              key_size=2048,
                                              backend=default_backend())
_rsa_private_key_b = rsa.generate_private_key(public_exponent=65537,
                                              key_size=2048,
                                              backend=default_backend())
_MULTI_KEYRING_WITH_GENERATOR_AND_CHILDREN = MultiKeyring(
    generator=RawAESKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_key=_WRAPPING_KEY_AES,
    ),
    children=[
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            private_wrapping_key=_rsa_private_key_a,
            public_wrapping_key=_rsa_private_key_a.public_key(),
        ),
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            private_wrapping_key=_rsa_private_key_b,
            public_wrapping_key=_rsa_private_key_b.public_key(),
        ),
    ],
)

_MULTI_KEYRING_WITHOUT_CHILDREN = MultiKeyring(generator=RawRSAKeyring(
    key_namespace=_PROVIDER_ID,
Beispiel #22
0
        )
    ],
)

_MULTI_KEYRING_WITH_GENERATOR_AND_CHILDREN = MultiKeyring(
    generator=RawAESKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_key=_WRAPPING_KEY_AES,
    ),
    children=[
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            private_wrapping_key=rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()),
        ),
        RawRSAKeyring(
            key_namespace=_PROVIDER_ID,
            key_name=_KEY_ID,
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            private_wrapping_key=rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()),
        ),
    ],
)