Merge pull request from OpenKMIP/feat/add-key-wrapping-data-model

Update the object data model to support storing key wrapping data
This commit is contained in:
Peter Hamilton 2017-10-02 01:19:23 -04:00 committed by GitHub
commit 6df0315d41
8 changed files with 736 additions and 30 deletions

@ -85,9 +85,17 @@ class ObjectFactory:
length = key.key_block.cryptographic_length.value
value = key.key_block.key_value.key_material.value
format_type = key.key_block.key_format_type.value
key_wrapping_data = key.key_block.key_wrapping_data
if cls is pobjects.SymmetricKey:
key = cls(algorithm, length, value)
key = cls(
algorithm,
length,
value,
key_wrapping_data=self._build_key_wrapping_data(
key_wrapping_data
)
)
if key.key_format_type != format_type:
raise TypeError(
"core key format type not compatible with Pie "
@ -96,7 +104,15 @@ class ObjectFactory:
else:
return key
else:
return cls(algorithm, length, value, format_type)
return cls(
algorithm,
length,
value,
format_type,
key_wrapping_data=self._build_key_wrapping_data(
key_wrapping_data
)
)
def _build_pie_secret_data(self, secret):
secret_data_type = secret.secret_data_type.value
@ -117,6 +133,11 @@ class ObjectFactory:
key_material = cobjects.KeyMaterial(value)
key_value = cobjects.KeyValue(key_material)
key_wrapping_data = None
if key.key_wrapping_data:
key_wrapping_data = cobjects.KeyWrappingData(
**key.key_wrapping_data
)
key_block = cobjects.KeyBlock(
key_format_type=misc.KeyFormatType(format_type),
key_compression_type=None,
@ -124,7 +145,8 @@ class ObjectFactory:
cryptographic_algorithm=attributes.CryptographicAlgorithm(
algorithm),
cryptographic_length=attributes.CryptographicLength(length),
key_wrapping_data=None)
key_wrapping_data=key_wrapping_data
)
return cls(key_block)
@ -155,3 +177,54 @@ class ObjectFactory:
opaque_data_type = secrets.OpaqueObject.OpaqueDataType(opaque_type)
opaque_data_value = secrets.OpaqueObject.OpaqueDataValue(value)
return secrets.OpaqueObject(opaque_data_type, opaque_data_value)
def _build_cryptographic_parameters(self, value):
cryptographic_parameters = {
'block_cipher_mode': value.block_cipher_mode,
'padding_method': value.padding_method,
'hashing_algorithm': value.hashing_algorithm,
'key_role_type': value.key_role_type,
'digital_signature_algorithm': value.digital_signature_algorithm,
'cryptographic_algorithm': value.cryptographic_algorithm,
'random_iv': value.random_iv,
'iv_length': value.iv_length,
'tag_length': value.tag_length,
'fixed_field_length': value.fixed_field_length,
'invocation_field_length': value.invocation_field_length,
'counter_length': value.counter_length,
'initial_counter_value': value.initial_counter_value
}
return cryptographic_parameters
def _build_key_wrapping_data(self, value):
if value is None:
return None
encryption_key_info = value.encryption_key_information
encryption_key_information = {}
if encryption_key_info:
encryption_key_information = {
'unique_identifier': encryption_key_info.unique_identifier,
'cryptographic_parameters':
self._build_cryptographic_parameters(
encryption_key_info.cryptographic_parameters
)
}
mac_signature_key_info = value.mac_signature_key_information
mac_signature_key_information = {}
if mac_signature_key_info:
mac_signature_key_information = {
'unique_identifier': mac_signature_key_info.unique_identifier,
'cryptographic_parameters':
self._build_cryptographic_parameters(
mac_signature_key_info.cryptographic_parameters
)
}
key_wrapping_data = {
'wrapping_method': value.wrapping_method,
'encryption_key_information': encryption_key_information,
'mac_signature_key_information': mac_signature_key_information,
'mac_signature': value.mac_signature,
'iv_counter_nonce': value.iv_counter_nonce,
'encoding_option': value.encoding_option
}
return key_wrapping_data

@ -15,6 +15,7 @@
from abc import abstractmethod
from sqlalchemy import Column, event, ForeignKey, Integer, String, VARBINARY
from sqlalchemy import Boolean
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import relationship
@ -212,6 +213,8 @@ class Key(CryptographicObject):
cryptographic_length: An int defining the length of the key in bits.
key_format_type: A KeyFormatType enumeration defining the format of
the key value.
key_wrapping_data: A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
"""
__tablename__ = 'keys'
@ -224,6 +227,167 @@ class Key(CryptographicObject):
key_format_type = Column(
'key_format_type', sql.EnumType(enums.KeyFormatType))
# Key wrapping data fields
_kdw_wrapping_method = Column(
'_kdw_wrapping_method',
sql.EnumType(enums.WrappingMethod),
default=None
)
_kdw_eki_unique_identifier = Column(
'_kdw_eki_unique_identifier',
String,
default=None
)
_kdw_eki_cp_block_cipher_mode = Column(
'_kdw_eki_cp_block_cipher_mode',
sql.EnumType(enums.BlockCipherMode),
default=None
)
_kdw_eki_cp_padding_method = Column(
'_kdw_eki_cp_padding_method',
sql.EnumType(enums.PaddingMethod),
default=None
)
_kdw_eki_cp_hashing_algorithm = Column(
'_kdw_eki_cp_hashing_algorithm',
sql.EnumType(enums.HashingAlgorithm),
default=None
)
_kdw_eki_cp_key_role_type = Column(
'_kdw_eki_cp_key_role_type',
sql.EnumType(enums.KeyRoleType),
default=None
)
_kdw_eki_cp_digital_signature_algorithm = Column(
'_kdw_eki_cp_digital_signature_algorithm',
sql.EnumType(enums.DigitalSignatureAlgorithm),
default=None
)
_kdw_eki_cp_cryptographic_algorithm = Column(
'_kdw_eki_cp_cryptographic_algorithm',
sql.EnumType(enums.CryptographicAlgorithm),
default=None
)
_kdw_eki_cp_random_iv = Column(
'_kdw_eki_cp_random_iv',
Boolean,
default=None
)
_kdw_eki_cp_iv_length = Column(
'_kdw_eki_cp_iv_length',
Integer,
default=None
)
_kdw_eki_cp_tag_length = Column(
'_kdw_eki_cp_tag_length',
Integer,
default=None
)
_kdw_eki_cp_fixed_field_length = Column(
'_kdw_eki_cp_fixed_field_length',
Integer,
default=None
)
_kdw_eki_cp_invocation_field_length = Column(
'_kdw_eki_cp_invocation_field_length',
Integer
)
_kdw_eki_cp_counter_length = Column(
'_kdw_eki_cp_counter_length',
Integer,
default=None
)
_kdw_eki_cp_initial_counter_value = Column(
'_kdw_eki_cp_initial_counter_value',
Integer,
default=None
)
_kdw_mski_unique_identifier = Column(
'_kdw_mski_unique_identifier',
String,
default=None
)
_kdw_mski_cp_block_cipher_mode = Column(
'_kdw_mski_cp_block_cipher_mode',
sql.EnumType(enums.BlockCipherMode),
default=None
)
_kdw_mski_cp_padding_method = Column(
'_kdw_mski_cp_padding_method',
sql.EnumType(enums.PaddingMethod),
default=None
)
_kdw_mski_cp_hashing_algorithm = Column(
'_kdw_mski_cp_hashing_algorithm',
sql.EnumType(enums.HashingAlgorithm),
default=None
)
_kdw_mski_cp_key_role_type = Column(
'_kdw_mski_cp_key_role_type',
sql.EnumType(enums.KeyRoleType),
default=None
)
_kdw_mski_cp_digital_signature_algorithm = Column(
'_kdw_mski_cp_digital_signature_algorithm',
sql.EnumType(enums.DigitalSignatureAlgorithm),
default=None
)
_kdw_mski_cp_cryptographic_algorithm = Column(
'_kdw_mski_cp_cryptographic_algorithm',
sql.EnumType(enums.CryptographicAlgorithm),
default=None
)
_kdw_mski_cp_random_iv = Column(
'_kdw_mski_cp_random_iv',
Boolean,
default=None
)
_kdw_mski_cp_iv_length = Column(
'_kdw_mski_cp_iv_length',
Integer,
default=None
)
_kdw_mski_cp_tag_length = Column(
'_kdw_mski_cp_tag_length',
Integer,
default=None
)
_kdw_mski_cp_fixed_field_length = Column(
'_kdw_mski_cp_fixed_field_length',
Integer,
default=None
)
_kdw_mski_cp_invocation_field_length = Column(
'_kdw_mski_cp_invocation_field_length',
Integer,
default=None
)
_kdw_mski_cp_counter_length = Column(
'_kdw_mski_cp_counter_length',
Integer,
default=None
)
_kdw_mski_cp_initial_counter_value = Column(
'_kdw_mski_cp_initial_counter_value',
Integer,
default=None
)
_kdw_mac_signature = Column(
'_kdw_mac_signature',
VARBINARY(1024),
default=None
)
_kdw_iv_counter_nonce = Column(
'_kdw_iv_counter_nonce',
VARBINARY(1024),
default=None
)
_kdw_encoding_option = Column(
'_kdw_encoding_option',
sql.EnumType(enums.EncodingOption),
default=None
)
__mapper_args__ = {
'polymorphic_identity': 'Key'
}
@ -232,15 +396,21 @@ class Key(CryptographicObject):
}
@abstractmethod
def __init__(self):
def __init__(self, key_wrapping_data=None):
"""
Create a Key object.
Args:
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
Optional, defaults to None.
"""
super(Key, self).__init__()
self.cryptographic_algorithm = None
self.cryptographic_length = None
self.key_format_type = None
self.key_wrapping_data = key_wrapping_data
# All remaining attributes are not considered part of the public API
# and are subject to change.
@ -250,6 +420,145 @@ class Key(CryptographicObject):
# unsupported by kmip.core
self._usage_limits = None
@property
def key_wrapping_data(self):
"""
Retrieve all of the relevant key wrapping data fields and return them
as a dictionary.
"""
key_wrapping_data = {}
encryption_key_info = {
'unique_identifier': self._kdw_eki_unique_identifier,
'cryptographic_parameters': {
'block_cipher_mode': self._kdw_eki_cp_block_cipher_mode,
'padding_method': self._kdw_eki_cp_padding_method,
'hashing_algorithm': self._kdw_eki_cp_hashing_algorithm,
'key_role_type': self._kdw_eki_cp_key_role_type,
'digital_signature_algorithm':
self._kdw_eki_cp_digital_signature_algorithm,
'cryptographic_algorithm':
self._kdw_eki_cp_cryptographic_algorithm,
'random_iv': self._kdw_eki_cp_random_iv,
'iv_length': self._kdw_eki_cp_iv_length,
'tag_length': self._kdw_eki_cp_tag_length,
'fixed_field_length': self._kdw_eki_cp_fixed_field_length,
'invocation_field_length':
self._kdw_eki_cp_invocation_field_length,
'counter_length': self._kdw_eki_cp_counter_length,
'initial_counter_value':
self._kdw_eki_cp_initial_counter_value
}
}
if not any(encryption_key_info['cryptographic_parameters'].values()):
encryption_key_info['cryptographic_parameters'] = {}
if not any(encryption_key_info.values()):
encryption_key_info = {}
mac_sign_key_info = {
'unique_identifier': self._kdw_mski_unique_identifier,
'cryptographic_parameters': {
'block_cipher_mode': self._kdw_mski_cp_block_cipher_mode,
'padding_method': self._kdw_mski_cp_padding_method,
'hashing_algorithm': self._kdw_mski_cp_hashing_algorithm,
'key_role_type': self._kdw_mski_cp_key_role_type,
'digital_signature_algorithm':
self._kdw_mski_cp_digital_signature_algorithm,
'cryptographic_algorithm':
self._kdw_mski_cp_cryptographic_algorithm,
'random_iv': self._kdw_mski_cp_random_iv,
'iv_length': self._kdw_mski_cp_iv_length,
'tag_length': self._kdw_mski_cp_tag_length,
'fixed_field_length': self._kdw_mski_cp_fixed_field_length,
'invocation_field_length':
self._kdw_mski_cp_invocation_field_length,
'counter_length': self._kdw_mski_cp_counter_length,
'initial_counter_value':
self._kdw_mski_cp_initial_counter_value
}
}
if not any(mac_sign_key_info['cryptographic_parameters'].values()):
mac_sign_key_info['cryptographic_parameters'] = {}
if not any(mac_sign_key_info.values()):
mac_sign_key_info = {}
key_wrapping_data['wrapping_method'] = self._kdw_wrapping_method
key_wrapping_data['encryption_key_information'] = encryption_key_info
key_wrapping_data['mac_signature_key_information'] = mac_sign_key_info
key_wrapping_data['mac_signature'] = self._kdw_mac_signature
key_wrapping_data['iv_counter_nonce'] = self._kdw_iv_counter_nonce
key_wrapping_data['encoding_option'] = self._kdw_encoding_option
if not any(key_wrapping_data.values()):
key_wrapping_data = {}
return key_wrapping_data
@key_wrapping_data.setter
def key_wrapping_data(self, value):
"""
Set the key wrapping data attributes using a dictionary.
"""
if value is None:
value = {}
elif not isinstance(value, dict):
raise TypeError("Key wrapping data must be a dictionary.")
self._kdw_wrapping_method = value.get('wrapping_method')
eki = value.get('encryption_key_information')
if eki is None:
eki = {}
self._kdw_eki_unique_identifier = eki.get('unique_identifier')
eki_cp = eki.get('cryptographic_parameters')
if eki_cp is None:
eki_cp = {}
self._kdw_eki_cp_block_cipher_mode = eki_cp.get('block_cipher_mode')
self._kdw_eki_cp_padding_method = eki_cp.get('padding_method')
self._kdw_eki_cp_hashing_algorithm = eki_cp.get('hashing_algorithm')
self._kdw_eki_cp_key_role_type = eki_cp.get('key_role_type')
self._kdw_eki_cp_digital_signature_algorithm = \
eki_cp.get('digital_signature_algorithm')
self._kdw_eki_cp_cryptographic_algorithm = \
eki_cp.get('cryptographic_algorithm')
self._kdw_eki_cp_random_iv = eki_cp.get('random_iv')
self._kdw_eki_cp_iv_length = eki_cp.get('iv_length')
self._kdw_eki_cp_tag_length = eki_cp.get('tag_length')
self._kdw_eki_cp_fixed_field_length = eki_cp.get('fixed_field_length')
self._kdw_eki_cp_invocation_field_length = \
eki_cp.get('invocation_field_length')
self._kdw_eki_cp_counter_length = eki_cp.get('counter_length')
self._kdw_eki_cp_initial_counter_value = \
eki_cp.get('initial_counter_value')
mski = value.get('mac_signature_key_information')
if mski is None:
mski = {}
self._kdw_mski_unique_identifier = mski.get('unique_identifier')
mski_cp = mski.get('cryptographic_parameters')
if mski_cp is None:
mski_cp = {}
self._kdw_mski_cp_block_cipher_mode = mski_cp.get('block_cipher_mode')
self._kdw_mski_cp_padding_method = mski_cp.get('padding_method')
self._kdw_mski_cp_hashing_algorithm = mski_cp.get('hashing_algorithm')
self._kdw_mski_cp_key_role_type = mski_cp.get('key_role_type')
self._kdw_mski_cp_digital_signature_algorithm = \
mski_cp.get('digital_signature_algorithm')
self._kdw_mski_cp_cryptographic_algorithm = \
mski_cp.get('cryptographic_algorithm')
self._kdw_mski_cp_random_iv = mski_cp.get('random_iv')
self._kdw_mski_cp_iv_length = mski_cp.get('iv_length')
self._kdw_mski_cp_tag_length = mski_cp.get('tag_length')
self._kdw_mski_cp_fixed_field_length = \
mski_cp.get('fixed_field_length')
self._kdw_mski_cp_invocation_field_length = \
mski_cp.get('invocation_field_length')
self._kdw_mski_cp_counter_length = mski_cp.get('counter_length')
self._kdw_mski_cp_initial_counter_value = \
mski_cp.get('initial_counter_value')
self._kdw_mac_signature = value.get('mac_signature')
self._kdw_iv_counter_nonce = value.get('iv_counter_nonce')
self._kdw_encoding_option = value.get('encoding_option')
class SymmetricKey(Key):
"""
@ -267,6 +576,8 @@ class SymmetricKey(Key):
cryptographic_usage_masks: The list of usage mask flags for
SymmetricKey application.
names: The string names of the SymmetricKey.
key_wrapping_data: A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
"""
__tablename__ = 'symmetric_keys'
@ -282,7 +593,7 @@ class SymmetricKey(Key):
}
def __init__(self, algorithm, length, value, masks=None,
name='Symmetric Key'):
name='Symmetric Key', key_wrapping_data=None):
"""
Create a SymmetricKey.
@ -295,8 +606,13 @@ class SymmetricKey(Key):
how the key will be used. Optional, defaults to None.
name(string): The string name of the key. Optional, defaults to
'Symmetric Key'.
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
Optional, defaults to None.
"""
super(SymmetricKey, self).__init__()
super(SymmetricKey, self).__init__(
key_wrapping_data=key_wrapping_data
)
self._object_type = enums.ObjectType.SYMMETRIC_KEY
self.key_format_type = enums.KeyFormatType.RAW
@ -353,17 +669,29 @@ class SymmetricKey(Key):
raise TypeError("key name {0} must be a string".format(
position))
if (len(self.value) * 8) != self.cryptographic_length:
msg = "key length ({0}) not equal to key value length ({1})"
msg = msg.format(self.cryptographic_length, len(self.value) * 8)
raise ValueError(msg)
if not self.key_wrapping_data:
if (len(self.value) * 8) != self.cryptographic_length:
msg = "key length ({0}) not equal to key value length ({1})"
msg = msg.format(
self.cryptographic_length,
len(self.value) * 8
)
raise ValueError(msg)
def __repr__(self):
algorithm = "algorithm={0}".format(self.cryptographic_algorithm)
length = "length={0}".format(self.cryptographic_length)
value = "value={0}".format(binascii.hexlify(self.value))
key_wrapping_data = "key_wrapping_data={0}".format(
self.key_wrapping_data
)
return "SymmetricKey({0}, {1}, {2})".format(algorithm, length, value)
return "SymmetricKey({0}, {1}, {2}, {3})".format(
algorithm,
length,
value,
key_wrapping_data
)
def __str__(self):
return str(binascii.hexlify(self.value))
@ -376,6 +704,8 @@ class SymmetricKey(Key):
return False
elif self.cryptographic_length != other.cryptographic_length:
return False
elif self.key_wrapping_data != other.key_wrapping_data:
return False
else:
return True
else:
@ -408,6 +738,8 @@ class PublicKey(Key):
cryptographic_usage_masks: The list of usage mask flags for PublicKey
application.
names: The list of string names of the PublicKey.
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
"""
__tablename__ = 'public_keys'
@ -424,7 +756,7 @@ class PublicKey(Key):
def __init__(self, algorithm, length, value,
format_type=enums.KeyFormatType.X_509, masks=None,
name='Public Key'):
name='Public Key', key_wrapping_data=None):
"""
Create a PublicKey.
@ -439,8 +771,13 @@ class PublicKey(Key):
defining how the key will be used. Optional, defaults to None.
name(string): The string name of the key. Optional, defaults to
'Public Key'.
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
Optional, defaults to None.
"""
super(PublicKey, self).__init__()
super(PublicKey, self).__init__(
key_wrapping_data=key_wrapping_data
)
self._object_type = enums.ObjectType.PUBLIC_KEY
self._valid_formats = [
@ -512,9 +849,12 @@ class PublicKey(Key):
length = "length={0}".format(self.cryptographic_length)
value = "value={0}".format(binascii.hexlify(self.value))
format_type = "format_type={0}".format(self.key_format_type)
key_wrapping_data = "key_wrapping_data={0}".format(
self.key_wrapping_data
)
return "PublicKey({0}, {1}, {2}, {3})".format(
algorithm, length, value, format_type)
return "PublicKey({0}, {1}, {2}, {3}, {4})".format(
algorithm, length, value, format_type, key_wrapping_data)
def __str__(self):
return str(binascii.hexlify(self.value))
@ -529,6 +869,8 @@ class PublicKey(Key):
return False
elif self.cryptographic_length != other.cryptographic_length:
return False
elif self.key_wrapping_data != other.key_wrapping_data:
return False
else:
return True
else:
@ -562,6 +904,8 @@ class PrivateKey(Key):
application. Optional, defaults to None.
names: The list of string names of the PrivateKey. Optional, defaults
to 'Private Key'.
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
"""
__tablename__ = 'private_keys'
@ -577,7 +921,7 @@ class PrivateKey(Key):
}
def __init__(self, algorithm, length, value, format_type, masks=None,
name='Private Key'):
name='Private Key', key_wrapping_data=None):
"""
Create a PrivateKey.
@ -591,8 +935,13 @@ class PrivateKey(Key):
masks(list): A list of CryptographicUsageMask enumerations
defining how the key will be used.
name(string): The string name of the key.
key_wrapping_data(dict): A dictionary containing key wrapping data
settings, describing how the key value has been wrapped.
Optional, defaults to None.
"""
super(PrivateKey, self).__init__()
super(PrivateKey, self).__init__(
key_wrapping_data=key_wrapping_data
)
self._object_type = enums.ObjectType.PRIVATE_KEY
self._valid_formats = [
@ -664,9 +1013,12 @@ class PrivateKey(Key):
length = "length={0}".format(self.cryptographic_length)
value = "value={0}".format(binascii.hexlify(self.value))
format_type = "format_type={0}".format(self.key_format_type)
key_wrapping_data = "key_wrapping_data={0}".format(
self.key_wrapping_data
)
return "PrivateKey({0}, {1}, {2}, {3})".format(
algorithm, length, value, format_type)
return "PrivateKey({0}, {1}, {2}, {3}, {4})".format(
algorithm, length, value, format_type, key_wrapping_data)
def __str__(self):
return str(binascii.hexlify(self.value))
@ -681,6 +1033,8 @@ class PrivateKey(Key):
return False
elif self.cryptographic_length != other.cryptographic_length:
return False
elif self.key_wrapping_data != other.key_wrapping_data:
return False
else:
return True
else:

@ -107,7 +107,10 @@ class EnumType(types.TypeDecorator):
value(Enum): An Enum instance whose integer value is to be stored.
dialect(string): SQL dialect
"""
return value.value
if value:
return value.value
else:
return -1
def process_result_value(self, value, dialect):
"""
@ -120,6 +123,8 @@ class EnumType(types.TypeDecorator):
to create the Enum
dialect(string): SQL dialect
"""
if value == -1:
return None
return self._cls(value)

@ -94,3 +94,17 @@ class TestKey(TestCase):
"""
dummy = DummyKey()
self.assertFalse(dummy != dummy)
def test_key_wrapping_data_invalid(self):
"""
Test that the right error is raised when setting the key wrapping
data with an invalid value.
"""
dummy = DummyKey()
args = (dummy, 'key_wrapping_data', 'invalid')
self.assertRaisesRegexp(
TypeError,
"Key wrapping data must be a dictionary.",
setattr,
*args
)

@ -300,9 +300,13 @@ class TestPrivateKey(testtools.TestCase):
key = PrivateKey(
enums.CryptographicAlgorithm.RSA, 1024, self.bytes_1024,
enums.KeyFormatType.PKCS_8)
args = "algorithm={0}, length={1}, value={2}, format_type={3}".format(
enums.CryptographicAlgorithm.RSA, 1024,
binascii.hexlify(self.bytes_1024), enums.KeyFormatType.PKCS_8)
args = "{0}, {1}, {2}, {3}, {4}".format(
"algorithm={0}".format(enums.CryptographicAlgorithm.RSA),
"length={0}".format(1024),
"value={0}".format(binascii.hexlify(self.bytes_1024)),
"format_type={0}".format(enums.KeyFormatType.PKCS_8),
"key_wrapping_data={0}".format({})
)
expected = "PrivateKey({0})".format(args)
observed = repr(key)
self.assertEqual(expected, observed)
@ -388,6 +392,31 @@ class TestPrivateKey(testtools.TestCase):
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the equality operator returns False when comparing two
PrivateKey objects with different key wrapping data.
"""
a = PrivateKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.PKCS_8,
key_wrapping_data={}
)
b = PrivateKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.PKCS_8,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_type_mismatch(self):
"""
Test that the equality operator returns False when comparing a
@ -470,6 +499,31 @@ class TestPrivateKey(testtools.TestCase):
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the inequality operator returns True when comparing two
PrivateKey objects with different key wrapping data.
"""
a = PrivateKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.PKCS_8,
key_wrapping_data={}
)
b = PrivateKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.PKCS_8,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_type_mismatch(self):
"""
Test that the equality operator returns True when comparing a

@ -198,9 +198,13 @@ class TestPublicKey(testtools.TestCase):
key = PublicKey(
enums.CryptographicAlgorithm.RSA, 1024, self.bytes_1024,
enums.KeyFormatType.X_509)
args = "algorithm={0}, length={1}, value={2}, format_type={3}".format(
enums.CryptographicAlgorithm.RSA, 1024,
binascii.hexlify(self.bytes_1024), enums.KeyFormatType.X_509)
args = "{0}, {1}, {2}, {3}, {4}".format(
"algorithm={0}".format(enums.CryptographicAlgorithm.RSA),
"length={0}".format(1024),
"value={0}".format(binascii.hexlify(self.bytes_1024)),
"format_type={0}".format(enums.KeyFormatType.X_509),
"key_wrapping_data={0}".format({})
)
expected = "PublicKey({0})".format(args)
observed = repr(key)
self.assertEqual(expected, observed)
@ -286,6 +290,31 @@ class TestPublicKey(testtools.TestCase):
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the equality operator returns False when comparing two
PublicKey objects with different key wrapping data.
"""
a = PublicKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.X_509,
key_wrapping_data={}
)
b = PublicKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.X_509,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_type_mismatch(self):
"""
Test that the equality operator returns False when comparing a
@ -368,6 +397,31 @@ class TestPublicKey(testtools.TestCase):
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the inequality operator returns True when comparing two
PublicKey objects with different key wrapping data.
"""
a = PublicKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.X_509,
key_wrapping_data={}
)
b = PublicKey(
enums.CryptographicAlgorithm.RSA,
1024,
self.bytes_1024,
enums.KeyFormatType.X_509,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_type_mismatch(self):
"""
Test that the equality operator returns True when comparing a

@ -179,11 +179,17 @@ class TestSymmetricKey(testtools.TestCase):
Test that repr can be applied to a SymmetricKey.
"""
key = SymmetricKey(
enums.CryptographicAlgorithm.AES, 128, self.bytes_128a)
enums.CryptographicAlgorithm.AES,
128,
self.bytes_128a
)
args = "algorithm={0}, length={1}, value={2}".format(
enums.CryptographicAlgorithm.AES, 128,
binascii.hexlify(self.bytes_128a))
args = "{0}, {1}, {2}, {3}".format(
"algorithm={0}".format(enums.CryptographicAlgorithm.AES),
"length={0}".format(128),
"value={0}".format(binascii.hexlify(self.bytes_128a)),
"key_wrapping_data={0}".format({})
)
expected = "SymmetricKey({0})".format(args)
observed = repr(key)
@ -253,6 +259,29 @@ class TestSymmetricKey(testtools.TestCase):
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the equality operator returns False when comparing two
SymmetricKey objects with different key wrapping data.
"""
a = SymmetricKey(
enums.CryptographicAlgorithm.AES,
128,
self.bytes_128a,
key_wrapping_data={}
)
b = SymmetricKey(
enums.CryptographicAlgorithm.AES,
128,
self.bytes_128a,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertFalse(a == b)
self.assertFalse(b == a)
def test_equal_on_type_mismatch(self):
"""
Test that the equality operator returns False when comparing a
@ -317,6 +346,29 @@ class TestSymmetricKey(testtools.TestCase):
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_not_equal_key_wrapping_data(self):
"""
Test that the inequality operator returns True when comparing two
SymmetricKey objects with different key wrapping data.
"""
a = SymmetricKey(
enums.CryptographicAlgorithm.AES,
128,
self.bytes_128a,
key_wrapping_data={}
)
b = SymmetricKey(
enums.CryptographicAlgorithm.AES,
128,
self.bytes_128a,
key_wrapping_data={
'wrapping_method': enums.WrappingMethod.ENCRYPT
}
)
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_not_equal_on_type_mismatch(self):
"""
Test that the equality operator returns True when comparing a

@ -562,3 +562,103 @@ class TestObjectFactory(testtools.TestCase):
self.assertEqual(key.cryptographic_length, length)
self.assertEqual(key.key_format_type, format_type)
self.assertEqual(key.value, value)
def test_build_cryptographic_parameters(self):
cryptographic_parameters = cobjects.CryptographicParameters(
block_cipher_mode=enums.BlockCipherMode.CBC,
padding_method=enums.PaddingMethod.ANSI_X923,
hashing_algorithm=enums.HashingAlgorithm.SHA_256,
key_role_type=enums.KeyRoleType.KEK,
digital_signature_algorithm=enums.DigitalSignatureAlgorithm.
DSA_WITH_SHA1,
cryptographic_algorithm=enums.CryptographicAlgorithm.AES,
random_iv=True,
iv_length=32,
tag_length=33,
fixed_field_length=34,
invocation_field_length=35,
counter_length=36,
initial_counter_value=0
)
result = self.factory._build_cryptographic_parameters(
cryptographic_parameters
)
self.assertIsInstance(result, dict)
self.assertEqual(
enums.BlockCipherMode.CBC,
result.get('block_cipher_mode')
)
self.assertEqual(
enums.PaddingMethod.ANSI_X923,
result.get('padding_method')
)
self.assertEqual(
enums.HashingAlgorithm.SHA_256,
result.get('hashing_algorithm')
)
self.assertEqual(
enums.KeyRoleType.KEK,
result.get('key_role_type')
)
self.assertEqual(
enums.DigitalSignatureAlgorithm.DSA_WITH_SHA1,
result.get('digital_signature_algorithm')
)
self.assertEqual(
enums.CryptographicAlgorithm.AES,
result.get('cryptographic_algorithm')
)
self.assertEqual(True, result.get('random_iv'))
self.assertEqual(32, result.get('iv_length'))
self.assertEqual(33, result.get('tag_length'))
self.assertEqual(34, result.get('fixed_field_length'))
self.assertEqual(35, result.get('invocation_field_length'))
self.assertEqual(36, result.get('counter_length'))
self.assertEqual(0, result.get('initial_counter_value'))
def test_build_key_wrapping_data(self):
key_wrapping_data = cobjects.KeyWrappingData(
wrapping_method=enums.WrappingMethod.ENCRYPT,
encryption_key_information=cobjects.EncryptionKeyInformation(
unique_identifier='1',
cryptographic_parameters=cobjects.CryptographicParameters(
block_cipher_mode=enums.BlockCipherMode.CBC
)
),
mac_signature_key_information=cobjects.MACSignatureKeyInformation(
unique_identifier='2',
cryptographic_parameters=cobjects.CryptographicParameters(
block_cipher_mode=enums.BlockCipherMode.CCM
)
),
mac_signature=b'\x01',
iv_counter_nonce=b'\x02',
encoding_option=enums.EncodingOption.NO_ENCODING
)
result = self.factory._build_key_wrapping_data(
key_wrapping_data
)
self.assertIsInstance(result, dict)
self.assertEqual(
enums.WrappingMethod.ENCRYPT,
result.get('wrapping_method')
)
self.assertIsInstance(result.get('encryption_key_information'), dict)
eki = result.get('encryption_key_information')
self.assertEqual('1', eki.get('unique_identifier'))
self.assertIsInstance(eki.get('cryptographic_parameters'), dict)
self.assertIsInstance(
result.get('mac_signature_key_information'),
dict
)
mski = result.get('mac_signature_key_information')
self.assertEqual('2', mski.get('unique_identifier'))
self.assertIsInstance(mski.get('cryptographic_parameters'), dict)
self.assertEqual(b'\x01', result.get('mac_signature'))
self.assertEqual(b'\x02', result.get('iv_counter_nonce'))
self.assertEqual(
enums.EncodingOption.NO_ENCODING,
result.get('encoding_option')
)