Skip to content

Handlers #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
MANIFEST_VERSION = Dict[str, Union[str, int]]

AWS_KMS_KEY_SPEC = Dict[str, Union[bool, str]]
MANUAL_KEY_SPEC = Dict[str, Union[bool, str, int, Iterable[str]]]
MANUAL_KEY_SPEC = Dict[str, Union[bool, str, int]]
KEY_SPEC = Union[AWS_KMS_KEY_SPEC, MANUAL_KEY_SPEC]
KEYS_MANIFEST = Dict[str, Union[MANIFEST_VERSION, Iterable[KEY_SPEC]]]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,4 @@ def run_and_write_to_dir(self, target_directory, json_indent=None):
keys_uri="file://keys.json", keys=self.keys, test_scenarios=test_scenarios
)

root_writer(
"manifest.json", json.dumps(decrypt_manifest.manifest_spec, indent=json_indent).encode(ENCODING)
)
root_writer("manifest.json", json.dumps(decrypt_manifest.manifest_spec, indent=json_indent).encode(ENCODING))
45 changes: 18 additions & 27 deletions test_vector_handlers/src/awses_test_vectors/manifests/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,7 @@

from awses_test_vectors.internal.aws_kms import arn_from_key_id
from awses_test_vectors.internal.defaults import ENCODING
from awses_test_vectors.internal.util import (
dictionary_validator,
iterable_validator,
membership_validator,
validate_manifest_type,
)
from awses_test_vectors.internal.util import dictionary_validator, membership_validator, validate_manifest_type

try: # Python 3.5.0 and 3.5.1 have incompatible typing modules
from typing import cast, Dict, Iterable, Optional # noqa pylint: disable=unused-import
Expand All @@ -42,7 +37,7 @@
# We only actually need these imports when running the mypy checks
pass

SUPPORTED_VERSIONS = (1,)
SUPPORTED_VERSIONS = (3,)
KEY_TYPES = ("symmetric", "private", "public")
KEY_ENCODINGS = ("base64", "pem")
KEY_ALGORITHMS = ("aes", "rsa")
Expand All @@ -60,14 +55,16 @@ class KeySpec(object):

encrypt = attr.ib(validator=attr.validators.instance_of(bool))
decrypt = attr.ib(validator=attr.validators.instance_of(bool))
key_id = attr.ib(validator=attr.validators.instance_of(six.string_types))

def __init__(self, encrypt, decrypt): # noqa=D107
# type: (bool, bool) -> None
def __init__(self, encrypt, decrypt, key_id): # noqa=D107
# type: (bool, bool, str) -> None
# Workaround pending resolution of attrs/mypy interaction.
# https://github.com/python/mypy/issues/2088
# https://github.com/python-attrs/attrs/issues/215
self.encrypt = encrypt
self.decrypt = decrypt
self.key_id = key_id
attr.validate(self)


Expand All @@ -84,16 +81,14 @@ class AwsKmsKeySpec(KeySpec):
# pylint: disable=too-few-public-methods

type_name = attr.ib(validator=membership_validator(("aws-kms",)))
key_id = attr.ib(validator=attr.validators.instance_of(six.string_types))

def __init__(self, encrypt, decrypt, type_name, key_id): # noqa=D107
# type: (bool, bool, str, str) -> None
# Workaround pending resolution of attrs/mypy interaction.
# https://github.com/python/mypy/issues/2088
# https://github.com/python-attrs/attrs/issues/215
self.type_name = type_name
self.key_id = key_id
super(AwsKmsKeySpec, self).__init__(encrypt, decrypt)
super(AwsKmsKeySpec, self).__init__(encrypt, decrypt, key_id)

@property
def manifest_spec(self):
Expand All @@ -117,35 +112,32 @@ class ManualKeySpec(KeySpec):

Allowed values described in AWS Crypto Tools Test Vector Framework feature #0002 Keys Manifest.

:param str key_id: Master key ID
:param bool encrypt: Key can be used to encrypt
:param bool decrypt: Key can be used to decrypt
:param str algorithm: Algorithm to use with key
:param str type_name: Key type
:param int bits: Key length in bits
:param str encoding: Encoding used to encode key material
:param material: Raw material encoded, then split into lines separated by ``line_separator``
:type material: list of str
:param str line_separator: Character with which to separate members of ``material``
before decoding (optional: default is empty string)
:param str material: Raw material encoded
"""

algorithm = attr.ib(validator=membership_validator(KEY_ALGORITHMS))
type_name = attr.ib(validator=membership_validator(KEY_TYPES))
bits = attr.ib(validator=attr.validators.instance_of(int))
encoding = attr.ib(validator=membership_validator(KEY_ENCODINGS))
material = attr.ib(validator=iterable_validator(list, six.string_types))
line_separator = attr.ib(default="", validator=attr.validators.instance_of(six.string_types))
material = attr.ib(validator=attr.validators.instance_of(six.string_types))

def __init__(
self,
key_id, # type: str
encrypt, # type: bool
decrypt, # type: bool
algorithm, # type: str
type_name, # type: str
bits, # type: int
encoding, # type: str
material, # type: Iterable[str]
line_separator="", # type: Optional[str]
): # noqa=D107
# type: (...) -> None
# Workaround pending resolution of attrs/mypy interaction.
Expand All @@ -156,8 +148,7 @@ def __init__(
self.bits = bits
self.encoding = encoding
self.material = material
self.line_separator = line_separator
super(ManualKeySpec, self).__init__(encrypt, decrypt)
super(ManualKeySpec, self).__init__(encrypt, decrypt, key_id)

@property
def raw_material(self):
Expand All @@ -167,7 +158,7 @@ def raw_material(self):
:return: Binary key material
:rtype: bytes
"""
raw_material = self.line_separator.join(self.material).encode(ENCODING)
raw_material = self.material.encode(ENCODING)
if self.encoding == "base64":
return base64.b64decode(raw_material)

Expand All @@ -188,8 +179,8 @@ def manifest_spec(self):
"type": self.type_name,
"bits": self.bits,
"encoding": self.encoding,
"line-separator": self.line_separator,
"material": self.material,
"key-id": self.key_id,
}


Expand All @@ -201,6 +192,7 @@ def key_from_manifest_spec(key_spec):
:return: Loaded key
:rtype: KeySpec
"""
key_id = key_spec["key-id"] # type: str
decrypt = key_spec["decrypt"] # type: bool
encrypt = key_spec["encrypt"] # type: bool
type_name = key_spec["type"] # type: str
Expand All @@ -211,16 +203,15 @@ def key_from_manifest_spec(key_spec):
algorithm = key_spec["algorithm"] # type: str
bits = key_spec["bits"] # type: int
encoding = key_spec["encoding"] # type: str
line_separator = key_spec.get("line-separator", "") # type: str
material = key_spec["material"] # type: Iterable[str]
material = key_spec["material"] # type: str
return ManualKeySpec(
key_id=key_id,
encrypt=encrypt,
decrypt=decrypt,
type_name=type_name,
algorithm=algorithm,
bits=bits,
encoding=encoding,
line_separator=line_separator,
material=material,
)

Expand All @@ -242,7 +233,7 @@ class KeysManifest(object):
@classmethod
def from_manifest_spec(cls, raw_manifest):
# type: (KEYS_MANIFEST) -> KeysManifest
""""""
"""Load from a JSON keys manifest."""
manifest_version = raw_manifest["manifest"] # type: MANIFEST_VERSION
validate_manifest_type(
type_name=cls.type_name, manifest_version=manifest_version, supported_versions=SUPPORTED_VERSIONS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,17 @@
"rsa/pkcs1": WrappingAlgorithm.RSA_PKCS1,
"rsa/oaep-mgf1/sha1": WrappingAlgorithm.RSA_OAEP_SHA1_MGF1,
"rsa/oaep-mgf1/sha256": WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
# \/ not yet implemented \/
# 'rsa/oaep-mgf1/sha384': WrappingAlgorithm.RSA_OAEP_SHA384_MGF1,
# 'rsa/oaep-mgf1/sha512': WrappingAlgorithm.RSA_OAEP_SHA512_MGF1,
}
_NOT_YET_IMPLEMENTED = {"rsa/oaep-mgf1/sha384", "rsa/oaep-mgf1/sha512"}
try:
_RAW_WRAPPING_KEY_ALGORITHMS.update(
{
"rsa/oaep-mgf1/sha384": WrappingAlgorithm.RSA_OAEP_SHA384_MGF1,
"rsa/oaep-mgf1/sha512": WrappingAlgorithm.RSA_OAEP_SHA512_MGF1,
}
)
_NOT_YET_IMPLEMENTED = {}
except AttributeError:
_NOT_YET_IMPLEMENTED = {"rsa/oaep-mgf1/sha384", "rsa/oaep-mgf1/sha512"}
_RAW_ENCRYPTION_KEY_TYPE = {
"symmetric": EncryptionKeyType.SYMMETRIC,
"private": EncryptionKeyType.PRIVATE,
Expand All @@ -68,18 +74,16 @@ class MasterKeySpec(object):

Described in AWS Crypto Tools Test Vector Framework features #0003 and #0004.

:param str type_name:
:param str key_name:
:param str key_id:
:param str provider_id:
:param str encryption_algorithm:
:param str padding_algorithm:
:param str padding_hash:
:param str type_name: Master key type name
:param str key_name: Name of key in keys spec
:param str provider_id: Master key provider ID
:param str encryption_algorithm: Wrapping key encryption algorithm (required for raw master keys)
:param str padding_algorithm: Wrapping key padding algorithm (required for raw master keys)
:param str padding_hash: Wrapping key padding hash (required for raw master keys)
"""

type_name = attr.ib(validator=membership_validator(KNOWN_TYPES))
key_name = attr.ib(validator=attr.validators.instance_of(six.string_types))
key_id = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
provider_id = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
encryption_algorithm = attr.ib(validator=attr.validators.optional(membership_validator(KNOWN_ALGORITHMS)))
padding_algorithm = attr.ib(validator=attr.validators.optional(membership_validator(KNOWN_PADDING)))
Expand Down Expand Up @@ -113,7 +117,6 @@ def from_scenario(cls, spec):
return cls(
type_name=spec["type"],
key_name=spec["key"],
key_id=spec.get("key-id"),
provider_id=spec.get("provider-id"),
encryption_algorithm=spec.get("encryption-algorithm"),
padding_algorithm=spec.get("padding-algorithm"),
Expand Down Expand Up @@ -166,19 +169,6 @@ def _wrapping_key(self, key_spec):
key_type = _RAW_ENCRYPTION_KEY_TYPE[key_spec.type_name]
return WrappingKey(wrapping_algorithm=algorithm, wrapping_key=material, wrapping_key_type=key_type)

def _raw_key_id(self):
# type: () -> str
"""Determine the key ID value if this is a raw master key.

:returns: Correct key ID
:rtype: str
:raises TypeError: if this is not a raw master key specification
"""
if not self.type_name == "raw":
raise TypeError("This is not a raw master key")

return self.key_id if self.key_id is not None else self.key_name

def _raw_master_key_from_spec(self, key_spec):
# type: (KeySpec) -> RawMasterKey
"""Build a raw master key using this specification.
Expand All @@ -192,8 +182,7 @@ def _raw_master_key_from_spec(self, key_spec):
raise TypeError("This is not a raw master key")

wrapping_key = self._wrapping_key(key_spec)
key_id = self._raw_key_id()
return RawMasterKey(provider_id=self.provider_id, key_id=key_id, wrapping_key=wrapping_key)
return RawMasterKey(provider_id=self.provider_id, key_id=key_spec.key_id, wrapping_key=wrapping_key)

def _kms_master_key_from_spec(self, key_spec):
# type: (KeySpec) -> KMSMasterKey
Expand All @@ -207,9 +196,6 @@ def _kms_master_key_from_spec(self, key_spec):
if not self.type_name == "aws-kms":
raise TypeError("This is not an AWS KMS master key")

if self.key_id is not None and self.key_id != key_spec.key_id:
raise ValueError("AWS KMS key IDs must match between master key spec and key spec")

return KMS_MASTER_KEY_PROVIDER.master_key(key_id=key_spec.key_id)

_MASTER_KEY_LOADERS = {"aws-kms": _kms_master_key_from_spec, "raw": _raw_master_key_from_spec}
Expand Down Expand Up @@ -237,7 +223,6 @@ def scenario_spec(self):
if self.type_name != "aws-kms":
spec.update(
{
"key-id": self.key_id,
"provider-id": self.provider_id,
"encryption-algorithm": self.encryption_algorithm,
"padding-algorithm": self.padding_algorithm,
Expand Down
Loading