diff --git a/kmip/core/factories/payloads/request.py b/kmip/core/factories/payloads/request.py index 73c53bc..146c9ce 100644 --- a/kmip/core/factories/payloads/request.py +++ b/kmip/core/factories/payloads/request.py @@ -32,6 +32,7 @@ from kmip.core.messages.payloads import rekey_key_pair from kmip.core.messages.payloads import register from kmip.core.messages.payloads import revoke from kmip.core.messages.payloads import sign +from kmip.core.messages.payloads import signature_verify from kmip.core.messages.payloads import mac @@ -90,3 +91,6 @@ class RequestPayloadFactory(PayloadFactory): def _create_sign_payload(self): return sign.SignRequestPayload() + + def _create_signature_verify_payload(self): + return signature_verify.SignatureVerifyRequestPayload() diff --git a/kmip/core/factories/payloads/response.py b/kmip/core/factories/payloads/response.py index 7792825..4349451 100644 --- a/kmip/core/factories/payloads/response.py +++ b/kmip/core/factories/payloads/response.py @@ -33,6 +33,7 @@ from kmip.core.messages.payloads import register from kmip.core.messages.payloads import revoke from kmip.core.messages.payloads import mac from kmip.core.messages.payloads import sign +from kmip.core.messages.payloads import signature_verify class ResponsePayloadFactory(PayloadFactory): @@ -90,3 +91,6 @@ class ResponsePayloadFactory(PayloadFactory): def _create_sign_payload(self): return sign.SignResponsePayload() + + def _create_signature_verify_payload(self): + return signature_verify.SignatureVerifyResponsePayload() diff --git a/kmip/core/messages/payloads/signature_verify.py b/kmip/core/messages/payloads/signature_verify.py new file mode 100644 index 0000000..656cb11 --- /dev/null +++ b/kmip/core/messages/payloads/signature_verify.py @@ -0,0 +1,650 @@ +# Copyright (c) 2017 The Johns Hopkins University/Applied Physics Laboratory +# 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. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +import six + +from kmip.core import attributes +from kmip.core import enums +from kmip.core import primitives +from kmip.core import utils + + +class SignatureVerifyRequestPayload(primitives.Struct): + """ + A request payload for the SignatureVerify operation. + + Attributes: + unique_identifier: The unique ID of the key to use for signature + verification. + cryptographic_parameters: A collection of settings relevant for the + signature verification process. + data: The data that was signed. + digested_data: The digested data to be verified. + signature_data: The signature to be verified. + correlation_value: An identifier for an existing, incomplete operation + this payload hooks into. + init_indicator: A boolean indicating whether or not the payload is the + first in a series for a multi-payload operation. + final_indicator: A boolean indicating whether or not the payload is + the last in a series for a multi-payload operation. + """ + + def __init__(self, + unique_identifier=None, + cryptographic_parameters=None, + data=None, + digested_data=None, + signature_data=None, + correlation_value=None, + init_indicator=None, + final_indicator=None): + """ + Construct a SignatureVerify request payload struct. + + Args: + unique_identifier (string): The ID of the managed object (e.g., + a public key) to be used for signature verification. Optional, + defaults to None. + cryptographic_parameters (CryptographicParameters): A + CryptographicParameters struct containing the settings for + the signature verification operation. Optional, defaults to + None. + data (bytes): The bytes representing the original data that was + signed. Optional, defaults to None. + digested_data (bytes): The bytes representing the digested data to + be verified with the signature. Optional, defaults to None. + signature_data (bytes): The bytes representing the signature to be + verified. Optional, defaults to None. + correlation_value (bytes): The bytes representing a correlation + value, allowing the linking together of individual payloads + for a single overarching operation. Optional, defaults to None. + init_indicator (boolean): A boolean value indicating whether or not + the payload is the first in a series for a multi-payload + operation. Optional, defaults to None. + final_indicator (boolean): A boolean value indicating whether or + not the payload is the last in a series for a multi-payload + operation. Optional, defaults to None. + """ + super(SignatureVerifyRequestPayload, self).__init__( + enums.Tags.REQUEST_PAYLOAD + ) + + self._unique_identifier = None + self._cryptographic_parameters = None + self._data = None + self._digested_data = None + self._signature_data = None + self._correlation_value = None + self._init_indicator = None + self._final_indicator = None + + self.unique_identifier = unique_identifier + self.cryptographic_parameters = cryptographic_parameters + self.data = data + self.digested_data = digested_data + self.signature_data = signature_data + self.correlation_value = correlation_value + self.init_indicator = init_indicator + self.final_indicator = final_indicator + + @property + def unique_identifier(self): + if self._unique_identifier: + return self._unique_identifier.value + else: + return None + + @unique_identifier.setter + def unique_identifier(self, value): + if value is None: + self._unique_identifier = None + elif isinstance(value, six.string_types): + self._unique_identifier = primitives.TextString( + value=value, + tag=enums.Tags.UNIQUE_IDENTIFIER + ) + else: + raise TypeError("Unique identifier must be a string.") + + @property + def cryptographic_parameters(self): + return self._cryptographic_parameters + + @cryptographic_parameters.setter + def cryptographic_parameters(self, value): + if value is None: + self._cryptographic_parameters = None + elif isinstance(value, attributes.CryptographicParameters): + self._cryptographic_parameters = value + else: + raise TypeError( + "Cryptographic parameters must be a CryptographicParameters " + "struct." + ) + + @property + def data(self): + if self._data: + return self._data.value + else: + return None + + @data.setter + def data(self, value): + if value is None: + self._data = None + elif isinstance(value, six.binary_type): + self._data = primitives.ByteString( + value=value, + tag=enums.Tags.DATA + ) + else: + raise TypeError("Data must be bytes.") + + @property + def digested_data(self): + if self._digested_data: + return self._digested_data.value + else: + return None + + @digested_data.setter + def digested_data(self, value): + if value is None: + self._digested_data = None + elif isinstance(value, six.binary_type): + self._digested_data = primitives.ByteString( + value=value, + tag=enums.Tags.DIGESTED_DATA + ) + else: + raise TypeError("Digested data must be bytes.") + + @property + def signature_data(self): + if self._signature_data: + return self._signature_data.value + else: + return None + + @signature_data.setter + def signature_data(self, value): + if value is None: + self._signature_data = None + elif isinstance(value, six.binary_type): + self._signature_data = primitives.ByteString( + value=value, + tag=enums.Tags.SIGNATURE_DATA + ) + else: + raise TypeError("Signature data must be bytes.") + + @property + def correlation_value(self): + if self._correlation_value: + return self._correlation_value.value + else: + return None + + @correlation_value.setter + def correlation_value(self, value): + if value is None: + self._correlation_value = None + elif isinstance(value, six.binary_type): + self._correlation_value = primitives.ByteString( + value=value, + tag=enums.Tags.CORRELATION_VALUE + ) + else: + raise TypeError("Correlation value must be bytes.") + + @property + def init_indicator(self): + if self._init_indicator: + return self._init_indicator.value + else: + return None + + @init_indicator.setter + def init_indicator(self, value): + if value is None: + self._init_indicator = None + elif isinstance(value, bool): + self._init_indicator = primitives.Boolean( + value=value, + tag=enums.Tags.INIT_INDICATOR + ) + else: + raise TypeError("Init indicator must be a boolean.") + + @property + def final_indicator(self): + if self._final_indicator: + return self._final_indicator.value + else: + return None + + @final_indicator.setter + def final_indicator(self, value): + if value is None: + self._final_indicator = None + elif isinstance(value, bool): + self._final_indicator = primitives.Boolean( + value=value, + tag=enums.Tags.FINAL_INDICATOR + ) + else: + raise TypeError("Final indicator must be a boolean.") + + def read(self, input_stream): + """ + Read the data encoding the SignatureVerify request payload and decode + it into its constituent parts. + + Args: + input_stream (stream): A data stream containing encoded object + data, supporting a read method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if the data attribute is missing from the + encoded payload. + """ + super(SignatureVerifyRequestPayload, self).read(input_stream) + local_stream = utils.BytearrayStream(input_stream.read(self.length)) + + if self.is_tag_next(enums.Tags.UNIQUE_IDENTIFIER, local_stream): + self._unique_identifier = primitives.TextString( + tag=enums.Tags.UNIQUE_IDENTIFIER + ) + self._unique_identifier.read(local_stream) + if self.is_tag_next(enums.Tags.CRYPTOGRAPHIC_PARAMETERS, local_stream): + self._cryptographic_parameters = \ + attributes.CryptographicParameters() + self._cryptographic_parameters.read(local_stream) + if self.is_tag_next(enums.Tags.DATA, local_stream): + self._data = primitives.ByteString(tag=enums.Tags.DATA) + self._data.read(local_stream) + if self.is_tag_next(enums.Tags.DIGESTED_DATA, local_stream): + self._digested_data = primitives.ByteString( + tag=enums.Tags.DIGESTED_DATA + ) + self._digested_data.read(local_stream) + if self.is_tag_next(enums.Tags.SIGNATURE_DATA, local_stream): + self._signature_data = primitives.ByteString( + tag=enums.Tags.SIGNATURE_DATA + ) + self._signature_data.read(local_stream) + if self.is_tag_next(enums.Tags.CORRELATION_VALUE, local_stream): + self._correlation_value = primitives.ByteString( + tag=enums.Tags.CORRELATION_VALUE + ) + self._correlation_value.read(local_stream) + if self.is_tag_next(enums.Tags.INIT_INDICATOR, local_stream): + self._init_indicator = primitives.Boolean( + tag=enums.Tags.INIT_INDICATOR + ) + self._init_indicator.read(local_stream) + if self.is_tag_next(enums.Tags.FINAL_INDICATOR, local_stream): + self._final_indicator = primitives.Boolean( + tag=enums.Tags.FINAL_INDICATOR + ) + self._final_indicator.read(local_stream) + + self.is_oversized(local_stream) + + def write(self, output_stream): + """ + Write the data encoding the SignatureVerify request payload to a + stream. + + Args: + output_stream (stream): A data stream in which to encode object + data, supporting a write method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if the data attribute is not defined. + """ + local_stream = utils.BytearrayStream() + + if self._unique_identifier: + self._unique_identifier.write(local_stream) + if self._cryptographic_parameters: + self._cryptographic_parameters.write(local_stream) + if self._data: + self._data.write(local_stream) + if self._digested_data: + self._digested_data.write(local_stream) + if self._signature_data: + self._signature_data.write(local_stream) + if self._correlation_value: + self._correlation_value.write(local_stream) + if self._init_indicator: + self._init_indicator.write(local_stream) + if self._final_indicator: + self._final_indicator.write(local_stream) + + self.length = local_stream.length() + super(SignatureVerifyRequestPayload, self).write(output_stream) + output_stream.write(local_stream.buffer) + + def __eq__(self, other): + if isinstance(other, SignatureVerifyRequestPayload): + if self.unique_identifier != other.unique_identifier: + return False + elif self.cryptographic_parameters != \ + other.cryptographic_parameters: + return False + elif self.data != other.data: + return False + elif self.digested_data != other.digested_data: + return False + elif self.signature_data != other.signature_data: + return False + elif self.correlation_value != other.correlation_value: + return False + elif self.init_indicator != other.init_indicator: + return False + elif self.final_indicator != other.final_indicator: + return False + else: + return True + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, SignatureVerifyRequestPayload): + return not (self == other) + else: + return NotImplemented + + def __repr__(self): + args = ", ".join([ + "unique_identifier='{0}'".format(self.unique_identifier), + "cryptographic_parameters={0}".format( + repr(self.cryptographic_parameters) + ), + "data={0}".format(self.data), + "digested_data={0}".format(self.digested_data), + "signature_data={0}".format(self.signature_data), + "correlation_value={0}".format(self.correlation_value), + "init_indicator={0}".format(self.init_indicator), + "final_indicator={0}".format(self.final_indicator) + ]) + return "SignatureVerifyRequestPayload({0})".format(args) + + def __str__(self): + return str({ + 'unique_identifier': self.unique_identifier, + 'cryptographic_parameters': self.cryptographic_parameters, + 'data': self.data, + 'digested_data': self.digested_data, + 'signature_data': self.signature_data, + 'correlation_value': self.correlation_value, + 'init_indicator': self.init_indicator, + 'final_indicator': self.final_indicator + }) + + +class SignatureVerifyResponsePayload(primitives.Struct): + """ + A response payload for the SignatureVerify operation. + + Attributes: + unique_identifier: The unique ID of the key used for signature + verification. + validity_indicator: The validity of the verified signature. + data: Recovered data produced by the signature verification process. + correlation_value: An identifier for an existing, incomplete operation + this payload is a part of. + """ + + def __init__(self, + unique_identifier=None, + validity_indicator=None, + data=None, + correlation_value=None): + """ + Construct a SignatureVerify response payload struct. + + Args: + unique_identifier (string): The ID of the managed object (e.g., + a public key) used for signature verification. Optional, + defaults to None. Required for read/write. + validity_indicator (ValidityIndicator): A ValidityIndicator + enumeration that specifies the validity of the signature. + Optional, defaults to None. Required for read/write. + data (bytes): The bytes representing any data recovered during the + signature verification process. Optional, defaults to None. + correlation_value (bytes): The bytes representing a correlation + value, allowing the linking together of individual payloads + for a single overarching operation. Optional, defaults to None. + """ + super(SignatureVerifyResponsePayload, self).__init__( + enums.Tags.RESPONSE_PAYLOAD + ) + + self._unique_identifier = None + self._validity_indicator = None + self._data = None + self._correlation_value = None + + self.unique_identifier = unique_identifier + self.validity_indicator = validity_indicator + self.data = data + self.correlation_value = correlation_value + + @property + def unique_identifier(self): + if self._unique_identifier: + return self._unique_identifier.value + else: + return None + + @unique_identifier.setter + def unique_identifier(self, value): + if value is None: + self._unique_identifier = None + elif isinstance(value, six.string_types): + self._unique_identifier = primitives.TextString( + value=value, + tag=enums.Tags.UNIQUE_IDENTIFIER + ) + else: + raise TypeError("Unique identifier must be a string.") + + @property + def validity_indicator(self): + if self._validity_indicator: + return self._validity_indicator.value + else: + return None + + @validity_indicator.setter + def validity_indicator(self, value): + if value is None: + self._validity_indicator = None + elif isinstance(value, enums.ValidityIndicator): + self._validity_indicator = primitives.Enumeration( + enums.ValidityIndicator, + value=value, + tag=enums.Tags.VALIDITY_INDICATOR + ) + else: + raise TypeError( + "Validity indicator must be a ValidityIndicator enumeration." + ) + + @property + def data(self): + if self._data: + return self._data.value + else: + return None + + @data.setter + def data(self, value): + if value is None: + self._data = None + elif isinstance(value, six.binary_type): + self._data = primitives.ByteString( + value=value, + tag=enums.Tags.DATA + ) + else: + raise TypeError("Data must be bytes.") + + @property + def correlation_value(self): + if self._correlation_value: + return self._correlation_value.value + else: + return None + + @correlation_value.setter + def correlation_value(self, value): + if value is None: + self._correlation_value = None + elif isinstance(value, six.binary_type): + self._correlation_value = primitives.ByteString( + value=value, + tag=enums.Tags.CORRELATION_VALUE + ) + else: + raise TypeError("Correlation value must be bytes.") + + def read(self, input_stream): + """ + Read the data encoding the SignatureVerify response payload and decode + it into its constituent parts. + + Args: + input_stream (stream): A data stream containing encoded object + data, supporting a read method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if the data attribute is missing from the + encoded payload. + """ + super(SignatureVerifyResponsePayload, self).read(input_stream) + local_stream = utils.BytearrayStream(input_stream.read(self.length)) + + if self.is_tag_next(enums.Tags.UNIQUE_IDENTIFIER, local_stream): + self._unique_identifier = primitives.TextString( + tag=enums.Tags.UNIQUE_IDENTIFIER + ) + self._unique_identifier.read(local_stream) + else: + raise ValueError( + "Parsed payload encoding is missing the unique identifier " + "field." + ) + if self.is_tag_next(enums.Tags.VALIDITY_INDICATOR, local_stream): + self._validity_indicator = primitives.Enumeration( + enums.ValidityIndicator, + tag=enums.Tags.VALIDITY_INDICATOR + ) + self._validity_indicator.read(local_stream) + else: + raise ValueError( + "Parsed payload encoding is missing the validity indicator " + "field." + ) + if self.is_tag_next(enums.Tags.DATA, local_stream): + self._data = primitives.ByteString(tag=enums.Tags.DATA) + self._data.read(local_stream) + if self.is_tag_next(enums.Tags.CORRELATION_VALUE, local_stream): + self._correlation_value = primitives.ByteString( + tag=enums.Tags.CORRELATION_VALUE + ) + self._correlation_value.read(local_stream) + + self.is_oversized(local_stream) + + def write(self, output_stream): + """ + Write the data encoding the SignatureVerify response payload to a + stream. + + Args: + output_stream (stream): A data stream in which to encode object + data, supporting a write method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if the data attribute is not defined. + """ + local_stream = utils.BytearrayStream() + + if self._unique_identifier: + self._unique_identifier.write(local_stream) + else: + raise ValueError( + "Payload is missing the unique identifier field." + ) + if self._validity_indicator: + self._validity_indicator.write(local_stream) + else: + raise ValueError( + "Payload is missing the validity indicator field." + ) + if self._data: + self._data.write(local_stream) + if self._correlation_value: + self._correlation_value.write(local_stream) + + self.length = local_stream.length() + super(SignatureVerifyResponsePayload, self).write(output_stream) + output_stream.write(local_stream.buffer) + + def __eq__(self, other): + if isinstance(other, SignatureVerifyResponsePayload): + if self.unique_identifier != other.unique_identifier: + return False + elif self.validity_indicator != other.validity_indicator: + return False + elif self.data != other.data: + return False + elif self.correlation_value != other.correlation_value: + return False + else: + return True + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, SignatureVerifyResponsePayload): + return not (self == other) + else: + return NotImplemented + + def __repr__(self): + args = ", ".join([ + "unique_identifier='{0}'".format(self.unique_identifier), + "validity_indicator={0}".format(self.validity_indicator), + "data={0}".format(self.data), + "correlation_value={0}".format(self.correlation_value) + ]) + return "SignatureVerifyResponsePayload({0})".format(args) + + def __str__(self): + return str({ + 'unique_identifier': self.unique_identifier, + 'validity_indicator': self.validity_indicator, + 'data': self.data, + 'correlation_value': self.correlation_value + }) diff --git a/kmip/tests/unit/core/factories/payloads/test_request.py b/kmip/tests/unit/core/factories/payloads/test_request.py index 5872aaa..3e8fc02 100644 --- a/kmip/tests/unit/core/factories/payloads/test_request.py +++ b/kmip/tests/unit/core/factories/payloads/test_request.py @@ -35,6 +35,7 @@ from kmip.core.messages.payloads import rekey_key_pair from kmip.core.messages.payloads import register from kmip.core.messages.payloads import revoke from kmip.core.messages.payloads import sign +from kmip.core.messages.payloads import signature_verify from kmip.core.messages.payloads import mac @@ -222,9 +223,10 @@ class TestRequestPayloadFactory(testtools.TestCase): self._test_payload_type(payload, sign.SignRequestPayload) def test_create_signature_verify_payload(self): - self._test_not_implemented( - self.factory.create, - enums.Operation.SIGNATURE_VERIFY + payload = self.factory.create(enums.Operation.SIGNATURE_VERIFY) + self._test_payload_type( + payload, + signature_verify.SignatureVerifyRequestPayload ) def test_create_mac_payload(self): diff --git a/kmip/tests/unit/core/factories/payloads/test_response.py b/kmip/tests/unit/core/factories/payloads/test_response.py index 70dc914..0278806 100644 --- a/kmip/tests/unit/core/factories/payloads/test_response.py +++ b/kmip/tests/unit/core/factories/payloads/test_response.py @@ -35,6 +35,7 @@ from kmip.core.messages.payloads import rekey_key_pair from kmip.core.messages.payloads import register from kmip.core.messages.payloads import revoke from kmip.core.messages.payloads import sign +from kmip.core.messages.payloads import signature_verify from kmip.core.messages.payloads import mac @@ -220,9 +221,10 @@ class TestResponsePayloadFactory(testtools.TestCase): self._test_payload_type(payload, sign.SignResponsePayload) def test_create_signature_verify_payload(self): - self._test_not_implemented( - self.factory.create, - enums.Operation.SIGNATURE_VERIFY + payload = self.factory.create(enums.Operation.SIGNATURE_VERIFY) + self._test_payload_type( + payload, + signature_verify.SignatureVerifyResponsePayload ) def test_create_mac_payload(self): diff --git a/kmip/tests/unit/core/messages/payloads/test_signature_verify.py b/kmip/tests/unit/core/messages/payloads/test_signature_verify.py new file mode 100644 index 0000000..478eed2 --- /dev/null +++ b/kmip/tests/unit/core/messages/payloads/test_signature_verify.py @@ -0,0 +1,1585 @@ +# Copyright (c) 2017 The Johns Hopkins University/Applied Physics Laboratory +# 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. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +import testtools + +from kmip.core import attributes +from kmip.core import enums +from kmip.core import utils + +from kmip.core.messages.payloads import signature_verify + + +class TestSignatureVerifyRequestPayload(testtools.TestCase): + """ + Test suite for the SignatureVerify request payload. + """ + + def setUp(self): + super(TestSignatureVerifyRequestPayload, self).setUp() + + # Encoding obtained in part from the KMIP 1.1 testing document, + # Sections 3.1.3 and 14.1. The rest of the encoding was built by + # hand. + # + # This encoding matches the following set of values: + # Request Payload + # Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038 + # Cryptographic Parameters + # Digital Signature Algorithm - SHA 256 with RSA + # Data + # 0xCDC87DA223D786DF3B45E0BBBC721326D1EE2AF806CC315475CC6F0D9C + # 66E1B62371D45CE2392E1AC92844C310102F156A0D8D52C1F4C40BA3AA65 + # 095786CB769757A6563BA958FED0BCC984E8B517A3D5F515B23B8A41E74A + # A867693F90DFB061A6E86DFAAEE64472C00E5F20945729CBEBE77F06CE78 + # E08F4098FBA41F9D6193C0317E8B60D4B6084ACB42D29E3808A3BC372D85 + # E331170FCBF7CC72D0B71C296648B3A4D10F416295D0807AA625CAB2744F + # D9EA8FD223C42537029828BD16BE02546F130FD2E33B936D2676E08AED1B + # 73318B750A0167D0 + # Digested Data + # 0x01020304050607080910111213141516 + # Signature Data + # 0x6BC3A06656842930A247E30D5864B4D819236BA7C68965862AD7DBC4E2 + # 4AF28E86BB531F03358BE5FB74777C6086F850CAEF893F0D6FCC2D0C91EC + # 013693B4EA00B80CD49AAC4ECB5F8911AFE539ADA4A8F3823D1D13E472D1 + # 490547C659C7617F3D24087DDB6F2B72096167FC097CAB18E9A458FCB634 + # CDCE8EE35894C484D7 + # Correlation Value - 1 + # Init Indicator - True + # Final Indicator - False + + self.full_encoding = utils.BytearrayStream( + b'\x42\x00\x79\x01\x00\x00\x02\x00' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66' + b'\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63' + b'\x33\x30\x33\x38\x00\x00\x00\x00' + b'\x42\x00\x2B\x01\x00\x00\x00\x10' + b'\x42\x00\xAE\x05\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x00' + b'\x42\x00\xC2\x08\x00\x00\x00\xD9' + b'\xCD\xC8\x7D\xA2\x23\xD7\x86\xDF\x3B\x45\xE0\xBB\xBC\x72\x13\x26' + b'\xD1\xEE\x2A\xF8\x06\xCC\x31\x54\x75\xCC\x6F\x0D\x9C\x66\xE1\xB6' + b'\x23\x71\xD4\x5C\xE2\x39\x2E\x1A\xC9\x28\x44\xC3\x10\x10\x2F\x15' + b'\x6A\x0D\x8D\x52\xC1\xF4\xC4\x0B\xA3\xAA\x65\x09\x57\x86\xCB\x76' + b'\x97\x57\xA6\x56\x3B\xA9\x58\xFE\xD0\xBC\xC9\x84\xE8\xB5\x17\xA3' + b'\xD5\xF5\x15\xB2\x3B\x8A\x41\xE7\x4A\xA8\x67\x69\x3F\x90\xDF\xB0' + b'\x61\xA6\xE8\x6D\xFA\xAE\xE6\x44\x72\xC0\x0E\x5F\x20\x94\x57\x29' + b'\xCB\xEB\xE7\x7F\x06\xCE\x78\xE0\x8F\x40\x98\xFB\xA4\x1F\x9D\x61' + b'\x93\xC0\x31\x7E\x8B\x60\xD4\xB6\x08\x4A\xCB\x42\xD2\x9E\x38\x08' + b'\xA3\xBC\x37\x2D\x85\xE3\x31\x17\x0F\xCB\xF7\xCC\x72\xD0\xB7\x1C' + b'\x29\x66\x48\xB3\xA4\xD1\x0F\x41\x62\x95\xD0\x80\x7A\xA6\x25\xCA' + b'\xB2\x74\x4F\xD9\xEA\x8F\xD2\x23\xC4\x25\x37\x02\x98\x28\xBD\x16' + b'\xBE\x02\x54\x6F\x13\x0F\xD2\xE3\x3B\x93\x6D\x26\x76\xE0\x8A\xED' + b'\x1B\x73\x31\x8B\x75\x0A\x01\x67\xD0\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x01\x07\x08\x00\x00\x00\x10' + b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16' + b'\x42\x00\xC3\x08\x00\x00\x00\x80' + b'\x6B\xC3\xA0\x66\x56\x84\x29\x30\xA2\x47\xE3\x0D\x58\x64\xB4\xD8' + b'\x19\x23\x6B\xA7\xC6\x89\x65\x86\x2A\xD7\xDB\xC4\xE2\x4A\xF2\x8E' + b'\x86\xBB\x53\x1F\x03\x35\x8B\xE5\xFB\x74\x77\x7C\x60\x86\xF8\x50' + b'\xCA\xEF\x89\x3F\x0D\x6F\xCC\x2D\x0C\x91\xEC\x01\x36\x93\xB4\xEA' + b'\x00\xB8\x0C\xD4\x9A\xAC\x4E\xCB\x5F\x89\x11\xAF\xE5\x39\xAD\xA4' + b'\xA8\xF3\x82\x3D\x1D\x13\xE4\x72\xD1\x49\x05\x47\xC6\x59\xC7\x61' + b'\x7F\x3D\x24\x08\x7D\xDB\x6F\x2B\x72\x09\x61\x67\xFC\x09\x7C\xAB' + b'\x18\xE9\xA4\x58\xFC\xB6\x34\xCD\xCE\x8E\xE3\x58\x94\xC4\x84\xD7' + b'\x42\x00\xD6\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xD7\x06\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01' + b'\x42\x00\xD8\x06\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00' + ) + + # Encoding obtained in part from the KMIP 1.1 testing document, + # Sections 3.1.3 and 14.1. The rest of the encoding was built by + # hand. + # + # This encoding matches the following set of values: + # Request Payload + # Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038 + # Cryptographic Parameters + # Digital Signature Algorithm - SHA 256 with RSA + # Signature Data + # 0x6BC3A06656842930A247E30D5864B4D819236BA7C68965862AD7DBC4E2 + # 4AF28E86BB531F03358BE5FB74777C6086F850CAEF893F0D6FCC2D0C91EC + # 013693B4EA00B80CD49AAC4ECB5F8911AFE539ADA4A8F3823D1D13E472D1 + # 490547C659C7617F3D24087DDB6F2B72096167FC097CAB18E9A458FCB634 + # CDCE8EE35894C484D7 + + self.partial_encoding = utils.BytearrayStream( + b'\x42\x00\x79\x01\x00\x00\x00\xD0' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66' + b'\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63' + b'\x33\x30\x33\x38\x00\x00\x00\x00' + b'\x42\x00\x2B\x01\x00\x00\x00\x10' + b'\x42\x00\xAE\x05\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x00' + b'\x42\x00\xC3\x08\x00\x00\x00\x80' + b'\x6B\xC3\xA0\x66\x56\x84\x29\x30\xA2\x47\xE3\x0D\x58\x64\xB4\xD8' + b'\x19\x23\x6B\xA7\xC6\x89\x65\x86\x2A\xD7\xDB\xC4\xE2\x4A\xF2\x8E' + b'\x86\xBB\x53\x1F\x03\x35\x8B\xE5\xFB\x74\x77\x7C\x60\x86\xF8\x50' + b'\xCA\xEF\x89\x3F\x0D\x6F\xCC\x2D\x0C\x91\xEC\x01\x36\x93\xB4\xEA' + b'\x00\xB8\x0C\xD4\x9A\xAC\x4E\xCB\x5F\x89\x11\xAF\xE5\x39\xAD\xA4' + b'\xA8\xF3\x82\x3D\x1D\x13\xE4\x72\xD1\x49\x05\x47\xC6\x59\xC7\x61' + b'\x7F\x3D\x24\x08\x7D\xDB\x6F\x2B\x72\x09\x61\x67\xFC\x09\x7C\xAB' + b'\x18\xE9\xA4\x58\xFC\xB6\x34\xCD\xCE\x8E\xE3\x58\x94\xC4\x84\xD7' + ) + + self.empty_encoding = utils.BytearrayStream( + b'\x42\x00\x79\x01\x00\x00\x00\x00' + ) + + self.data = ( + b'\xCD\xC8\x7D\xA2\x23\xD7\x86\xDF\x3B\x45\xE0\xBB\xBC\x72\x13\x26' + b'\xD1\xEE\x2A\xF8\x06\xCC\x31\x54\x75\xCC\x6F\x0D\x9C\x66\xE1\xB6' + b'\x23\x71\xD4\x5C\xE2\x39\x2E\x1A\xC9\x28\x44\xC3\x10\x10\x2F\x15' + b'\x6A\x0D\x8D\x52\xC1\xF4\xC4\x0B\xA3\xAA\x65\x09\x57\x86\xCB\x76' + b'\x97\x57\xA6\x56\x3B\xA9\x58\xFE\xD0\xBC\xC9\x84\xE8\xB5\x17\xA3' + b'\xD5\xF5\x15\xB2\x3B\x8A\x41\xE7\x4A\xA8\x67\x69\x3F\x90\xDF\xB0' + b'\x61\xA6\xE8\x6D\xFA\xAE\xE6\x44\x72\xC0\x0E\x5F\x20\x94\x57\x29' + b'\xCB\xEB\xE7\x7F\x06\xCE\x78\xE0\x8F\x40\x98\xFB\xA4\x1F\x9D\x61' + b'\x93\xC0\x31\x7E\x8B\x60\xD4\xB6\x08\x4A\xCB\x42\xD2\x9E\x38\x08' + b'\xA3\xBC\x37\x2D\x85\xE3\x31\x17\x0F\xCB\xF7\xCC\x72\xD0\xB7\x1C' + b'\x29\x66\x48\xB3\xA4\xD1\x0F\x41\x62\x95\xD0\x80\x7A\xA6\x25\xCA' + b'\xB2\x74\x4F\xD9\xEA\x8F\xD2\x23\xC4\x25\x37\x02\x98\x28\xBD\x16' + b'\xBE\x02\x54\x6F\x13\x0F\xD2\xE3\x3B\x93\x6D\x26\x76\xE0\x8A\xED' + b'\x1B\x73\x31\x8B\x75\x0A\x01\x67\xD0' + ) + self.digested_data = ( + b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16' + ) + self.signature_data = ( + b'\x6B\xC3\xA0\x66\x56\x84\x29\x30\xA2\x47\xE3\x0D\x58\x64\xB4\xD8' + b'\x19\x23\x6B\xA7\xC6\x89\x65\x86\x2A\xD7\xDB\xC4\xE2\x4A\xF2\x8E' + b'\x86\xBB\x53\x1F\x03\x35\x8B\xE5\xFB\x74\x77\x7C\x60\x86\xF8\x50' + b'\xCA\xEF\x89\x3F\x0D\x6F\xCC\x2D\x0C\x91\xEC\x01\x36\x93\xB4\xEA' + b'\x00\xB8\x0C\xD4\x9A\xAC\x4E\xCB\x5F\x89\x11\xAF\xE5\x39\xAD\xA4' + b'\xA8\xF3\x82\x3D\x1D\x13\xE4\x72\xD1\x49\x05\x47\xC6\x59\xC7\x61' + b'\x7F\x3D\x24\x08\x7D\xDB\x6F\x2B\x72\x09\x61\x67\xFC\x09\x7C\xAB' + b'\x18\xE9\xA4\x58\xFC\xB6\x34\xCD\xCE\x8E\xE3\x58\x94\xC4\x84\xD7' + ) + + def tearDown(self): + super(TestSignatureVerifyRequestPayload, self).tearDown() + + def test_init(self): + """ + Test that a SignatureVerify request payload can be constructed with no + arguments. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.cryptographic_parameters) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(None, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + def test_init_with_args(self): + """ + Test that a SignatureVerify request payload can be constructed with + valid values + """ + payload = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='00000000-1111-2222-3333-444444444444', + cryptographic_parameters=attributes.CryptographicParameters(), + data=b'\x01\x02\x03', + digested_data=b'\x11\x22\x33', + signature_data=b'\x10\x20\x30', + correlation_value=b'\xFF', + init_indicator=False, + final_indicator=True + ) + + self.assertEqual( + '00000000-1111-2222-3333-444444444444', + payload.unique_identifier + ) + self.assertEqual( + attributes.CryptographicParameters(), + payload.cryptographic_parameters + ) + self.assertEqual(b'\x01\x02\x03', payload.data) + self.assertEqual(b'\x11\x22\x33', payload.digested_data) + self.assertEqual(b'\x10\x20\x30', payload.signature_data) + self.assertEqual(b'\xFF', payload.correlation_value) + self.assertEqual(False, payload.init_indicator) + self.assertEqual(True, payload.final_indicator) + + def test_invalid_unique_identifier(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the unique identifier of a SignatureVerify request payload. + """ + kwargs = {'unique_identifier': 0} + self.assertRaisesRegexp( + TypeError, + "Unique identifier must be a string.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'unique_identifier', 0) + self.assertRaisesRegexp( + TypeError, + "Unique identifier must be a string.", + setattr, + *args + ) + + def test_invalid_cryptographic_parameters(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the cryptographic parameters of a SignatureVerify request payload. + """ + kwargs = {'cryptographic_parameters': 0} + self.assertRaisesRegexp( + TypeError, + "Cryptographic parameters must be a CryptographicParameters " + "struct.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'cryptographic_parameters', 'invalid') + self.assertRaisesRegexp( + TypeError, + "Cryptographic parameters must be a CryptographicParameters " + "struct.", + setattr, + *args + ) + + def test_invalid_data(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the data of a SignatureVerify request payload. + """ + kwargs = {'data': 0} + self.assertRaisesRegexp( + TypeError, + "Data must be bytes.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'data', 0) + self.assertRaisesRegexp( + TypeError, + "Data must be bytes.", + setattr, + *args + ) + + def test_invalid_digested_data(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the digested data of a SignatureVerify request payload. + """ + kwargs = {'digested_data': 0} + self.assertRaisesRegexp( + TypeError, + "Digested data must be bytes.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'digested_data', 0) + self.assertRaisesRegexp( + TypeError, + "Digested data must be bytes.", + setattr, + *args + ) + + def test_invalid_signature_data(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the signature data of a SignatureVerify request payload. + """ + kwargs = {'signature_data': 0} + self.assertRaisesRegexp( + TypeError, + "Signature data must be bytes.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'signature_data', 0) + self.assertRaisesRegexp( + TypeError, + "Signature data must be bytes.", + setattr, + *args + ) + + def test_invalid_correlation_value(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the correlation value of a SignatureVerify request payload. + """ + kwargs = {'correlation_value': 0} + self.assertRaisesRegexp( + TypeError, + "Correlation value must be bytes.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'correlation_value', 0) + self.assertRaisesRegexp( + TypeError, + "Correlation value must be bytes.", + setattr, + *args + ) + + def test_invalid_init_indicator(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the init indicator of a SignatureVerify request payload. + """ + kwargs = {'init_indicator': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Init indicator must be a boolean.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'init_indicator', 'invalid') + self.assertRaisesRegexp( + TypeError, + "Init indicator must be a boolean.", + setattr, + *args + ) + + def test_invalid_final_indicator(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the final indicator of a SignatureVerify request payload. + """ + kwargs = {'final_indicator': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Final indicator must be a boolean.", + signature_verify.SignatureVerifyRequestPayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyRequestPayload() + args = (payload, 'final_indicator', 'invalid') + self.assertRaisesRegexp( + TypeError, + "Final indicator must be a boolean.", + setattr, + *args + ) + + def test_read(self): + """ + Test that a SignatureVerify request payload can be read from a data + stream. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.cryptographic_parameters) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(None, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + payload.read(self.full_encoding) + + self.assertEqual( + '49a1ca88-6bea-4fb2-b450-7e58802c3038', + payload.unique_identifier + ) + self.assertIsInstance( + payload.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION, + payload.cryptographic_parameters.digital_signature_algorithm + ) + self.assertEqual(self.data, payload.data) + self.assertEqual(self.digested_data, payload.digested_data) + self.assertEqual(self.signature_data, payload.signature_data) + self.assertEqual(b'\x01', payload.correlation_value) + self.assertEqual(True, payload.init_indicator) + self.assertEqual(False, payload.final_indicator) + + def test_read_partial(self): + """ + Test that a SignatureVerify request payload can be read from a partial + data stream containing the minimum required attributes. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.cryptographic_parameters) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(None, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + payload.read(self.partial_encoding) + + self.assertEqual( + '49a1ca88-6bea-4fb2-b450-7e58802c3038', + payload.unique_identifier + ) + self.assertIsInstance( + payload.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION, + payload.cryptographic_parameters.digital_signature_algorithm + ) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(self.signature_data, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + def test_read_empty(self): + """ + Test that a SignatureVerify request payload can be read from an empty + data stream containing the minimum required attributes. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.cryptographic_parameters) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(None, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + payload.read(self.empty_encoding) + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.cryptographic_parameters) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.digested_data) + self.assertEqual(None, payload.signature_data) + self.assertEqual(None, payload.correlation_value) + self.assertEqual(None, payload.init_indicator) + self.assertEqual(None, payload.final_indicator) + + def test_write(self): + """ + Test that a SignatureVerify request payload can be written to a data + stream. + """ + payload = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=self.data, + digested_data=self.digested_data, + signature_data=self.signature_data, + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(len(self.full_encoding), len(stream)) + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_write_partial(self): + """ + Test that a partially defined SignatureVerify request payload can be + written to a data stream. + """ + payload = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + signature_data=self.signature_data + ) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(len(self.partial_encoding), len(stream)) + self.assertEqual(str(self.partial_encoding), str(stream)) + + def test_write_empty(self): + """ + Test that an empty SignatureVerify request payload can be written to a + data stream. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(len(self.empty_encoding), len(stream)) + self.assertEqual(str(self.empty_encoding), str(stream)) + + def test_equal_on_equal(self): + """ + Test that the equality operator returns True when comparing two + SignatureVerify request payloads with the same data. + """ + a = signature_verify.SignatureVerifyRequestPayload() + b = signature_verify.SignatureVerifyRequestPayload() + + self.assertTrue(a == b) + self.assertTrue(b == a) + + a = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=self.data, + digested_data=self.digested_data, + signature_data=self.signature_data, + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + b = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=self.data, + digested_data=self.digested_data, + signature_data=self.signature_data, + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_equal_on_not_equal_unique_identifier(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different unique identifiers. + """ + a = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='a' + ) + b = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='b' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_cryptographic_parameters(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different cryptographic + parameters. + """ + a = signature_verify.SignatureVerifyRequestPayload( + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums. + DigitalSignatureAlgorithm.DSA_WITH_SHA1 + ) + ) + b = signature_verify.SignatureVerifyRequestPayload( + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums. + DigitalSignatureAlgorithm.ECDSA_WITH_SHA256 + ) + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_data(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different data. + """ + a = signature_verify.SignatureVerifyRequestPayload(data=b'\x11') + b = signature_verify.SignatureVerifyRequestPayload(data=b'\xFF') + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_digested_data(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different digested data. + """ + a = signature_verify.SignatureVerifyRequestPayload( + digested_data=b'\x00\x01\x02\x03' + ) + b = signature_verify.SignatureVerifyRequestPayload( + digested_data=b'\xAA\xBB\xCC\xDD' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_signature_data(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different signature data. + """ + a = signature_verify.SignatureVerifyRequestPayload( + signature_data=b'\x00\x00\x00\x00' + ) + b = signature_verify.SignatureVerifyRequestPayload( + signature_data=b'\xFF\xFF\xFF\xFF' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_correlation_value(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different correlation values. + """ + a = signature_verify.SignatureVerifyRequestPayload( + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyRequestPayload( + correlation_value=b'\x02' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_init_indicator(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different init indicators. + """ + a = signature_verify.SignatureVerifyRequestPayload( + init_indicator=True + ) + b = signature_verify.SignatureVerifyRequestPayload( + init_indicator=False + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_final_indicator(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different final indicators. + """ + a = signature_verify.SignatureVerifyRequestPayload( + final_indicator=False + ) + b = signature_verify.SignatureVerifyRequestPayload( + final_indicator=True + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_type_mismatch(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify request payloads with different types. + """ + a = signature_verify.SignatureVerifyRequestPayload() + b = 'invalid' + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_not_equal_on_equal(self): + """ + Test that the inequality operator returns False when comparing two + SignatureVerify request payloads with the same data. + """ + a = signature_verify.SignatureVerifyRequestPayload() + b = signature_verify.SignatureVerifyRequestPayload() + + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=self.data, + digested_data=self.digested_data, + signature_data=self.signature_data, + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + b = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=self.data, + digested_data=self.digested_data, + signature_data=self.signature_data, + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_not_equal_on_not_equal_unique_identifier(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different unique identifiers. + """ + a = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='a' + ) + b = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='b' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_cryptographic_parameters(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different cryptographic + parameters. + """ + a = signature_verify.SignatureVerifyRequestPayload( + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums. + DigitalSignatureAlgorithm.DSA_WITH_SHA1 + ) + ) + b = signature_verify.SignatureVerifyRequestPayload( + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums. + DigitalSignatureAlgorithm.ECDSA_WITH_SHA256 + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_data(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different data. + """ + a = signature_verify.SignatureVerifyRequestPayload(data=b'\x11') + b = signature_verify.SignatureVerifyRequestPayload(data=b'\xFF') + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_digested_data(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different digested data. + """ + a = signature_verify.SignatureVerifyRequestPayload( + digested_data=b'\x00\x01\x02\x03' + ) + b = signature_verify.SignatureVerifyRequestPayload( + digested_data=b'\xAA\xBB\xCC\xDD' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_signature_data(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different signature data. + """ + a = signature_verify.SignatureVerifyRequestPayload( + signature_data=b'\x00\x00\x00\x00' + ) + b = signature_verify.SignatureVerifyRequestPayload( + signature_data=b'\xFF\xFF\xFF\xFF' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_correlation_value(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different correlation values. + """ + a = signature_verify.SignatureVerifyRequestPayload( + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyRequestPayload( + correlation_value=b'\x02' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_init_indicator(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different init indicators. + """ + a = signature_verify.SignatureVerifyRequestPayload( + init_indicator=True + ) + b = signature_verify.SignatureVerifyRequestPayload( + init_indicator=False + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_final_indicator(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different final indicators. + """ + a = signature_verify.SignatureVerifyRequestPayload( + final_indicator=False + ) + b = signature_verify.SignatureVerifyRequestPayload( + final_indicator=True + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_type_mismatch(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify request payloads with different types. + """ + a = signature_verify.SignatureVerifyRequestPayload() + b = 'invalid' + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test that repr can be applied to a SignatureVerify request payload. + """ + payload = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=attributes.CryptographicParameters( + digital_signature_algorithm=enums.DigitalSignatureAlgorithm. + SHA256_WITH_RSA_ENCRYPTION, + ), + data=b'\x00\x11\x22\x33', + digested_data=b'\x01\x03\x05\x07', + signature_data=b'\xFF\xFF\xFF\xFF', + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + expected = ( + "SignatureVerifyRequestPayload(" + "unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', " + "cryptographic_parameters=CryptographicParameters(" + "block_cipher_mode=None, " + "padding_method=None, " + "hashing_algorithm=None, " + "key_role_type=None, " + "digital_signature_algorithm=" + "DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION, " + "cryptographic_algorithm=None, " + "random_iv=None, " + "iv_length=None, " + "tag_length=None, " + "fixed_field_length=None, " + "invocation_field_length=None, " + "counter_length=None, " + "initial_counter_value=None), " + "data=" + str(b'\x00\x11\x22\x33') + ", " + "digested_data=" + str(b'\x01\x03\x05\x07') + ", " + "signature_data=" + str(b'\xFF\xFF\xFF\xFF') + ", " + "correlation_value=" + str(b'\x01') + ", " + "init_indicator=True, " + "final_indicator=False)" + ) + observed = repr(payload) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to a SignatureVerify request payload + """ + cryptographic_parameters = attributes.CryptographicParameters( + digital_signature_algorithm=enums. + DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ) + payload = signature_verify.SignatureVerifyRequestPayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + cryptographic_parameters=cryptographic_parameters, + data=b'\x00\x11\x22\x33', + digested_data=b'\x01\x03\x05\x07', + signature_data=b'\xFF\xFF\xFF\xFF', + correlation_value=b'\x01', + init_indicator=True, + final_indicator=False + ) + + expected = str({ + 'unique_identifier': '49a1ca88-6bea-4fb2-b450-7e58802c3038', + 'cryptographic_parameters': cryptographic_parameters, + 'data': b'\x00\x11\x22\x33', + 'digested_data': b'\x01\x03\x05\x07', + 'signature_data': b'\xFF\xFF\xFF\xFF', + 'correlation_value': b'\x01', + 'init_indicator': True, + 'final_indicator': False + }) + observed = str(payload) + + self.assertEqual(expected, observed) + + +class TestSignatureVerifyResponsePayload(testtools.TestCase): + """ + Test suite for the SignatureVerify response payload. + """ + + def setUp(self): + super(TestSignatureVerifyResponsePayload, self).setUp() + + # Encoding obtained in part from the KMIP 1.1 testing document, + # Sections 3.1.3 and 14.1. The rest of the encoding was built by + # hand. + # + # This encoding matches the following set of values: + # Request Payload + # Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038 + # Validity Indicator - Valid + # Data + # 0xCDC87DA223D786DF3B45E0BBBC721326D1EE2AF806CC315475CC6F0D9C + # 66E1B62371D45CE2392E1AC92844C310102F156A0D8D52C1F4C40BA3AA65 + # 095786CB769757A6563BA958FED0BCC984E8B517A3D5F515B23B8A41E74A + # A867693F90DFB061A6E86DFAAEE64472C00E5F20945729CBEBE77F06CE78 + # E08F4098FBA41F9D6193C0317E8B60D4B6084ACB42D29E3808A3BC372D85 + # E331170FCBF7CC72D0B71C296648B3A4D10F416295D0807AA625CAB2744F + # D9EA8FD223C42537029828BD16BE02546F130FD2E33B936D2676E08AED1B + # 73318B750A0167D0 + # Correlation Value - 1 + + self.full_encoding = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x01\x38' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66' + b'\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63' + b'\x33\x30\x33\x38\x00\x00\x00\x00' + b'\x42\x00\x9B\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\xC2\x08\x00\x00\x00\xD9' + b'\xCD\xC8\x7D\xA2\x23\xD7\x86\xDF\x3B\x45\xE0\xBB\xBC\x72\x13\x26' + b'\xD1\xEE\x2A\xF8\x06\xCC\x31\x54\x75\xCC\x6F\x0D\x9C\x66\xE1\xB6' + b'\x23\x71\xD4\x5C\xE2\x39\x2E\x1A\xC9\x28\x44\xC3\x10\x10\x2F\x15' + b'\x6A\x0D\x8D\x52\xC1\xF4\xC4\x0B\xA3\xAA\x65\x09\x57\x86\xCB\x76' + b'\x97\x57\xA6\x56\x3B\xA9\x58\xFE\xD0\xBC\xC9\x84\xE8\xB5\x17\xA3' + b'\xD5\xF5\x15\xB2\x3B\x8A\x41\xE7\x4A\xA8\x67\x69\x3F\x90\xDF\xB0' + b'\x61\xA6\xE8\x6D\xFA\xAE\xE6\x44\x72\xC0\x0E\x5F\x20\x94\x57\x29' + b'\xCB\xEB\xE7\x7F\x06\xCE\x78\xE0\x8F\x40\x98\xFB\xA4\x1F\x9D\x61' + b'\x93\xC0\x31\x7E\x8B\x60\xD4\xB6\x08\x4A\xCB\x42\xD2\x9E\x38\x08' + b'\xA3\xBC\x37\x2D\x85\xE3\x31\x17\x0F\xCB\xF7\xCC\x72\xD0\xB7\x1C' + b'\x29\x66\x48\xB3\xA4\xD1\x0F\x41\x62\x95\xD0\x80\x7A\xA6\x25\xCA' + b'\xB2\x74\x4F\xD9\xEA\x8F\xD2\x23\xC4\x25\x37\x02\x98\x28\xBD\x16' + b'\xBE\x02\x54\x6F\x13\x0F\xD2\xE3\x3B\x93\x6D\x26\x76\xE0\x8A\xED' + b'\x1B\x73\x31\x8B\x75\x0A\x01\x67\xD0\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xD6\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + ) + + # Encoding obtained in part from the KMIP 1.1 testing document, + # Sections 3.1.3 and 14.1. The rest of the encoding was built by + # hand. + # + # This encoding matches the following set of values: + # Request Payload + # Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038 + # Validity Indicator - Valid + + self.partial_encoding = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x00\x40' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66' + b'\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63' + b'\x33\x30\x33\x38\x00\x00\x00\x00' + b'\x42\x00\x9B\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + ) + + self.partial_encoding_missing_unique_id = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x00\x10' + b'\x42\x00\x9B\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + ) + + self.partial_encoding_missing_validity_ind = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x00\x30' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66' + b'\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63' + b'\x33\x30\x33\x38\x00\x00\x00\x00' + ) + + self.data = ( + b'\xCD\xC8\x7D\xA2\x23\xD7\x86\xDF\x3B\x45\xE0\xBB\xBC\x72\x13\x26' + b'\xD1\xEE\x2A\xF8\x06\xCC\x31\x54\x75\xCC\x6F\x0D\x9C\x66\xE1\xB6' + b'\x23\x71\xD4\x5C\xE2\x39\x2E\x1A\xC9\x28\x44\xC3\x10\x10\x2F\x15' + b'\x6A\x0D\x8D\x52\xC1\xF4\xC4\x0B\xA3\xAA\x65\x09\x57\x86\xCB\x76' + b'\x97\x57\xA6\x56\x3B\xA9\x58\xFE\xD0\xBC\xC9\x84\xE8\xB5\x17\xA3' + b'\xD5\xF5\x15\xB2\x3B\x8A\x41\xE7\x4A\xA8\x67\x69\x3F\x90\xDF\xB0' + b'\x61\xA6\xE8\x6D\xFA\xAE\xE6\x44\x72\xC0\x0E\x5F\x20\x94\x57\x29' + b'\xCB\xEB\xE7\x7F\x06\xCE\x78\xE0\x8F\x40\x98\xFB\xA4\x1F\x9D\x61' + b'\x93\xC0\x31\x7E\x8B\x60\xD4\xB6\x08\x4A\xCB\x42\xD2\x9E\x38\x08' + b'\xA3\xBC\x37\x2D\x85\xE3\x31\x17\x0F\xCB\xF7\xCC\x72\xD0\xB7\x1C' + b'\x29\x66\x48\xB3\xA4\xD1\x0F\x41\x62\x95\xD0\x80\x7A\xA6\x25\xCA' + b'\xB2\x74\x4F\xD9\xEA\x8F\xD2\x23\xC4\x25\x37\x02\x98\x28\xBD\x16' + b'\xBE\x02\x54\x6F\x13\x0F\xD2\xE3\x3B\x93\x6D\x26\x76\xE0\x8A\xED' + b'\x1B\x73\x31\x8B\x75\x0A\x01\x67\xD0' + ) + + def tearDown(self): + super(TestSignatureVerifyResponsePayload, self).tearDown() + + def test_init(self): + """ + Test that a SignatureVerify response payload can be constructed with no + arguments. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.validity_indicator) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.correlation_value) + + def test_init_with_args(self): + """ + Test that a SignatureVerify response payload can be constructed with + valid values + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='00000000-1111-2222-3333-444444444444', + validity_indicator=enums.ValidityIndicator.VALID, + data=b'\x01\x02\x03', + correlation_value=b'\xFF' + ) + + self.assertEqual( + '00000000-1111-2222-3333-444444444444', + payload.unique_identifier + ) + self.assertEqual( + enums.ValidityIndicator.VALID, + payload.validity_indicator + ) + self.assertEqual(b'\x01\x02\x03', payload.data) + self.assertEqual(b'\xFF', payload.correlation_value) + + def test_invalid_unique_identifier(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the unique identifier of a SignatureVerify response payload. + """ + kwargs = {'unique_identifier': 0} + self.assertRaisesRegexp( + TypeError, + "Unique identifier must be a string.", + signature_verify.SignatureVerifyResponsePayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyResponsePayload() + args = (payload, 'unique_identifier', 0) + self.assertRaisesRegexp( + TypeError, + "Unique identifier must be a string.", + setattr, + *args + ) + + def test_invalid_validity_indicator(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the validity indicator of a SignatureVerify response payload. + """ + kwargs = {'validity_indicator': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Validity indicator must be a ValidityIndicator enumeration.", + signature_verify.SignatureVerifyResponsePayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyResponsePayload() + args = (payload, 'validity_indicator', 'invalid') + self.assertRaisesRegexp( + TypeError, + "Validity indicator must be a ValidityIndicator enumeration.", + setattr, + *args + ) + + def test_invalid_data(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the data of a SignatureVerify request payload. + """ + kwargs = {'data': 0} + self.assertRaisesRegexp( + TypeError, + "Data must be bytes.", + signature_verify.SignatureVerifyResponsePayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyResponsePayload() + args = (payload, 'data', 0) + self.assertRaisesRegexp( + TypeError, + "Data must be bytes.", + setattr, + *args + ) + + def test_invalid_correlation_value(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the correlation value of a SignatureVerify request payload. + """ + kwargs = {'correlation_value': 0} + self.assertRaisesRegexp( + TypeError, + "Correlation value must be bytes.", + signature_verify.SignatureVerifyResponsePayload, + **kwargs + ) + + payload = signature_verify.SignatureVerifyResponsePayload() + args = (payload, 'correlation_value', 0) + self.assertRaisesRegexp( + TypeError, + "Correlation value must be bytes.", + setattr, + *args + ) + + def test_read(self): + """ + Test that a SignatureVerify response payload can be read from a data + stream. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.validity_indicator) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.correlation_value) + + payload.read(self.full_encoding) + + self.assertEqual( + '49a1ca88-6bea-4fb2-b450-7e58802c3038', + payload.unique_identifier + ) + self.assertEqual( + enums.ValidityIndicator.VALID, + payload.validity_indicator + ) + self.assertEqual(self.data, payload.data) + self.assertEqual(b'\x01', payload.correlation_value) + + def test_read_partial(self): + """ + Test that a SignatureVerify response payload can be read from a partial + data stream containing the minimum required attributes. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + + self.assertEqual(None, payload.unique_identifier) + self.assertEqual(None, payload.validity_indicator) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.correlation_value) + + payload.read(self.partial_encoding) + + self.assertEqual( + '49a1ca88-6bea-4fb2-b450-7e58802c3038', + payload.unique_identifier + ) + self.assertEqual( + enums.ValidityIndicator.VALID, + payload.validity_indicator + ) + self.assertEqual(None, payload.data) + self.assertEqual(None, payload.correlation_value) + + def test_read_missing_unique_identifier(self): + """ + Test that a ValueError gets raised when a required + SignatureVerifyResponsePayload field is missing when decoding the + struct. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + args = (self.partial_encoding_missing_unique_id, ) + self.assertRaisesRegexp( + ValueError, + "Parsed payload encoding is missing the unique identifier field.", + payload.read, + *args + ) + + def test_read_missing_validity_indicator(self): + """ + Test that a ValueError gets raised when a required + SignatureVerifyResponsePayload field is missing when decoding the + struct. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + args = (self.partial_encoding_missing_validity_ind, ) + self.assertRaisesRegexp( + ValueError, + "Parsed payload encoding is missing the validity indicator field.", + payload.read, + *args + ) + + def test_write(self): + """ + Test that a SignatureVerify response payload can be written to a data + stream. + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.VALID, + data=self.data, + correlation_value=b'\x01' + ) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(len(self.full_encoding), len(stream)) + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_write_partial(self): + """ + Test that a partially defined SignatureVerify response payload can be + written to a data stream. + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.VALID + ) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(len(self.partial_encoding), len(stream)) + self.assertEqual(str(self.partial_encoding), str(stream)) + + def test_write_missing_unique_identifier(self): + """ + Test that a ValueError gets raised when a required + SignatureVerifyResponsePayload field is missing when encoding the + struct. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + stream = utils.BytearrayStream() + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Payload is missing the unique identifier field.", + payload.write, + *args + ) + + def test_write_missing_validity_indicator(self): + """ + Test that a ValueError gets raised when a required + SignatureVerifyResponsePayload field is missing when encoding the + struct. + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038' + ) + stream = utils.BytearrayStream() + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Payload is missing the validity indicator field.", + payload.write, + *args + ) + + def test_equal_on_equal(self): + """ + Test that the equality operator returns True when comparing two + SignatureVerify response payloads with the same data. + """ + a = signature_verify.SignatureVerifyResponsePayload() + b = signature_verify.SignatureVerifyResponsePayload() + + self.assertTrue(a == b) + self.assertTrue(b == a) + + a = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.INVALID, + data=self.data, + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.INVALID, + data=self.data, + correlation_value=b'\x01' + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_equal_on_not_equal_unique_identifier(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify response payloads with different unique identifiers. + """ + a = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='a' + ) + b = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='b' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_validity_indicator(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify response payloads with different validity indicators. + """ + a = signature_verify.SignatureVerifyResponsePayload( + validity_indicator=enums.ValidityIndicator.VALID + ) + b = signature_verify.SignatureVerifyResponsePayload( + validity_indicator=enums.ValidityIndicator.INVALID + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_data(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify response payloads with different data. + """ + a = signature_verify.SignatureVerifyResponsePayload(data=b'\x11') + b = signature_verify.SignatureVerifyResponsePayload(data=b'\xFF') + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_correlation_value(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify response payloads with different correlation values. + """ + a = signature_verify.SignatureVerifyResponsePayload( + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyResponsePayload( + correlation_value=b'\x02' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_type_mismatch(self): + """ + Test that the equality operator returns False when comparing two + SignatureVerify response payloads with different types. + """ + a = signature_verify.SignatureVerifyResponsePayload() + b = 'invalid' + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_not_equal_on_equal(self): + """ + Test that the inequality operator returns False when comparing two + SignatureVerify response payloads with the same data. + """ + a = signature_verify.SignatureVerifyResponsePayload() + b = signature_verify.SignatureVerifyResponsePayload() + + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.INVALID, + data=self.data, + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.INVALID, + data=self.data, + correlation_value=b'\x01' + ) + + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_not_equal_on_not_equal_unique_identifier(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify response payloads with different unique identifiers. + """ + a = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='a' + ) + b = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='b' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_validity_indicator(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify response payloads with different validity indicators. + """ + a = signature_verify.SignatureVerifyResponsePayload( + validity_indicator=enums.ValidityIndicator.VALID + ) + b = signature_verify.SignatureVerifyResponsePayload( + validity_indicator=enums.ValidityIndicator.INVALID + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_data(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify response payloads with different data. + """ + a = signature_verify.SignatureVerifyResponsePayload(data=b'\x11') + b = signature_verify.SignatureVerifyResponsePayload(data=b'\xFF') + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_correlation_value(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify response payloads with different correlation values. + """ + a = signature_verify.SignatureVerifyResponsePayload( + correlation_value=b'\x01' + ) + b = signature_verify.SignatureVerifyResponsePayload( + correlation_value=b'\x02' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_type_mismatch(self): + """ + Test that the inequality operator returns True when comparing two + SignatureVerify response payloads with different types. + """ + a = signature_verify.SignatureVerifyResponsePayload() + b = 'invalid' + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test that repr can be applied to a SignatureVerify response payload. + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.VALID, + data=b'\x00\x11\x22\x33', + correlation_value=b'\x01' + ) + expected = ( + "SignatureVerifyResponsePayload(" + "unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', " + "validity_indicator=ValidityIndicator.VALID, " + "data=" + str(b'\x00\x11\x22\x33') + ", " + "correlation_value=" + str(b'\x01') + ")" + ) + observed = repr(payload) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to a SignatureVerify response payload + """ + payload = signature_verify.SignatureVerifyResponsePayload( + unique_identifier='49a1ca88-6bea-4fb2-b450-7e58802c3038', + validity_indicator=enums.ValidityIndicator.VALID, + data=b'\x00\x11\x22\x33', + correlation_value=b'\x01' + ) + + expected = str({ + 'unique_identifier': '49a1ca88-6bea-4fb2-b450-7e58802c3038', + 'validity_indicator': enums.ValidityIndicator.VALID, + 'data': b'\x00\x11\x22\x33', + 'correlation_value': b'\x01' + }) + observed = str(payload) + + self.assertEqual(expected, observed)