From 43ecea23a6c0cedf056442717ef3f5ccf3739bb2 Mon Sep 17 00:00:00 2001 From: Peter Hamilton <peter.hamilton@jhuapl.edu> Date: Fri, 13 Mar 2015 16:31:39 -0400 Subject: [PATCH] Updating the Register unit demo This change updates the Register unit demo, adding support for the registration of different types of secret objects. The changes required to support this include implementation updates to the KeyValue backing objects. --- kmip/core/factories/secrets.py | 10 +- kmip/core/objects.py | 147 ++++++++------- kmip/core/server.py | 8 +- kmip/demos/units/register.py | 86 ++------- kmip/demos/utils.py | 219 +++++++++++++++++++--- kmip/tests/core/messages/test_messages.py | 49 +++-- kmip/tests/core/test_server.py | 8 +- kmip/tests/services/test_kmip_client.py | 45 +++-- 8 files changed, 358 insertions(+), 214 deletions(-) diff --git a/kmip/core/factories/secrets.py b/kmip/core/factories/secrets.py index f09c891..0fda6ad 100644 --- a/kmip/core/factories/secrets.py +++ b/kmip/core/factories/secrets.py @@ -24,8 +24,8 @@ from kmip.core.misc import KeyFormatType from kmip.core.objects import Attribute from kmip.core.objects import KeyBlock +from kmip.core.objects import KeyMaterial from kmip.core.objects import KeyWrappingData -from kmip.core.objects import KeyValueStruct from kmip.core.objects import KeyValue from kmip.core.secrets import PrivateKey @@ -84,12 +84,8 @@ class SecretFactory(object): key_comp_type = KeyBlock.KeyCompressionType( key_compression_type) - key_material = self.key_factory.create_key(key_type, - key_value) - key_val_struc = KeyValueStruct(key_format_type=key_format_type, - key_material=key_material) - key_value = KeyValue(key_value=key_val_struc, - key_format_type=key_format_type) + key_material = KeyMaterial(key_value) + key_value = KeyValue(key_material) crypto_algorithm = CryptographicAlgorithm(cryptographic_algorithm) crypto_length = CryptographicLength(cryptographic_length) diff --git a/kmip/core/objects.py b/kmip/core/objects.py index 84746a8..f1b8964 100644 --- a/kmip/core/objects.py +++ b/kmip/core/objects.py @@ -19,7 +19,6 @@ from kmip.core import attributes from kmip.core.attributes import CryptographicParameters from kmip.core.factories.attribute_values import AttributeValueFactory -from kmip.core.factories.keys import KeyFactory from kmip.core import enums from kmip.core.enums import AttributeType @@ -373,13 +372,12 @@ class KeyBlock(Struct): self.key_format_type = KeyFormatType() self.key_format_type.read(tstream) - key_format_type = self.key_format_type.enum if self.is_tag_next(Tags.KEY_COMPRESSION_TYPE, tstream): self.key_compression_type = KeyBlock.KeyCompressionType() self.key_compression_type.read(tstream) - self.key_value = KeyValue(key_format_type=key_format_type) + self.key_value = KeyValue() self.key_value.read(tstream) if self.is_tag_next(Tags.CRYPTOGRAPHIC_ALGORITHM, tstream): @@ -434,35 +432,78 @@ class KeyBlock(Struct): # 2.1.4 -class KeyValueString(ByteString): +class KeyMaterial(ByteString): def __init__(self, value=None): - super(self.__class__, self).__init__(value, Tags.KEY_VALUE) + super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL) -class KeyValueStruct(Struct): +# TODO (peter-hamilton) Get rid of this and replace with a KeyMaterial factory. +class KeyMaterialStruct(Struct): + + def __init__(self): + super(KeyMaterialStruct, self).__init__(Tags.SERVER_INFORMATION) + + self.data = BytearrayStream() + + self.validate() + + def read(self, istream): + super(KeyMaterialStruct, self).read(istream) + tstream = BytearrayStream(istream.read(self.length)) + + self.data = BytearrayStream(tstream.read()) + + self.is_oversized(tstream) + self.validate() + + def write(self, ostream): + tstream = BytearrayStream() + tstream.write(self.data.buffer) + + self.length = tstream.length() + super(KeyMaterialStruct, self).write(ostream) + ostream.write(tstream.buffer) + + def validate(self): + self.__validate() + + def __validate(self): + # NOTE (peter-hamilton): Intentional pass, no way to validate data. + pass + + +class KeyValue(Struct): def __init__(self, - key_format_type=None, key_material=None, attributes=None): super(self.__class__, self).__init__(Tags.KEY_VALUE) - self.key_format_type = key_format_type - self.key_material = key_material - self.attributes = attributes - self.key_factory = KeyFactory() + + if key_material is None: + self.key_material = KeyMaterial() + else: + self.key_material = key_material + + if attributes is None: + self.attributes = list() + else: + self.attributes = attributes + self.validate() def read(self, istream): super(self.__class__, self).read(istream) tstream = BytearrayStream(istream.read(self.length)) - self.key_material = self.key_factory.create_key(self.key_format_type) - self.key_material.read(tstream) + # TODO (peter-hamilton) Replace this with a KeyMaterial factory. + if self.is_type_next(Types.STRUCTURE, tstream): + self.key_material = KeyMaterialStruct() + self.key_material.read(tstream) + else: + self.key_material = KeyMaterial() + self.key_material.read(tstream) - self.attributes = list() - - # Read the attributes, 0 or more while self.is_tag_next(Tags.ATTRIBUTE, tstream): attribute = Attribute() attribute.read(tstream) @@ -476,11 +517,9 @@ class KeyValueStruct(Struct): self.key_material.write(tstream) - if self.attributes is not None: - for attribute in self.attributes: - attribute.write(tstream) + for attribute in self.attributes: + attribute.write(tstream) - # Write the length and value of the credential self.length = tstream.length() super(self.__class__, self).write(ostream) ostream.write(tstream.buffer) @@ -489,56 +528,26 @@ class KeyValueStruct(Struct): self.__validate() def __validate(self): - # TODO (peter-hamilton) Finish implementation. - pass + # TODO (peter-hamilton) Replace with check against KeyMaterial factory. + if not isinstance(self.key_material, KeyMaterial): + msg = "invalid key material" + msg += "; expected {0}, received {1}".format( + KeyMaterial, self.key_material) + raise TypeError(msg) - -class KeyValue(Struct): - ''' - KeyValue can be either a ByteString or a Struct. Therefore, this class - acts as a wrapper for two different KeyValue objects, KeyValueString, - which represents the ByteString format, and KeyValueStruct, which - represents the Struct format, both of which are defined above. This - KeyValue object does not read or write itself; instead, it reads and - writes its internal key_value attribute, which is either a KeyValueString - or a KeyValueStruct. - - When reading, the class determines what the format of its internal - structure should be by looking at the type of the object it will read - using KeyValue.is_type_next(). This is one of the only places in the - code where this approach is used. - ''' - - def __init__(self, - key_value=None, - key_format_type=None): - super(self.__class__, self).__init__(Tags.KEY_VALUE) - self.key_value = key_value - self.key_format_type = key_format_type - if self.key_value is not None: - self.type = key_value.type - self.validate() - - def read(self, istream): - if self.is_type_next(Types.BYTE_STRING, istream): - self.key_value = KeyValueString() - self.key_value.read(istream) - elif self.is_type_next(Types.STRUCTURE, istream): - kft = self.key_format_type - self.key_value = KeyValueStruct(key_format_type=kft) - self.key_value.read(istream) - - def write(self, ostream): - tstream = BytearrayStream() - self.key_value.write(tstream) - ostream.write(tstream.buffer) - - def validate(self): - self.__validate() - - def __validate(self): - # TODO (peter-hamilton) Finish implementation. - pass + if isinstance(self.attributes, list): + for i in xrange(len(self.attributes)): + attribute = self.attributes[i] + if not isinstance(attribute, Attribute): + msg = "invalid attribute ({0} in list)".format(i) + msg += "; expected {0}, received {1}".format( + Attribute, attribute) + raise TypeError(msg) + else: + msg = "invalid attributes list" + msg += "; expected {0}, received {1}".format( + list, self.attributes) + raise TypeError(msg) # 2.1.5 diff --git a/kmip/core/server.py b/kmip/core/server.py index 33b66de..ff9aa00 100644 --- a/kmip/core/server.py +++ b/kmip/core/server.py @@ -29,7 +29,6 @@ from kmip.core.enums import ResultStatus as RS from kmip.core.factories.attributes import AttributeFactory from kmip.core.factories.keys import KeyFactory from kmip.core.factories.secrets import SecretFactory -from kmip.core.keys import RawKey from kmip.core.messages.contents import ResultStatus from kmip.core.messages.contents import ResultReason @@ -38,8 +37,8 @@ from kmip.core.messages.contents import ResultMessage from kmip.core.misc import KeyFormatType from kmip.core.objects import KeyBlock +from kmip.core.objects import KeyMaterial from kmip.core.objects import KeyValue -from kmip.core.objects import KeyValueStruct from kmip.core.objects import TemplateAttribute from kmip.core.repo.mem_repo import MemRepo from kmip.core.secrets import SymmetricKey @@ -346,8 +345,8 @@ class KMIPImpl(KMIP): def _gen_symmetric_key(self, bit_length, crypto_alg): key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW) - key_material = RawKey(bytearray(os.urandom(int(bit_length/8)))) - key_value = KeyValueStruct(key_format_type, key_material) + key_material = KeyMaterial(os.urandom(int(bit_length/8))) + key_value = KeyValue(key_material) crypto_length = CryptographicLength(bit_length) key_block = KeyBlock(key_format_type, None, key_value, crypto_alg, crypto_length, None) @@ -385,7 +384,6 @@ class KMIPImpl(KMIP): kv = key_block.key_value if isinstance(kv, KeyValue): kv = key_block.key_value - if isinstance(kv, KeyValueStruct): if kv.attributes is not None: self.logger.debug('adding the key value struct attributes') attributes.extend(kv.attributes) diff --git a/kmip/demos/units/register.py b/kmip/demos/units/register.py index c2b0919..7bc04e4 100644 --- a/kmip/demos/units/register.py +++ b/kmip/demos/units/register.py @@ -13,19 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from kmip.core.enums import AttributeType -from kmip.core.enums import CredentialType -from kmip.core.enums import CryptographicAlgorithm -from kmip.core.enums import CryptographicUsageMask from kmip.core.enums import KeyFormatType from kmip.core.enums import ObjectType from kmip.core.enums import Operation from kmip.core.enums import ResultStatus -from kmip.core.factories.attributes import AttributeFactory -from kmip.core.factories.credentials import CredentialFactory -from kmip.core.factories.secrets import SecretFactory - from kmip.core.objects import TemplateAttribute from kmip.demos import utils @@ -38,87 +30,45 @@ import sys if __name__ == '__main__': - # Build and parse arguments parser = utils.build_cli_parser(Operation.REGISTER) opts, args = parser.parse_args(sys.argv[1:]) username = opts.username password = opts.password config = opts.config - algorithm = opts.algorithm - length = opts.length + object_type = opts.type + format_type = opts.format # Exit early if the arguments are not specified - if algorithm is None: - logging.debug('No algorithm provided, exiting early from demo') - sys.exit() - if length is None: - logging.debug("No key length provided, exiting early from demo") + object_type = getattr(ObjectType, object_type, None) + if object_type is None: + logging.error("Invalid object type specified; exiting early from demo") sys.exit() + key_format_type = getattr(KeyFormatType, format_type, None) + if key_format_type is None: + logging.error( + "Invalid key format type specified; exiting early from demo") + # Build and setup logging and needed factories f_log = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'logconfig.ini') logging.config.fileConfig(f_log) logger = logging.getLogger(__name__) - attribute_factory = AttributeFactory() - credential_factory = CredentialFactory() - secret_factory = SecretFactory() - - # Build the KMIP server account credentials - # TODO (peter-hamilton) Move up into KMIPProxy - if (username is None) and (password is None): - credential = None - else: - credential_type = CredentialType.USERNAME_AND_PASSWORD - credential_value = {'Username': username, - 'Password': password} - credential = credential_factory.create_credential(credential_type, - credential_value) - # Build the client and connect to the server - client = KMIPProxy(config=config) - client.open() - - # Build the different object attributes - object_type = ObjectType.SYMMETRIC_KEY - - attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM - algorithm_enum = getattr(CryptographicAlgorithm, algorithm, None) - - if algorithm_enum is None: - logging.debug("{0} not found".format(algorithm)) - logging.debug("Invalid algorithm specified, exiting early from demo") - - client.close() - sys.exit() - - mask_flags = [CryptographicUsageMask.ENCRYPT, - CryptographicUsageMask.DECRYPT] - attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK - usage_mask = attribute_factory.create_attribute(attribute_type, - mask_flags) + # Create the template attribute for the secret and then build the secret + usage_mask = utils.build_cryptographic_usage_mask(logger, object_type) attributes = [usage_mask] template_attribute = TemplateAttribute(attributes=attributes) - secret_features = {} + secret = utils.build_object(logger, object_type, key_format_type) - key_format_type = KeyFormatType.RAW - secret_features.update([('key_format_type', key_format_type)]) + # Build the client, connect to the server, register the secret, and + # disconnect from the server + client = KMIPProxy(config=config) - # TODO (peter-hamilton) Replace with calls to crypto libraries - key_data = {'bytes': bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x00\x00')} - - secret_features.update([('key_value', key_data)]) - secret_features.update([('cryptographic_algorithm', algorithm_enum)]) - secret_features.update([('cryptographic_length', length)]) - - secret = secret_factory.create(object_type, secret_features) - - # Register the SYMMETRIC_KEY object - result = client.register(object_type, template_attribute, secret, - credential) + client.open() + result = client.register(object_type, template_attribute, secret) client.close() # Display operation results diff --git a/kmip/demos/utils.py b/kmip/demos/utils.py index a8b18c8..6d5a724 100644 --- a/kmip/demos/utils.py +++ b/kmip/demos/utils.py @@ -13,10 +13,29 @@ # License for the specific language governing permissions and limitations # under the License. +from kmip.core.attributes import CryptographicAlgorithm +from kmip.core.attributes import CryptographicLength + +from kmip.core.enums import AttributeType +from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum +from kmip.core.enums import CryptographicUsageMask from kmip.core.enums import ObjectType from kmip.core.enums import Operation +from kmip.core.factories.attributes import AttributeFactory + +from kmip.core.misc import KeyFormatType + +from kmip.core.objects import KeyBlock +from kmip.core.objects import KeyMaterial +from kmip.core.objects import KeyValue + +from kmip.core.secrets import PrivateKey +from kmip.core.secrets import PublicKey +from kmip.core.secrets import SymmetricKey + import optparse +import sys def build_cli_parser(operation): @@ -130,21 +149,23 @@ def build_cli_parser(operation): help="Name of secret to retrieve from the KMIP server") elif operation is Operation.REGISTER: parser.add_option( - "-a", - "--algorithm", + "-f", + "--format", action="store", type="str", - default=None, - dest="algorithm", - help="Encryption algorithm for the secret (e.g., AES)") + default="RAW", + dest="format", + help=("Format in which to store the secret. Supported formats " + "include: RAW, PKCS_1, PKCS_8, X_509")) parser.add_option( - "-l", - "--length", + "-t", + "--type", action="store", - type="int", - default=None, - dest="length", - help="Key length in bits (e.g., 128, 256)") + type="str", + default="SYMMETRIC_KEY", + dest="type", + help=("Type of the object to register. Supported types include: " + "PRIVATE_KEY, PUBLIC_KEY, SYMMETRIC_KEY")) elif operation is Operation.QUERY: pass elif operation is Operation.DISCOVER_VERSIONS: @@ -155,6 +176,162 @@ def build_cli_parser(operation): return parser +def build_cryptographic_usage_mask(logger, object_type): + if object_type == ObjectType.SYMMETRIC_KEY: + flags = [CryptographicUsageMask.ENCRYPT, + CryptographicUsageMask.DECRYPT] + elif object_type == ObjectType.PUBLIC_KEY: + flags = [CryptographicUsageMask.VERIFY] + elif object_type == ObjectType.PRIVATE_KEY: + flags = [CryptographicUsageMask.SIGN] + else: + logger.error("Unrecognized object type, could not build cryptographic " + "usage mask") + sys.exit() + + attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK + attribute_factory = AttributeFactory() + usage_mask = attribute_factory.create_attribute(attribute_type, flags) + + return usage_mask + + +def build_object(logger, object_type, key_format_type): + + key_value = build_key_value(logger, object_type) + cryptographic_algorithm = build_cryptographic_algorithm( + logger, object_type) + cryptographic_length = build_cryptographic_length(logger, object_type) + + key_block = build_key_block( + key_format_type, + key_value, + cryptographic_algorithm, + cryptographic_length) + + if object_type == ObjectType.SYMMETRIC_KEY: + return SymmetricKey(key_block) + elif object_type == ObjectType.PUBLIC_KEY: + return PublicKey(key_block) + elif object_type == ObjectType.PRIVATE_KEY: + return PrivateKey(key_block) + else: + logger.error("Unrecognized object type, could not build object") + sys.exit() + + +def build_cryptographic_length(logger, object_type): + if object_type == ObjectType.SYMMETRIC_KEY: + return CryptographicLength(128) + elif object_type == ObjectType.PUBLIC_KEY: + return CryptographicLength(1024) + elif object_type == ObjectType.PRIVATE_KEY: + return CryptographicLength(1024) + else: + logger.error("Unrecognized object type, could not build cryptographic " + "length") + sys.exit() + + +def build_cryptographic_algorithm(logger, object_type): + if object_type == ObjectType.SYMMETRIC_KEY: + return CryptographicAlgorithm(CryptoAlgorithmEnum.AES) + elif object_type == ObjectType.PUBLIC_KEY: + return CryptographicAlgorithm(CryptoAlgorithmEnum.RSA) + elif object_type == ObjectType.PRIVATE_KEY: + return CryptographicAlgorithm(CryptoAlgorithmEnum.RSA) + else: + logger.error("Unrecognized object type, could not build cryptographic " + "algorithm") + sys.exit() + + +def build_key_value(logger, object_type): + if object_type == ObjectType.SYMMETRIC_KEY: + return ( + b'\x30\x82\x02\x76\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7' + b'\x0D\x01\x01\x01\x05\x00\x04\x82\x02\x60\x30\x82\x02\x5C\x02\x01' + b'\x00\x02\x81\x81\x00\x93\x04\x51\xC9\xEC\xD9\x4F\x5B\xB9\xDA\x17' + b'\xDD\x09\x38\x1B\xD2\x3B\xE4\x3E\xCA\x8C\x75\x39\xF3\x01\xFC\x8A' + b'\x8C\xD5\xD5\x27\x4C\x3E\x76\x99\xDB\xDC\x71\x1C\x97\xA7\xAA\x91' + b'\xE2\xC5\x0A\x82\xBD\x0B\x10\x34\xF0\xDF\x49\x3D\xEC\x16\x36\x24' + b'\x27\xE5\x8A\xCC\xE7\xF6\xCE\x0F\x9B\xCC\x61\x7B\xBD\x8C\x90\xD0' + b'\x09\x4A\x27\x03\xBA\x0D\x09\xEB\x19\xD1\x00\x5F\x2F\xB2\x65' + b'\x52') + elif object_type == ObjectType.PUBLIC_KEY: + return ( + b'\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01' + b'\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\x93\x04\x51' + b'\xC9\xEC\xD9\x4F\x5B\xB9\xDA\x17\xDD\x09\x38\x1B\xD2\x3B\xE4\x3E' + b'\xCA\x8C\x75\x39\xF3\x01\xFC\x8A\x8C\xD5\xD5\x27\x4C\x3E\x76\x99' + b'\xDB\xDC\x71\x1C\x97\xA7\xAA\x91\xE2\xC5\x0A\x82\xBD\x0B\x10\x34' + b'\xF0\xDF\x49\x3D\xEC\x16\x36\x24\x27\xE5\x8A\xCC\xE7\xF6\xCE\x0F' + b'\x9B\xCC\x61\x7B\xBD\x8C\x90\xD0\x09\x4A\x27\x03\xBA\x0D\x09\xEB' + b'\x19\xD1\x00\x5F\x2F\xB2\x65\x52\x6A\xAC\x75\xAF\x32\xF8\xBC\x78' + b'\x2C\xDE\xD2\xA5\x7F\x81\x1E\x03\xEA\xF6\x7A\x94\x4D\xE5\xE7\x84' + b'\x13\xDC\xA8\xF2\x32\xD0\x74\xE6\xDC\xEA\x4C\xEC\x9F\x02\x03\x01' + b'\x00\x01') + elif object_type == ObjectType.PRIVATE_KEY: + return ( + b'\x30\x82\x02\x76\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7' + b'\x0D\x01\x01\x01\x05\x00\x04\x82\x02\x60\x30\x82\x02\x5C\x02\x01' + b'\x00\x02\x81\x81\x00\x93\x04\x51\xC9\xEC\xD9\x4F\x5B\xB9\xDA\x17' + b'\xDD\x09\x38\x1B\xD2\x3B\xE4\x3E\xCA\x8C\x75\x39\xF3\x01\xFC\x8A' + b'\x8C\xD5\xD5\x27\x4C\x3E\x76\x99\xDB\xDC\x71\x1C\x97\xA7\xAA\x91' + b'\xE2\xC5\x0A\x82\xBD\x0B\x10\x34\xF0\xDF\x49\x3D\xEC\x16\x36\x24' + b'\x27\xE5\x8A\xCC\xE7\xF6\xCE\x0F\x9B\xCC\x61\x7B\xBD\x8C\x90\xD0' + b'\x09\x4A\x27\x03\xBA\x0D\x09\xEB\x19\xD1\x00\x5F\x2F\xB2\x65\x52' + b'\x6A\xAC\x75\xAF\x32\xF8\xBC\x78\x2C\xDE\xD2\xA5\x7F\x81\x1E\x03' + b'\xEA\xF6\x7A\x94\x4D\xE5\xE7\x84\x13\xDC\xA8\xF2\x32\xD0\x74\xE6' + b'\xDC\xEA\x4C\xEC\x9F\x02\x03\x01\x00\x01\x02\x81\x80\x0B\x6A\x7D' + b'\x73\x61\x99\xEA\x48\xA4\x20\xE4\x53\x7C\xA0\xC7\xC0\x46\x78\x4D' + b'\xCB\xEA\xA6\x3B\xAE\xBC\x0B\xC1\x32\x78\x74\x49\xCD\xE8\xD7\xCA' + b'\xD0\xC0\xC8\x63\xC0\xFE\xFB\x06\xC3\x06\x2B\xEF\xC5\x00\x33\xEC' + b'\xF8\x7B\x4E\x33\xA9\xBE\x7B\xCB\xC8\xF1\x51\x1A\xE2\x15\xE8\x0D' + b'\xEB\x5D\x8A\xF2\xBD\x31\x31\x9D\x78\x21\x19\x66\x40\x93\x5A\x0C' + b'\xD6\x7C\x94\x59\x95\x79\xF2\x10\x0D\x65\xE0\x38\x83\x1F\xDA\xFB' + b'\x0D\xBE\x2B\xBD\xAC\x00\xA6\x96\xE6\x7E\x75\x63\x50\xE1\xC9\x9A' + b'\xCE\x11\xA3\x6D\xAB\xAC\x3E\xD3\xE7\x30\x96\x00\x59\x02\x41\x00' + b'\xDD\xF6\x72\xFB\xCC\x5B\xDA\x3D\x73\xAF\xFC\x4E\x79\x1E\x0C\x03' + b'\x39\x02\x24\x40\x5D\x69\xCC\xAA\xBC\x74\x9F\xAA\x0D\xCD\x4C\x25' + b'\x83\xC7\x1D\xDE\x89\x41\xA7\xB9\xAA\x03\x0F\x52\xEF\x14\x51\x46' + b'\x6C\x07\x4D\x4D\x33\x8F\xE6\x77\x89\x2A\xCD\x9E\x10\xFD\x35\xBD' + b'\x02\x41\x00\xA9\x8F\xBC\x3E\xD6\xB4\xC6\xF8\x60\xF9\x71\x65\xAC' + b'\x2F\x7B\xB6\xF2\xE2\xCB\x19\x2A\x9A\xBD\x49\x79\x5B\xE5\xBC\xF3' + b'\x7D\x8E\xE6\x9A\x6E\x16\x9C\x24\xE5\xC3\x2E\x4E\x7F\xA3\x32\x65' + b'\x46\x14\x07\xF9\x52\xBA\x49\xE2\x04\x81\x8A\x2F\x78\x5F\x11\x3F' + b'\x92\x2B\x8B\x02\x40\x25\x3F\x94\x70\x39\x0D\x39\x04\x93\x03\x77' + b'\x7D\xDB\xC9\x75\x0E\x9D\x64\x84\x9C\xE0\x90\x3E\xAE\x70\x4D\xC9' + b'\xF5\x89\xB7\x68\x0D\xEB\x9D\x60\x9F\xD5\xBC\xD4\xDE\xCD\x6F\x12' + b'\x05\x42\xE5\xCF\xF5\xD7\x6F\x2A\x43\xC8\x61\x5F\xB5\xB3\xA9\x21' + b'\x34\x63\x79\x7A\xA9\x02\x41\x00\xA1\xDD\xF0\x23\xC0\xCD\x94\xC0' + b'\x19\xBB\x26\xD0\x9B\x9E\x3C\xA8\xFA\x97\x1C\xB1\x6A\xA5\x8B\x9B' + b'\xAF\x79\xD6\x08\x1A\x1D\xBB\xA4\x52\xBA\x53\x65\x3E\x28\x04\xBA' + b'\x98\xFF\x69\xE8\xBB\x1B\x3A\x16\x1E\xA2\x25\xEA\x50\x14\x63\x21' + b'\x6A\x8D\xAB\x9B\x88\xA7\x5E\x5F\x02\x40\x61\x78\x64\x6E\x11\x2C' + b'\xF7\x9D\x92\x1A\x8A\x84\x3F\x17\xF6\xE7\xFF\x97\x4F\x68\x81\x22' + b'\x36\x5B\xF6\x69\x0C\xDF\xC9\x96\xE1\x89\x09\x52\xEB\x38\x20\xDD' + b'\x18\x90\xEC\x1C\x86\x19\xE8\x7A\x2B\xD3\x8F\x9D\x03\xB3\x7F\xAC' + b'\x74\x2E\xFB\x74\x8C\x78\x85\x94\x2C\x39') + else: + logger.error("Unrecognized object type, could not build key value") + sys.exit() + + +def build_key_block(key_format_type, key_value, cryptographic_algorithm, + cryptographic_length): + key_material = KeyMaterial(key_value) + key_value = KeyValue(key_material) + + return KeyBlock( + key_format_type=KeyFormatType(key_format_type), + key_compression_type=None, + key_value=key_value, + cryptographic_algorithm=cryptographic_algorithm, + cryptographic_length=cryptographic_length, + key_wrapping_data=None) + + def log_template_attribute(logger, template_attribute): names = template_attribute.names attributes = template_attribute.attributes @@ -164,7 +341,7 @@ def log_template_attribute(logger, template_attribute): name = names[i] logger.info('name {0}: {1}'.format(i, name)) - log_attribute_list(attributes) + log_attribute_list(logger, attributes) def log_attribute_list(logger, attributes): @@ -230,22 +407,14 @@ def log_key_block(logger, key_block): def log_key_value(logger, key_value): if key_value is not None: - key_format_type = key_value.key_format_type - key_value = key_value.key_value + logger.info('key value:') - logger.info('key format type: {0}'.format(key_format_type)) + key_material = key_value.key_material + attributes = key_value.attributes - if key_value is not None: - logger.info('key value:') + logger.info('key material: {0}'.format(repr(key_material))) - key_material = key_value.key_material - attributes = key_value.attributes - - logger.info('key material: {0}'.format(repr(key_material))) - - log_attribute_list(logger, attributes) - else: - logger.info('key value: {0}'.format(key_value)) + log_attribute_list(logger, attributes) else: logger.info('key value: {0}'.format(key_value)) diff --git a/kmip/tests/core/messages/test_messages.py b/kmip/tests/core/messages/test_messages.py index f4e40e3..5145557 100644 --- a/kmip/tests/core/messages/test_messages.py +++ b/kmip/tests/core/messages/test_messages.py @@ -24,23 +24,22 @@ from kmip.core.attributes import ApplicationData from kmip.core.attributes import ApplicationNamespace from kmip.core.attributes import ApplicationSpecificInformation from kmip.core.attributes import ContactInformation +from kmip.core.attributes import CryptographicAlgorithm +from kmip.core.attributes import CryptographicLength from kmip.core.attributes import Name from kmip.core.attributes import ObjectGroup from kmip.core import enums from kmip.core.enums import AttributeType -from kmip.core.enums import CryptographicAlgorithm +from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum from kmip.core.enums import CryptographicUsageMask from kmip.core.enums import NameType -from kmip.core.enums import ObjectType from kmip.core import errors from kmip.core.errors import ErrorStrings from kmip.core import objects -from kmip.core.keys import RawKey - from kmip.core.messages import contents from kmip.core.messages import messages from kmip.core.messages.payloads import create @@ -357,7 +356,7 @@ class TestRequestMessage(TestCase): object_type = attr.ObjectType(enums.ObjectType.SYMMETRIC_KEY) name = AttributeType.CRYPTOGRAPHIC_ALGORITHM - value = CryptographicAlgorithm.AES + value = CryptoAlgorithmEnum.AES attr_a = self.attribute_factory.create_attribute(name, value) name = AttributeType.CRYPTOGRAPHIC_LENGTH @@ -1341,13 +1340,13 @@ class TestResponseMessage(TestCase): objects.KeyValue, type(key_value))) - key_material = key_value.key_value.key_material - value = bytearray(b'\x73\x67\x57\x80\x51\x01\x2A\x6D\x13\x4A\x85' - b'\x5E\x25\xC8\xCD\x5E\x4C\xA1\x31\x45\x57\x29' - b'\xD3\xC8') - self.assertIsInstance(key_material, RawKey, + key_material = key_value.key_material + value = ( + b'\x73\x67\x57\x80\x51\x01\x2A\x6D\x13\x4A\x85\x5E\x25\xC8\xCD' + b'\x5E\x4C\xA1\x31\x45\x57\x29\xD3\xC8') + self.assertIsInstance(key_material, objects.KeyMaterial, self.msg.format('key_material', 'type', - RawKey, + objects.KeyMaterial, type(key_material))) exp = utils.hexlify_bytearray(value) obs = utils.hexlify_bytearray(key_material.value) @@ -1395,17 +1394,29 @@ class TestResponseMessage(TestCase): uuid = '49a1ca88-6bea-4fb2-b450-7e58802c3038' uniq_id = attr.UniqueIdentifier(uuid) - key_type = enums.KeyFormatType.RAW - key = bytearray(b'\x73\x67\x57\x80\x51\x01\x2A\x6D\x13\x4A\x85\x5E\x25' - b'\xC8\xCD\x5E\x4C\xA1\x31\x45\x57\x29\xD3\xC8') + key = ( + b'\x73\x67\x57\x80\x51\x01\x2A\x6D\x13\x4A\x85\x5E\x25\xC8\xCD\x5E' + b'\x4C\xA1\x31\x45\x57\x29\xD3\xC8') crypto_algorithm = enums.CryptographicAlgorithm.TRIPLE_DES cryptographic_length = 168 - value = {'key_format_type': key_type, - 'key_value': {'bytes': key}, - 'cryptographic_algorithm': crypto_algorithm, - 'cryptographic_length': cryptographic_length} - secret = self.secret_factory.create(ObjectType.SYMMETRIC_KEY, value) + key_format_type = KeyFormatType(enums.KeyFormatType.RAW) + + key_material = objects.KeyMaterial(key) + key_value = objects.KeyValue(key_material) + cryptographic_algorithm = CryptographicAlgorithm(crypto_algorithm) + cryptographic_length = CryptographicLength(cryptographic_length) + + key_block = objects.KeyBlock( + key_format_type=key_format_type, + key_compression_type=None, + key_value=key_value, + cryptographic_algorithm=cryptographic_algorithm, + cryptographic_length=cryptographic_length, + key_wrapping_data=None) + + secret = SymmetricKey(key_block) + resp_pl = get.GetResponsePayload(object_type=object_type, unique_identifier=uniq_id, secret=secret) diff --git a/kmip/tests/core/test_server.py b/kmip/tests/core/test_server.py index 17d7e70..65c7d23 100644 --- a/kmip/tests/core/test_server.py +++ b/kmip/tests/core/test_server.py @@ -33,13 +33,13 @@ from kmip.core.enums import ResultStatus from kmip.core.enums import NameType from kmip.core.factories.attributes import AttributeFactory -from kmip.core.keys import RawKey from kmip.core.messages.contents import KeyCompressionType from kmip.core.misc import KeyFormatType from kmip.core.objects import KeyBlock -from kmip.core.objects import KeyValueStruct +from kmip.core.objects import KeyMaterial +from kmip.core.objects import KeyValue from kmip.core.objects import TemplateAttribute from kmip.core.secrets import SymmetricKey @@ -472,8 +472,8 @@ class TestKMIPServer(TestCase): # only need usage attribute attrs = [self._get_attrs()[1]] key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW) - key_material = RawKey(self.key) - key_value = KeyValueStruct(key_format_type, key_material, attrs) + key_material = KeyMaterial(self.key) + key_value = KeyValue(key_material, attrs) crypto_alg = CryptographicAlgorithm(self.algorithm_name) crypto_length = CryptographicLength(self.key_length) usage = CryptographicUsageMask(self.usage_mask) diff --git a/kmip/tests/services/test_kmip_client.py b/kmip/tests/services/test_kmip_client.py index 33f3758..8592859 100644 --- a/kmip/tests/services/test_kmip_client.py +++ b/kmip/tests/services/test_kmip_client.py @@ -21,15 +21,17 @@ import os import sys import time +from kmip.core.attributes import CryptographicAlgorithm +from kmip.core.attributes import CryptographicLength from kmip.core.attributes import PrivateKeyUniqueIdentifier from kmip.core.enums import AttributeType from kmip.core.enums import CredentialType -from kmip.core.enums import CryptographicAlgorithm +from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum from kmip.core.enums import CryptographicUsageMask from kmip.core.enums import ObjectType from kmip.core.enums import Operation as OperationEnum -from kmip.core.enums import KeyFormatType +from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum from kmip.core.enums import QueryFunction as QueryFunctionEnum from kmip.core.enums import ResultStatus from kmip.core.enums import ResultReason @@ -44,10 +46,8 @@ from kmip.core.factories.secrets import SecretFactory from kmip.core.messages.messages import RequestBatchItem from kmip.core.messages.messages import ResponseBatchItem from kmip.core.messages.messages import ResponseMessage - from kmip.core.messages.contents import Operation from kmip.core.messages.contents import ProtocolVersion - from kmip.core.messages.payloads.create_key_pair import \ CreateKeyPairRequestPayload, CreateKeyPairResponsePayload from kmip.core.messages.payloads.discover_versions import \ @@ -57,6 +57,7 @@ from kmip.core.messages.payloads.query import \ from kmip.core.messages.payloads.rekey_key_pair import \ RekeyKeyPairRequestPayload, RekeyKeyPairResponsePayload +from kmip.core.misc import KeyFormatType from kmip.core.misc import Offset from kmip.core.misc import QueryFunction from kmip.core.misc import ServerInformation @@ -64,6 +65,9 @@ from kmip.core.misc import VendorIdentification from kmip.core.objects import Attribute from kmip.core.objects import CommonTemplateAttribute +from kmip.core.objects import KeyBlock +from kmip.core.objects import KeyMaterial +from kmip.core.objects import KeyValue from kmip.core.objects import PrivateKeyTemplateAttribute from kmip.core.objects import PublicKeyTemplateAttribute from kmip.core.objects import TemplateAttribute @@ -218,7 +222,7 @@ class TestKMIPClientIntegration(TestCase): credential_value) object_type = ObjectType.SYMMETRIC_KEY - algorithm_value = CryptographicAlgorithm.AES + algorithm_value = CryptoAlgorithmEnum.AES mask_flags = [CryptographicUsageMask.ENCRYPT, CryptographicUsageMask.DECRYPT] attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK @@ -227,19 +231,26 @@ class TestKMIPClientIntegration(TestCase): attributes = [usage_mask] template_attribute = TemplateAttribute(attributes=attributes) - secret_features = {} + key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW) - key_format_type = KeyFormatType.RAW - secret_features.update([('key_format_type', key_format_type)]) + key_data = ( + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00') - key_data = {'bytes': bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x00\x00')} + key_material = KeyMaterial(key_data) + key_value = KeyValue(key_material) + cryptographic_algorithm = CryptographicAlgorithm(algorithm_value) + cryptographic_length = CryptographicLength(128) - secret_features.update([('key_value', key_data)]) - secret_features.update([('cryptographic_algorithm', algorithm_value)]) - secret_features.update([('cryptographic_length', 128)]) + key_block = KeyBlock( + key_format_type=key_format_type, + key_compression_type=None, + key_value=key_value, + cryptographic_algorithm=cryptographic_algorithm, + cryptographic_length=cryptographic_length, + key_wrapping_data=None) - secret = self.secret_factory.create(object_type, secret_features) + secret = SymmetricKey(key_block) result = self.client.register(object_type, template_attribute, secret, credential) @@ -273,9 +284,9 @@ class TestKMIPClientIntegration(TestCase): key_block = result.secret.key_block key_value = key_block.key_value - key_material = key_value.key_value.key_material + key_material = key_value.key_material - expected = key_data.get('bytes') + expected = key_data observed = key_material.value message = utils.build_er_error(key_material.__class__, 'value', expected, observed, 'value') @@ -303,7 +314,7 @@ class TestKMIPClientIntegration(TestCase): attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM algorithm = self.attr_factory.create_attribute( attribute_type, - CryptographicAlgorithm.AES) + CryptoAlgorithmEnum.AES) mask_flags = [CryptographicUsageMask.ENCRYPT, CryptographicUsageMask.DECRYPT]