mirror of
https://github.com/OpenKMIP/PyKMIP.git
synced 2025-04-08 19:25:06 +02:00
Merge pull request #347 from OpenKMIP/feat/add-key-wrapping-data-model
Update the object data model to support storing key wrapping data
This commit is contained in:
commit
6df0315d41
@ -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')
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user