mirror of
https://github.com/OpenKMIP/PyKMIP.git
synced 2025-07-20 20:44:22 +02:00
Adding support for Digest
This change adds support for the Digest attribute, including updates and unit test suites for all dependent KMIP objects.
This commit is contained in:
parent
f784b67f3a
commit
3e11002567
@ -15,13 +15,18 @@
|
||||
|
||||
from kmip.core import enums
|
||||
|
||||
from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.misc import KeyFormatType
|
||||
|
||||
from kmip.core.primitives import ByteString
|
||||
from kmip.core.primitives import Enumeration
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import TextString
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
@ -173,6 +178,28 @@ class CryptographicLength(Integer):
|
||||
|
||||
|
||||
# 3.6
|
||||
class HashingAlgorithm(Enumeration):
|
||||
"""
|
||||
An encodeable wrapper for the HashingAlgorithm enumeration.
|
||||
|
||||
Used to specify the algorithm used to compute the Digest of a Managed
|
||||
Object. See Sections 3.17 and 9.1.3.2.16 of the KMIP v1.1 specification
|
||||
for more information.
|
||||
"""
|
||||
ENUM_TYPE = enums.HashingAlgorithm
|
||||
|
||||
def __init__(self, value=HashingAlgorithmEnum.SHA_256):
|
||||
"""
|
||||
Construct a HashingAlgorithm object.
|
||||
|
||||
Args:
|
||||
value (HashingAlgorithm): A HashingAlgorithm enumeration value,
|
||||
(e.g., HashingAlgorithm.MD5). Optional, defaults to
|
||||
HashingAlgorithm.SHA_256.
|
||||
"""
|
||||
super(HashingAlgorithm, self).__init__(value, Tags.HASHING_ALGORITHM)
|
||||
|
||||
|
||||
class CryptographicParameters(Struct):
|
||||
|
||||
class BlockCipherMode(Enumeration):
|
||||
@ -189,13 +216,6 @@ class CryptographicParameters(Struct):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.PADDING_METHOD)
|
||||
|
||||
class HashingAlgorithm(Enumeration):
|
||||
ENUM_TYPE = enums.HashingAlgorithm
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.HASHING_ALGORITHM)
|
||||
|
||||
class KeyRoleType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyRoleType
|
||||
|
||||
@ -227,7 +247,7 @@ class CryptographicParameters(Struct):
|
||||
self.padding_method.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.HASHING_ALGORITHM, tstream):
|
||||
self.hashing_algorithm = CryptographicParameters.HashingAlgorithm()
|
||||
self.hashing_algorithm = HashingAlgorithm()
|
||||
self.hashing_algorithm.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_ROLE_TYPE, tstream):
|
||||
@ -272,6 +292,218 @@ class CertificateType(Enumeration):
|
||||
Tags.CERTIFICATE_TYPE)
|
||||
|
||||
|
||||
# 3.17
|
||||
class DigestValue(ByteString):
|
||||
"""
|
||||
A byte string representing the hash value of a Digest.
|
||||
|
||||
Used to hold the bytes of the digest hash value. Automatically generated
|
||||
by the KMIP server, the value is empty if the server does not have access
|
||||
to the value or encoding of the related Managed Object. See Section 3.17
|
||||
of the KMIP 1.1 specification for more information.
|
||||
|
||||
Attributes:
|
||||
value: The bytes of the hash.
|
||||
"""
|
||||
|
||||
def __init__(self, value=b''):
|
||||
"""
|
||||
Construct a DigestValue object.
|
||||
|
||||
Args:
|
||||
value (bytes): The bytes of the hash. Optional, defaults to
|
||||
the empty byte string.
|
||||
"""
|
||||
super(DigestValue, self).__init__(value, Tags.DIGEST_VALUE)
|
||||
|
||||
|
||||
class Digest(Struct):
|
||||
"""
|
||||
A structure storing a hash digest of a Managed Object.
|
||||
|
||||
Digests may be calculated for keys, secret data objects, certificates, and
|
||||
opaque data objects and are generated when the object is created or
|
||||
registered with the KMIP server. See Section 3.17 of the KMIP 1.1
|
||||
specification for more information.
|
||||
|
||||
Attributes:
|
||||
hashing_algorithm: The algorithm used to compute the hash digest.
|
||||
digest_value: The bytes representing the hash digest value.
|
||||
key_format_type: The type of the key the hash was generated for.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
hashing_algorithm=None,
|
||||
digest_value=None,
|
||||
key_format_type=None):
|
||||
"""
|
||||
Construct a Digest object.
|
||||
|
||||
Args:
|
||||
hashing_algorithm (HashingAlgorithm): The hash algorithm used to
|
||||
compute the value of the digest. Optional, defaults to None.
|
||||
digest_value (DigestValue): The byte string representing the
|
||||
value of the hash digest. Optional, defaults to None.
|
||||
key_format_type (KeyFormatType): The format type of the key the
|
||||
hash was computed for, if the object in question is a key.
|
||||
Optional, defaults to None.
|
||||
"""
|
||||
super(Digest, self).__init__(Tags.DIGEST)
|
||||
|
||||
if hashing_algorithm is None:
|
||||
self.hashing_algorithm = HashingAlgorithm()
|
||||
else:
|
||||
self.hashing_algorithm = hashing_algorithm
|
||||
|
||||
if digest_value is None:
|
||||
self.digest_value = DigestValue()
|
||||
else:
|
||||
self.digest_value = digest_value
|
||||
|
||||
if key_format_type is None:
|
||||
self.key_format_type = KeyFormatType()
|
||||
else:
|
||||
self.key_format_type = key_format_type
|
||||
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
"""
|
||||
Read the data encoding the Digest object and decode it into its
|
||||
constituent parts.
|
||||
|
||||
Args:
|
||||
istream (Stream): A data stream containing encoded object data,
|
||||
supporting a read method; usually a BytearrayStream object.
|
||||
"""
|
||||
super(Digest, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.hashing_algorithm.read(tstream)
|
||||
self.digest_value.read(tstream)
|
||||
self.key_format_type.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
"""
|
||||
Write the data encoding the Digest object to a stream.
|
||||
|
||||
Args:
|
||||
ostream (Stream): A data stream in which to encode object data,
|
||||
supporting a write method; usually a BytearrayStream object.
|
||||
"""
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.hashing_algorithm.write(tstream)
|
||||
self.digest_value.write(tstream)
|
||||
self.key_format_type.write(tstream)
|
||||
|
||||
self.length = tstream.length()
|
||||
super(Digest, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Error check the attributes of the Digest object.
|
||||
"""
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Add checks comparing the length of the digest
|
||||
# value against the standard length for the stated hashing algorithm.
|
||||
if not isinstance(self.hashing_algorithm, HashingAlgorithm):
|
||||
msg = "invalid hashing algorithm"
|
||||
msg += "; expected {0}, received {1}".format(
|
||||
HashingAlgorithm, self.hashing_algorithm)
|
||||
raise TypeError(msg)
|
||||
|
||||
if not isinstance(self.digest_value, DigestValue):
|
||||
msg = "invalid digest value"
|
||||
msg += "; expected {0}, received {1}".format(
|
||||
DigestValue, self.digest_value)
|
||||
raise TypeError(msg)
|
||||
|
||||
if not isinstance(self.key_format_type, KeyFormatType):
|
||||
msg = "invalid key format type"
|
||||
msg += "; expected {0}, received {1}".format(
|
||||
KeyFormatType, self.key_format_type)
|
||||
raise TypeError(msg)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Digest):
|
||||
if self.hashing_algorithm != other.hashing_algorithm:
|
||||
return False
|
||||
elif self.digest_value != other.digest_value:
|
||||
return False
|
||||
elif self.key_format_type != other.key_format_type:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
if isinstance(other, Digest):
|
||||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __repr__(self):
|
||||
hashing_algorithm = "hashing_algorithm={0}".format(
|
||||
repr(self.hashing_algorithm))
|
||||
digest_value = "digest_value={0}".format(
|
||||
repr(self.digest_value))
|
||||
key_format_type = "key_format_type={0}".format(
|
||||
repr(self.key_format_type))
|
||||
|
||||
return "Digest({0}, {1}, {2})".format(
|
||||
hashing_algorithm, digest_value, key_format_type)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.digest_value)
|
||||
|
||||
@classmethod
|
||||
def create(cls,
|
||||
hashing_algorithm=HashingAlgorithmEnum.SHA_256,
|
||||
digest_value=b'',
|
||||
key_format_type=KeyFormatTypeEnum.RAW):
|
||||
"""
|
||||
Construct a Digest object from provided digest values.
|
||||
|
||||
Args:
|
||||
hashing_algorithm (HashingAlgorithm): An enumeration representing
|
||||
the hash algorithm used to compute the digest. Optional,
|
||||
defaults to HashingAlgorithm.SHA_256.
|
||||
digest_value (byte string): The bytes of the digest hash. Optional,
|
||||
defaults to the empty byte string.
|
||||
key_format_type (KeyFormatType): An enumeration representing the
|
||||
format of the key corresponding to the digest. Optional,
|
||||
defaults to KeyFormatType.RAW.
|
||||
|
||||
Returns:
|
||||
Digest: The newly created Digest.
|
||||
|
||||
Example:
|
||||
>>> x = Digest.create(HashingAlgorithm.MD5, b'\x00',
|
||||
... KeyFormatType.RAW)
|
||||
>>> x.hashing_algorithm
|
||||
HashingAlgorithm(value=HashingAlgorithm.MD5)
|
||||
>>> x.digest_value
|
||||
DigestValue(value=bytearray(b'\x00'))
|
||||
>>> x.key_format_type
|
||||
KeyFormatType(value=KeyFormatType.RAW)
|
||||
"""
|
||||
algorithm = HashingAlgorithm(hashing_algorithm)
|
||||
value = DigestValue(bytearray(digest_value))
|
||||
format_type = KeyFormatType(key_format_type)
|
||||
|
||||
return Digest(hashing_algorithm=algorithm,
|
||||
digest_value=value,
|
||||
key_format_type=format_type)
|
||||
|
||||
|
||||
# 3.18
|
||||
class OperationPolicyName(TextString):
|
||||
|
||||
|
@ -21,6 +21,7 @@ from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
from kmip.core.attributes import CryptographicUsageMask
|
||||
from kmip.core.attributes import CustomAttribute
|
||||
from kmip.core.attributes import Digest
|
||||
from kmip.core.attributes import Name
|
||||
from kmip.core.attributes import ObjectGroup
|
||||
from kmip.core.attributes import UniqueIdentifier
|
||||
@ -67,7 +68,7 @@ class AttributeValueFactory(object):
|
||||
elif name is AttributeType.DIGITAL_SIGNATURE_ALGORITHM:
|
||||
value = self._create_digital_signature_algorithm(value)
|
||||
elif name is AttributeType.DIGEST:
|
||||
value = self._create_digest(value)
|
||||
value = self._create_digest()
|
||||
elif name is AttributeType.OPERATION_POLICY_NAME:
|
||||
value = self._create_operation_policy_name(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_USAGE_MASK:
|
||||
@ -182,8 +183,8 @@ class AttributeValueFactory(object):
|
||||
def _create_digital_signature_algorithm(self, alg):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_digest(self, digest):
|
||||
raise NotImplementedError()
|
||||
def _create_digest(self):
|
||||
return Digest()
|
||||
|
||||
def _create_operation_policy_name(self, name):
|
||||
return OperationPolicyName(name)
|
||||
|
@ -19,8 +19,8 @@ from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
|
||||
from kmip.core.enums import ObjectType
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
from kmip.core.misc import KeyFormatType
|
||||
|
||||
from kmip.core.objects import Attribute
|
||||
from kmip.core.objects import KeyBlock
|
||||
@ -75,7 +75,7 @@ class SecretFactory(object):
|
||||
cryptographic_length = value.get('cryptographic_length')
|
||||
key_wrapping_data = value.get('key_wrapping_data')
|
||||
|
||||
key_format_type = KeyBlock.KeyFormatType(key_type)
|
||||
key_format_type = KeyFormatType(key_type)
|
||||
|
||||
key_comp_type = None
|
||||
if key_compression_type is not None:
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
from kmip.core.enums import BatchErrorContinuationOption
|
||||
from kmip.core.enums import KeyCompressionType
|
||||
from kmip.core.enums import KeyFormatType
|
||||
from kmip.core.enums import Operation
|
||||
from kmip.core.enums import ResultStatus
|
||||
from kmip.core.enums import ResultReason
|
||||
@ -270,12 +269,3 @@ class KeyCompressionType(Enumeration):
|
||||
def __init__(self, value=None):
|
||||
super(KeyCompressionType, self).\
|
||||
__init__(value, Tags.KEY_COMPRESSION_TYPE)
|
||||
|
||||
|
||||
# 9.1.3.2.3
|
||||
class KeyFormatType(Enumeration):
|
||||
ENUM_TYPE = KeyFormatType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(KeyFormatType, self).\
|
||||
__init__(value, Tags.KEY_FORMAT_TYPE)
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import Tags
|
||||
from kmip.core.enums import QueryFunction as QueryFunctionEnum
|
||||
|
||||
@ -30,7 +31,7 @@ class Offset(Interval):
|
||||
|
||||
Used by Rekey and Recertify requests to indicate the time difference
|
||||
between the InitializationDate and the ActivationDate of the replacement
|
||||
item to be created. See Sections 4.4, 4.5, and 4.8 of the KMIP v1.1
|
||||
item to be created. See Sections 4.4, 4.5, and 4.8 of the KMIP 1.1
|
||||
specification for more information.
|
||||
"""
|
||||
|
||||
@ -50,7 +51,7 @@ class QueryFunction(Enumeration):
|
||||
An encodeable wrapper for the QueryFunction enumeration.
|
||||
|
||||
Used by Query requests to specify the information to retrieve from the
|
||||
KMIP server. See Sections 4.25 and 9.1.3.2.24 of the KMIP v1.1
|
||||
KMIP server. See Sections 4.25 and 9.1.3.2.24 of the KMIP 1.1
|
||||
specification for more information.
|
||||
"""
|
||||
ENUM_TYPE = QueryFunctionEnum
|
||||
@ -72,7 +73,7 @@ class VendorIdentification(TextString):
|
||||
A text string uniquely identifying a KMIP vendor.
|
||||
|
||||
Returned by KMIP servers upon receipt of a Query request for server
|
||||
information. See Section 4.25 of the KMIP v1.1. specification for more
|
||||
information. See Section 4.25 of the KMIP 1.1. specification for more
|
||||
information.
|
||||
"""
|
||||
|
||||
@ -93,7 +94,7 @@ class ServerInformation(Struct):
|
||||
A structure containing vendor-specific fields and/or substructures.
|
||||
|
||||
Returned by KMIP servers upon receipt of a Query request for server
|
||||
information. See Section 4.25 of the KMIP v1.1 specification for more
|
||||
information. See Section 4.25 of the KMIP 1.1 specification for more
|
||||
information.
|
||||
|
||||
Note:
|
||||
@ -182,3 +183,26 @@ class ServerInformation(Struct):
|
||||
|
||||
def __str__(self):
|
||||
return str(self.data)
|
||||
|
||||
|
||||
class KeyFormatType(Enumeration):
|
||||
"""
|
||||
An encodeable wrapper for the KeyFormatType enumeration.
|
||||
|
||||
Used to identify the format of different types of keys in KeyBlock and
|
||||
Digest objects, it can also be used to specify the format in which a key
|
||||
is returned when using the Get operation. See Sections 2.1.3, 2.1.7, 3.17,
|
||||
4.11, and 9.1.3.2.3 of the KMIP 1.1 specification for more information.
|
||||
"""
|
||||
ENUM_TYPE = KeyFormatTypeEnum
|
||||
|
||||
def __init__(self, value=KeyFormatTypeEnum.RAW):
|
||||
"""
|
||||
Construct a KeyFormatType object.
|
||||
|
||||
Args:
|
||||
value (KeyFormatType): A KeyFormatType enumeration value,
|
||||
(e.g., KeyFormatType.PKCS_1). Optional, default to
|
||||
KeyFormatType.RAW.
|
||||
"""
|
||||
super(KeyFormatType, self).__init__(value, Tags.KEY_FORMAT_TYPE)
|
||||
|
@ -28,6 +28,7 @@ from kmip.core.enums import Types
|
||||
from kmip.core.enums import CredentialType
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
from kmip.core.misc import KeyFormatType
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import TextString
|
||||
@ -343,12 +344,6 @@ class Credential(Struct):
|
||||
# 2.1.3
|
||||
class KeyBlock(Struct):
|
||||
|
||||
class KeyFormatType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyFormatType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_FORMAT_TYPE)
|
||||
|
||||
class KeyCompressionType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyCompressionType
|
||||
|
||||
@ -376,7 +371,7 @@ class KeyBlock(Struct):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.key_format_type = KeyBlock.KeyFormatType()
|
||||
self.key_format_type = KeyFormatType()
|
||||
self.key_format_type.read(tstream)
|
||||
key_format_type = self.key_format_type.enum
|
||||
|
||||
@ -429,9 +424,9 @@ class KeyBlock(Struct):
|
||||
|
||||
def __validate(self):
|
||||
if self.key_format_type is not None:
|
||||
if type(self.key_format_type) is not KeyBlock.KeyFormatType:
|
||||
if type(self.key_format_type) is not KeyFormatType:
|
||||
member = 'KeyBlock.key_format_type'
|
||||
exp_type = KeyBlock.KeyFormatType
|
||||
exp_type = KeyFormatType
|
||||
rcv_type = type(self.key_format_type)
|
||||
msg = ErrorStrings.BAD_EXP_RECV.format(member, 'type',
|
||||
exp_type, rcv_type)
|
||||
|
@ -417,7 +417,7 @@ class Enumeration(Integer):
|
||||
Enum, type(self.enum)))
|
||||
|
||||
def __repr__(self):
|
||||
return "Enumeration(value={0})".format(self.enum)
|
||||
return "{0}(value={1})".format(type(self).__name__, self.enum)
|
||||
|
||||
def __str__(self):
|
||||
return "{0} - {1} - {2}".format(
|
||||
@ -570,7 +570,10 @@ class TextString(Base):
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
if isinstance(other, TextString):
|
||||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class ByteString(Base):
|
||||
@ -579,7 +582,11 @@ class ByteString(Base):
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(ByteString, self).__init__(tag, type=Types.BYTE_STRING)
|
||||
self.value = value
|
||||
|
||||
if value is None:
|
||||
self.value = bytes()
|
||||
else:
|
||||
self.value = bytes(value)
|
||||
|
||||
self.validate()
|
||||
|
||||
@ -595,9 +602,10 @@ class ByteString(Base):
|
||||
|
||||
def read_value(self, istream):
|
||||
# Read bytes into bytearray
|
||||
self.value = bytearray()
|
||||
data = bytearray()
|
||||
for _ in range(self.length):
|
||||
self.value.append(istream.read(1)[0])
|
||||
data.append(istream.read(1)[0])
|
||||
self.value = bytes(data)
|
||||
|
||||
# Read padding and check content
|
||||
self.padding_length = self.PADDING_SIZE - (self.length %
|
||||
@ -618,7 +626,8 @@ class ByteString(Base):
|
||||
|
||||
def write_value(self, ostream):
|
||||
# Write bytes to stream
|
||||
for byte in self.value:
|
||||
data = bytearray(self.value)
|
||||
for byte in data:
|
||||
ostream.write(pack(self.BYTE_FORMAT, byte))
|
||||
|
||||
# Write padding to stream
|
||||
@ -633,15 +642,31 @@ class ByteString(Base):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Test is pointless, value is always bytes. Fix.
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type is not bytearray:
|
||||
if data_type is not bytes:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format('ByteString', 'value', bytearray,
|
||||
raise TypeError(msg.format('ByteString', 'value', bytes,
|
||||
data_type))
|
||||
|
||||
def __repr__(self):
|
||||
return '<Integer, %s>' % (self.value)
|
||||
return "{0}(value={1})".format(type(self).__name__, repr(self.value))
|
||||
|
||||
def __str__(self):
|
||||
return "{0}".format(str(self.value))
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, ByteString):
|
||||
return self.value == other.value
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
if isinstance(other, ByteString):
|
||||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class DateTime(LongInteger):
|
||||
|
@ -31,11 +31,12 @@ 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 KeyFormatType
|
||||
from kmip.core.messages.contents import ResultStatus
|
||||
from kmip.core.messages.contents import ResultReason
|
||||
from kmip.core.messages.contents import ResultMessage
|
||||
|
||||
from kmip.core.misc import KeyFormatType
|
||||
|
||||
from kmip.core.objects import KeyBlock
|
||||
from kmip.core.objects import KeyValue
|
||||
from kmip.core.objects import KeyValueStruct
|
||||
@ -344,7 +345,7 @@ class KMIPImpl(KMIP):
|
||||
return OperationResult(status, reason, message)
|
||||
|
||||
def _gen_symmetric_key(self, bit_length, crypto_alg):
|
||||
key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_material = RawKey(bytearray(os.urandom(int(bit_length/8))))
|
||||
key_value = KeyValueStruct(key_format_type, key_material)
|
||||
crypto_length = CryptographicLength(bit_length)
|
||||
|
@ -17,8 +17,12 @@ from testtools import TestCase
|
||||
|
||||
from kmip.core.attributes import ApplicationData
|
||||
from kmip.core.attributes import ApplicationNamespace
|
||||
from kmip.core.attributes import DigestValue
|
||||
from kmip.core.attributes import HashingAlgorithm
|
||||
from kmip.core.attributes import OperationPolicyName
|
||||
|
||||
from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
@ -90,6 +94,93 @@ class TestOperationPolicyName(TestCase):
|
||||
self._test_operation_policy_name(None)
|
||||
|
||||
|
||||
class TestHashingAlgorithm(TestCase):
|
||||
"""
|
||||
A test suite for the HashingAlgorithm class.
|
||||
|
||||
Since HashingAlgorithm is a simple wrapper for the Enumeration primitive,
|
||||
only a few tests pertaining to construction are needed.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestHashingAlgorithm, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestHashingAlgorithm, self).tearDown()
|
||||
|
||||
def _test_init(self, value):
|
||||
if (isinstance(value, HashingAlgorithmEnum)) or (value is None):
|
||||
hashing_algorithm = HashingAlgorithm(value)
|
||||
|
||||
msg = "expected {0}, observed {1}".format(
|
||||
value, hashing_algorithm.enum)
|
||||
self.assertEqual(value, hashing_algorithm.enum, msg)
|
||||
else:
|
||||
self.assertRaises(TypeError, HashingAlgorithm, value)
|
||||
|
||||
def test_init_with_none(self):
|
||||
"""
|
||||
Test that a HashingAlgorithm object can be constructed with no
|
||||
specified value.
|
||||
"""
|
||||
self._test_init(None)
|
||||
|
||||
def test_init_with_valid(self):
|
||||
"""
|
||||
Test that a HashingAlgorithm object can be constructed with a valid
|
||||
HashingAlgorithm enumeration value.
|
||||
"""
|
||||
self._test_init(HashingAlgorithmEnum.MD5)
|
||||
|
||||
def test_init_with_invalid(self):
|
||||
"""
|
||||
Test that a TypeError exception is raised when a non HashingAlgorithm
|
||||
enumeration value is used to construct a HashingAlgorithm object.
|
||||
"""
|
||||
self._test_init("invalid")
|
||||
|
||||
|
||||
class TestDigestValue(TestCase):
|
||||
"""
|
||||
A test suite for the DigestValue class.
|
||||
|
||||
Since DigestValue is a simple wrapper for the ByteString primitive, only
|
||||
a few tests pertaining to construction are needed.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestDigestValue, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestDigestValue, self).tearDown()
|
||||
|
||||
def _test_init(self, value):
|
||||
if (isinstance(value, bytes)) or (value is None):
|
||||
digest_value = DigestValue(value)
|
||||
|
||||
if value is None:
|
||||
value = bytes()
|
||||
|
||||
msg = "expected {0}, observed {1}".format(
|
||||
value, digest_value.value)
|
||||
self.assertEqual(value, digest_value.value, msg)
|
||||
else:
|
||||
self.assertRaises(TypeError, DigestValue, value)
|
||||
|
||||
def test_init_with_none(self):
|
||||
"""
|
||||
Test that a DigestValue object can be constructed with no specified
|
||||
value.
|
||||
"""
|
||||
self._test_init(None)
|
||||
|
||||
def test_init_with_valid(self):
|
||||
"""
|
||||
Test that a DigestValue object can be constructed with valid byte data.
|
||||
"""
|
||||
self._test_init(b'\x00\x01\x02\x03')
|
||||
|
||||
|
||||
class TestApplicationNamespace(TestCase):
|
||||
"""
|
||||
A test suite for the ApplicationNamespace class.
|
||||
|
451
kmip/tests/core/attributes/test_digest.py
Normal file
451
kmip/tests/core/attributes/test_digest.py
Normal file
@ -0,0 +1,451 @@
|
||||
# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from testtools import TestCase
|
||||
|
||||
from kmip.core.attributes import Digest
|
||||
from kmip.core.attributes import DigestValue
|
||||
from kmip.core.attributes import HashingAlgorithm
|
||||
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum
|
||||
|
||||
from kmip.core.objects import KeyFormatType
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class TestDigest(TestCase):
|
||||
"""
|
||||
A test suite for the Digest class.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestDigest, self).setUp()
|
||||
|
||||
self.hashing_algorithm_a = HashingAlgorithm(
|
||||
HashingAlgorithmEnum.SHA_256)
|
||||
self.hashing_algorithm_b = HashingAlgorithm(
|
||||
HashingAlgorithmEnum.SHA_256)
|
||||
self.hashing_algorithm_c = HashingAlgorithm(
|
||||
HashingAlgorithmEnum.SHA_256)
|
||||
|
||||
self.digest_value_a = DigestValue(b'')
|
||||
self.digest_value_b = DigestValue(
|
||||
b'\x6C\x06\x4F\xE0\x51\xAD\xD1\x1E\xDC\x07\x72\x7B\x59\x4E\xB4\x87'
|
||||
b'\x11\xDF\x84\x3E\x08\x44\x5B\xBA\x2C\xD7\x86\xBC\x16\xBC\x58'
|
||||
b'\xE8')
|
||||
self.digest_value_c = DigestValue(
|
||||
b'\x11\x11\x0A\x01\xED\x45\x89\xD9\x98\x7C\x9A\xD6\x03\x68\xE2\xB7'
|
||||
b'\x62\xF2\xB2\x0C\x00\x94\x6E\x19\x32\xC1\x60\x5A\x18\x17\x2F'
|
||||
b'\x55')
|
||||
|
||||
self.key_format_type_a = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
self.key_format_type_b = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
self.key_format_type_c = KeyFormatType(KeyFormatTypeEnum.PKCS_1)
|
||||
|
||||
# Encodings obtained from Section 18.1 and 18.2 of the KMIP 1.1 Test
|
||||
# Cases document.
|
||||
self.encoding_a = BytearrayStream((
|
||||
b'\x42\x00\x34\x01\x00\x00\x00\x28\x42\x00\x38\x05\x00\x00\x00\x04'
|
||||
b'\x00\x00\x00\x06\x00\x00\x00\x00\x42\x00\x35\x08\x00\x00\x00\x00'
|
||||
b'\x42\x00\x42\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00'
|
||||
b'\x00'))
|
||||
self.encoding_b = BytearrayStream((
|
||||
b'\x42\x00\x34\x01\x00\x00\x00\x48\x42\x00\x38\x05\x00\x00\x00\x04'
|
||||
b'\x00\x00\x00\x06\x00\x00\x00\x00\x42\x00\x35\x08\x00\x00\x00\x20'
|
||||
b'\x6C\x06\x4F\xE0\x51\xAD\xD1\x1E\xDC\x07\x72\x7B\x59\x4E\xB4\x87'
|
||||
b'\x11\xDF\x84\x3E\x08\x44\x5B\xBA\x2C\xD7\x86\xBC\x16\xBC\x58\xE8'
|
||||
b'\x42\x00\x42\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00'
|
||||
b'\x00'))
|
||||
self.encoding_c = BytearrayStream((
|
||||
b'\x42\x00\x34\x01\x00\x00\x00\x48\x42\x00\x38\x05\x00\x00\x00\x04'
|
||||
b'\x00\x00\x00\x06\x00\x00\x00\x00\x42\x00\x35\x08\x00\x00\x00\x20'
|
||||
b'\x11\x11\x0A\x01\xED\x45\x89\xD9\x98\x7C\x9A\xD6\x03\x68\xE2\xB7'
|
||||
b'\x62\xF2\xB2\x0C\x00\x94\x6E\x19\x32\xC1\x60\x5A\x18\x17\x2F\x55'
|
||||
b'\x42\x00\x42\x05\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00'
|
||||
b'\x00'))
|
||||
|
||||
def tearDown(self):
|
||||
super(TestDigest, self).tearDown()
|
||||
|
||||
def test_init_with_none(self):
|
||||
"""
|
||||
Test that a Digest object can be constructed with no specified values.
|
||||
"""
|
||||
Digest()
|
||||
|
||||
def test_init_with_args(self):
|
||||
"""
|
||||
Test that a Digest object can be constructed with valid values.
|
||||
"""
|
||||
Digest(hashing_algorithm=HashingAlgorithm(),
|
||||
digest_value=DigestValue(),
|
||||
key_format_type=KeyFormatType())
|
||||
|
||||
def test_validate_with_invalid_hashing_algorithm(self):
|
||||
"""
|
||||
Test that a TypeError exception is raised when an invalid
|
||||
HashingAlgorithm is used to construct a Digest object.
|
||||
"""
|
||||
hashing_algorithm = "invalid"
|
||||
kwargs = {'hashing_algorithm': hashing_algorithm}
|
||||
|
||||
self.assertRaisesRegexp(
|
||||
TypeError, "invalid hashing algorithm", Digest, **kwargs)
|
||||
|
||||
def test_validate_with_invalid_digest_value(self):
|
||||
"""
|
||||
Test that a TypeError exception is raised when an invalid DigestValue
|
||||
is used to construct a Digest object.
|
||||
"""
|
||||
digest_value = "invalid"
|
||||
kwargs = {'digest_value': digest_value}
|
||||
|
||||
self.assertRaisesRegexp(
|
||||
TypeError, "invalid digest value", Digest, **kwargs)
|
||||
|
||||
def test_validate_with_invalid_key_format_type(self):
|
||||
"""
|
||||
Test that a TypeError exception is raised when an invalid
|
||||
KeyFormatType is used to construct a Digeest object.
|
||||
"""
|
||||
key_format_type = "invalid"
|
||||
kwargs = {'key_format_type': key_format_type}
|
||||
|
||||
self.assertRaisesRegexp(
|
||||
TypeError, "invalid key format type", Digest, **kwargs)
|
||||
|
||||
def _test_read(self, stream, hashing_algorithm, digest_value,
|
||||
key_format_type):
|
||||
digest = Digest()
|
||||
digest.read(stream)
|
||||
|
||||
msg = "hashing algorithm encoding mismatch"
|
||||
msg += "; expected {0}, observed {1}".format(
|
||||
hashing_algorithm,
|
||||
digest.hashing_algorithm)
|
||||
self.assertEqual(
|
||||
hashing_algorithm,
|
||||
digest.hashing_algorithm, msg)
|
||||
|
||||
msg = "digest value encoding mismatch"
|
||||
msg += "; expected {0}, observed {1}".format(
|
||||
digest_value,
|
||||
digest.digest_value)
|
||||
self.assertEqual(
|
||||
digest_value,
|
||||
digest.digest_value, msg)
|
||||
|
||||
msg = "key format type encoding mismatch"
|
||||
msg += "; expected {0}, observed {1}".format(
|
||||
key_format_type,
|
||||
digest.key_format_type)
|
||||
self.assertEqual(
|
||||
key_format_type,
|
||||
digest.key_format_type, msg)
|
||||
|
||||
def test_read_a(self):
|
||||
"""
|
||||
Test that a Digest object with some data can be read from a data
|
||||
stream.
|
||||
"""
|
||||
self._test_read(self.encoding_a, self.hashing_algorithm_a,
|
||||
self.digest_value_a, self.key_format_type_a)
|
||||
|
||||
def test_read_b(self):
|
||||
"""
|
||||
Test that a Digest object with data can be read from a data stream.
|
||||
"""
|
||||
self._test_read(self.encoding_b, self.hashing_algorithm_b,
|
||||
self.digest_value_b, self.key_format_type_b)
|
||||
|
||||
def test_read_c(self):
|
||||
"""
|
||||
Test that a Digest object with data can be read from a data stream.
|
||||
"""
|
||||
self._test_read(self.encoding_c, self.hashing_algorithm_c,
|
||||
self.digest_value_c, self.key_format_type_c)
|
||||
|
||||
def _test_write(self, stream_expected, hashing_algorithm, digest_value,
|
||||
key_format_type):
|
||||
stream_observed = BytearrayStream()
|
||||
digest = Digest(
|
||||
hashing_algorithm=hashing_algorithm,
|
||||
digest_value=digest_value,
|
||||
key_format_type=key_format_type)
|
||||
digest.write(stream_observed)
|
||||
|
||||
length_expected = len(stream_expected)
|
||||
length_observed = len(stream_observed)
|
||||
|
||||
msg = "encoding lengths not equal"
|
||||
msg += "; expected {0}, observed {1}".format(
|
||||
length_expected, length_observed)
|
||||
self.assertEqual(length_expected, length_observed, msg)
|
||||
|
||||
msg = "encoding mismatch"
|
||||
msg += ";\nexpected:\n{0}\nobserved:\n{1}".format(
|
||||
stream_expected, stream_observed)
|
||||
self.assertEqual(stream_expected, stream_observed, msg)
|
||||
|
||||
def test_write_a(self):
|
||||
"""
|
||||
Test that a Digest object with some data can be written to a data
|
||||
stream.
|
||||
"""
|
||||
self._test_write(self.encoding_a, self.hashing_algorithm_a,
|
||||
self.digest_value_a, self.key_format_type_a)
|
||||
|
||||
def test_write_b(self):
|
||||
"""
|
||||
Test that a Digest object with data can be written to a data stream.
|
||||
"""
|
||||
self._test_write(self.encoding_b, self.hashing_algorithm_b,
|
||||
self.digest_value_b, self.key_format_type_b)
|
||||
|
||||
def test_write_c(self):
|
||||
"""
|
||||
Test that a Digest object with data can be written to a data stream.
|
||||
"""
|
||||
self._test_write(self.encoding_c, self.hashing_algorithm_c,
|
||||
self.digest_value_c, self.key_format_type_c)
|
||||
|
||||
def test_equal_on_equal(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing two Digest
|
||||
objects with the same internal data.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
|
||||
self.assertTrue(a == b)
|
||||
self.assertTrue(b == a)
|
||||
|
||||
def test_equal_on_equal_and_empty(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing two Digest
|
||||
objects with no internal data.
|
||||
"""
|
||||
a = Digest()
|
||||
b = Digest()
|
||||
|
||||
self.assertTrue(a == b)
|
||||
self.assertTrue(b == a)
|
||||
|
||||
def test_equal_on_not_equal(self):
|
||||
"""
|
||||
Test that the equality operator returns False when comparing two
|
||||
Digest objects with different sets of internal data.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = Digest()
|
||||
|
||||
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 Digest
|
||||
object with a non-Digest object.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = "invalid"
|
||||
|
||||
self.assertFalse(a == b)
|
||||
self.assertFalse(b == a)
|
||||
|
||||
def test_not_equal_on_equal(self):
|
||||
"""
|
||||
Test that the inequality operator returns False when comparing two
|
||||
Digest objects with the same internal data.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
|
||||
self.assertFalse(a != b)
|
||||
self.assertFalse(b != a)
|
||||
|
||||
def test_not_equal_on_equal_and_empty(self):
|
||||
"""
|
||||
Test that the inequality operator returns False when comparing two
|
||||
Digest objects with no internal data.
|
||||
"""
|
||||
a = Digest()
|
||||
b = Digest()
|
||||
|
||||
self.assertFalse(a != b)
|
||||
self.assertFalse(b != a)
|
||||
|
||||
def test_not_equal_on_not_equal(self):
|
||||
"""
|
||||
Test that the inequality operator returns True when comparing two
|
||||
Digest objects with the different sets of internal data.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = Digest()
|
||||
|
||||
self.assertTrue(a != b)
|
||||
self.assertTrue(b != a)
|
||||
|
||||
def test_not_equal_on_type_mismatch(self):
|
||||
"""
|
||||
Test that the inequality operator returns True when comparing an
|
||||
Digest object with a non-ExtensionInformation object.
|
||||
"""
|
||||
a = Digest(
|
||||
hashing_algorithm=self.hashing_algorithm_b,
|
||||
digest_value=self.digest_value_b,
|
||||
key_format_type=self.key_format_type_b)
|
||||
b = "invalid"
|
||||
|
||||
self.assertTrue(a != b)
|
||||
self.assertTrue(b != a)
|
||||
|
||||
def test_repr(self):
|
||||
"""
|
||||
Test that the representation of a Digest object with data is formatted
|
||||
properly and can be used by eval to create a new Digest object
|
||||
identical to the original.
|
||||
"""
|
||||
digest = Digest(
|
||||
hashing_algorithm=HashingAlgorithm(HashingAlgorithmEnum.MD5),
|
||||
digest_value=DigestValue(b'\x00\x01\x02\x03'),
|
||||
key_format_type=KeyFormatType(KeyFormatTypeEnum.RAW))
|
||||
byte_value = b'\x00\x01\x02\x03'
|
||||
|
||||
expected = "Digest("
|
||||
expected += "hashing_algorithm=HashingAlgorithm("
|
||||
expected += "value=HashingAlgorithm.MD5), "
|
||||
expected += "digest_value=DigestValue("
|
||||
expected += "value={0}), ".format(repr(byte_value))
|
||||
expected += "key_format_type=KeyFormatType("
|
||||
expected += "value=KeyFormatType.RAW))"
|
||||
observed = repr(digest)
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
# Instead of using eval(repr(digest)), we need to use a manual string,
|
||||
# eval(manual), due to the name collisions of the HashingAlgorithm
|
||||
# and KeyFormatType objects and enumerations.
|
||||
manual = "Digest("
|
||||
manual += "hashing_algorithm=HashingAlgorithm("
|
||||
manual += "value=HashingAlgorithmEnum.MD5), "
|
||||
manual += "digest_value=DigestValue("
|
||||
manual += "value={0}), ".format(repr(byte_value))
|
||||
manual += "key_format_type=KeyFormatType("
|
||||
manual += "value=KeyFormatTypeEnum.RAW))"
|
||||
|
||||
expected = digest
|
||||
observed = eval(manual)
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
def _test_str(self, value, expected):
|
||||
digest = Digest(digest_value=value)
|
||||
|
||||
observed = str(digest)
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
def test_str_with_no_data(self):
|
||||
"""
|
||||
Test that the string representation of a Digest object is formatted
|
||||
properly when there is no internal data.
|
||||
"""
|
||||
data = b''
|
||||
digest_value = DigestValue(data)
|
||||
self._test_str(digest_value, str(data))
|
||||
|
||||
def test_str_with_data(self):
|
||||
"""
|
||||
Test that the string representation of a Digest object is formatted
|
||||
properly when there is internal data.
|
||||
"""
|
||||
data = b'\x00\x01\x02\x03'
|
||||
digest_value = DigestValue(data)
|
||||
self._test_str(digest_value, str(data))
|
||||
|
||||
def _test_create(self, digest, hashing_algorithm, digest_value,
|
||||
key_format_type):
|
||||
self.assertIsInstance(digest, Digest)
|
||||
|
||||
expected = HashingAlgorithm(hashing_algorithm)
|
||||
observed = digest.hashing_algorithm
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
expected = DigestValue(digest_value)
|
||||
observed = digest.digest_value
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
expected = KeyFormatType(key_format_type)
|
||||
observed = digest.key_format_type
|
||||
|
||||
msg = "expected {0}, observed {1}".format(expected, observed)
|
||||
self.assertEqual(expected, observed, msg)
|
||||
|
||||
def test_create_with_defaults(self):
|
||||
"""
|
||||
Test that a Digest object can be built using the create class method
|
||||
with no arguments.
|
||||
"""
|
||||
digest = Digest.create()
|
||||
hashing_algorithm = HashingAlgorithmEnum.SHA_256
|
||||
digest_value = b''
|
||||
key_format_type = KeyFormatTypeEnum.RAW
|
||||
|
||||
self._test_create(digest, hashing_algorithm, digest_value,
|
||||
key_format_type)
|
||||
|
||||
def test_create_with_args(self):
|
||||
"""
|
||||
Test that a Digest object can be built using the create class method
|
||||
with arguments.
|
||||
"""
|
||||
hashing_algorithm = HashingAlgorithmEnum.MD5
|
||||
digest_value = b'\x00\x01\x02\x03'
|
||||
key_format_type = KeyFormatTypeEnum.PKCS_1
|
||||
digest = Digest.create(hashing_algorithm, digest_value,
|
||||
key_format_type)
|
||||
|
||||
self._test_create(digest, hashing_algorithm, digest_value,
|
||||
key_format_type)
|
@ -43,13 +43,13 @@ 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
|
||||
from kmip.core.messages.payloads import get
|
||||
from kmip.core.messages.payloads import register
|
||||
from kmip.core.messages.payloads import locate
|
||||
from kmip.core.messages.payloads import destroy
|
||||
|
||||
from kmip.core.misc import KeyFormatType
|
||||
from kmip.core.primitives import TextString
|
||||
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
@ -1329,7 +1329,7 @@ class TestResponseMessage(TestCase):
|
||||
type(key_block)))
|
||||
|
||||
key_format_type = key_block.key_format_type
|
||||
exp_type = objects.KeyBlock.KeyFormatType
|
||||
exp_type = KeyFormatType
|
||||
rcv_type = type(key_format_type)
|
||||
self.assertIsInstance(key_format_type, exp_type,
|
||||
self.msg.format('key_format_type', 'type',
|
||||
|
@ -16,8 +16,10 @@
|
||||
from six import string_types
|
||||
from testtools import TestCase
|
||||
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import QueryFunction as QueryFunctionEnum
|
||||
|
||||
from kmip.core.misc import KeyFormatType
|
||||
from kmip.core.misc import QueryFunction
|
||||
from kmip.core.misc import VendorIdentification
|
||||
|
||||
@ -115,3 +117,49 @@ class TestVendorIdentification(TestCase):
|
||||
used to construct a VendorIdentification object.
|
||||
"""
|
||||
self._test_init(0)
|
||||
|
||||
|
||||
class TestKeyFormatType(TestCase):
|
||||
"""
|
||||
A test suite for the KeyFormatType class.
|
||||
|
||||
Since KeyFormatType is a simple wrapper for the Enumeration primitive,
|
||||
only a few tests pertaining to construction are needed.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestKeyFormatType, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestKeyFormatType, self).tearDown()
|
||||
|
||||
def _test_init(self, value):
|
||||
if (isinstance(value, KeyFormatTypeEnum)) or (value is None):
|
||||
key_format_type = KeyFormatType(value)
|
||||
|
||||
msg = "expected {0}, observed {1}".format(
|
||||
value, key_format_type.enum)
|
||||
self.assertEqual(value, key_format_type.enum, msg)
|
||||
else:
|
||||
self.assertRaises(TypeError, KeyFormatType, value)
|
||||
|
||||
def test_init_with_none(self):
|
||||
"""
|
||||
Test that a KeyFormatType object can be constructed with no specified
|
||||
value.
|
||||
"""
|
||||
self._test_init(None)
|
||||
|
||||
def test_init_with_valid(self):
|
||||
"""
|
||||
Test that a KeyFormatType object can be constructed with a valid
|
||||
KeyFormatType enumeration value.
|
||||
"""
|
||||
self._test_init(KeyFormatTypeEnum.RAW)
|
||||
|
||||
def test_init_with_invalid(self):
|
||||
"""
|
||||
Test that a TypeError exception is raised when a non KeyFormatType
|
||||
enumeration value is used to construct a KeyFormatType object.
|
||||
"""
|
||||
self._test_init("invalid")
|
||||
|
@ -1151,11 +1151,11 @@ class TestByteString(TestCase):
|
||||
super(self.__class__, self).tearDown()
|
||||
|
||||
def test_init(self):
|
||||
value = bytearray(b'\x01\x02\x03')
|
||||
value = b'\x01\x02\x03'
|
||||
bs = ByteString(value)
|
||||
|
||||
self.assertIsInstance(bs.value, bytearray,
|
||||
self.bad_type.format('value', bytearray,
|
||||
self.assertIsInstance(bs.value, bytes,
|
||||
self.bad_type.format('value', bytes,
|
||||
type(bs.value)))
|
||||
self.assertEqual(value, bs.value,
|
||||
self.bad_value.format('value', value, bs.value))
|
||||
@ -1163,15 +1163,15 @@ class TestByteString(TestCase):
|
||||
def test_init_unset(self):
|
||||
bs = ByteString()
|
||||
|
||||
self.assertIsInstance(bs.value, type(None),
|
||||
self.assertIsInstance(bs.value, bytes,
|
||||
self.bad_type.format('value', type(None),
|
||||
type(bs.value)))
|
||||
self.assertEqual(None, bs.value,
|
||||
self.assertEqual(bytes(), bs.value,
|
||||
self.bad_value.format('value', None, bs.value))
|
||||
|
||||
def test_validate_on_valid(self):
|
||||
bs = ByteString()
|
||||
bs.value = bytearray(b'\x00')
|
||||
bs.value = b'\x00'
|
||||
|
||||
# Check no exception thrown.
|
||||
bs.validate()
|
||||
@ -1189,7 +1189,7 @@ class TestByteString(TestCase):
|
||||
self.assertRaises(TypeError, bs.validate)
|
||||
|
||||
def test_read_value(self):
|
||||
encoding = (b'\x01\x02\x03\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x01\x02\x03\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream(encoding)
|
||||
bs = ByteString()
|
||||
bs.length = 0x03
|
||||
@ -1200,7 +1200,7 @@ class TestByteString(TestCase):
|
||||
self.bad_read.format('value', expected, bs.value))
|
||||
|
||||
def test_read_value_no_padding(self):
|
||||
encoding = (b'\x01\x02\x03\x04\x05\x06\x07\x08')
|
||||
encoding = b'\x01\x02\x03\x04\x05\x06\x07\x08'
|
||||
self.stream = BytearrayStream(encoding)
|
||||
bs = ByteString()
|
||||
bs.length = 0x08
|
||||
@ -1211,24 +1211,24 @@ class TestByteString(TestCase):
|
||||
self.bad_read.format('value', expected, bs.value))
|
||||
|
||||
def test_read_value_max_padding(self):
|
||||
encoding = (b'\x01\x00\x00\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x01\x00\x00\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream(encoding)
|
||||
bs = ByteString()
|
||||
bs.length = 0x01
|
||||
bs.read_value(self.stream)
|
||||
|
||||
expected = bytearray(b'\x01')
|
||||
expected = b'\x01'
|
||||
self.assertEqual(expected, bs.value,
|
||||
self.bad_read.format('value', expected, bs.value))
|
||||
|
||||
def test_read_value_zero(self):
|
||||
encoding = (b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream(encoding)
|
||||
bs = ByteString()
|
||||
bs.length = 0x01
|
||||
bs.read_value(self.stream)
|
||||
|
||||
expected = bytearray(b'\x00')
|
||||
expected = b'\x00'
|
||||
self.assertEqual(expected, bs.value,
|
||||
self.bad_read.format('value', expected, bs.value))
|
||||
|
||||
@ -1239,7 +1239,7 @@ class TestByteString(TestCase):
|
||||
bs = ByteString()
|
||||
bs.read(self.stream)
|
||||
|
||||
expected = bytearray(b'\x01\x02\x03')
|
||||
expected = b'\x01\x02\x03'
|
||||
self.assertEqual(expected, bs.value,
|
||||
self.bad_read.format('value', expected, bs.value))
|
||||
|
||||
@ -1252,9 +1252,9 @@ class TestByteString(TestCase):
|
||||
self.assertRaises(errors.ReadValueError, bs.read, self.stream)
|
||||
|
||||
def test_write_value(self):
|
||||
encoding = (b'\x01\x02\x03\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x01\x02\x03\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream()
|
||||
value = bytearray(b'\x01\x02\x03')
|
||||
value = b'\x01\x02\x03'
|
||||
bs = ByteString(value)
|
||||
bs.write_value(self.stream)
|
||||
|
||||
@ -1267,9 +1267,9 @@ class TestByteString(TestCase):
|
||||
self.assertEqual(encoding, result, self.bad_encoding)
|
||||
|
||||
def test_write_value_no_padding(self):
|
||||
encoding = (b'\x01\x02\x03\x04\x05\x06\x07\x08')
|
||||
encoding = b'\x01\x02\x03\x04\x05\x06\x07\x08'
|
||||
self.stream = BytearrayStream()
|
||||
value = bytearray(b'\x01\x02\x03\x04\x05\x06\x07\x08')
|
||||
value = b'\x01\x02\x03\x04\x05\x06\x07\x08'
|
||||
bs = ByteString(value)
|
||||
bs.write_value(self.stream)
|
||||
|
||||
@ -1282,9 +1282,9 @@ class TestByteString(TestCase):
|
||||
self.assertEqual(encoding, result, self.bad_encoding)
|
||||
|
||||
def test_write_value_max_padding(self):
|
||||
encoding = (b'\x01\x00\x00\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x01\x00\x00\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream()
|
||||
value = bytearray(b'\x01')
|
||||
value = b'\x01'
|
||||
bs = ByteString(value)
|
||||
bs.write_value(self.stream)
|
||||
|
||||
@ -1297,9 +1297,9 @@ class TestByteString(TestCase):
|
||||
self.assertEqual(encoding, result, self.bad_encoding)
|
||||
|
||||
def test_write_value_zero(self):
|
||||
encoding = (b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
encoding = b'\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
self.stream = BytearrayStream()
|
||||
value = bytearray(b'\x00')
|
||||
value = b'\x00'
|
||||
bs = ByteString(value)
|
||||
bs.write_value(self.stream)
|
||||
|
||||
@ -1315,7 +1315,7 @@ class TestByteString(TestCase):
|
||||
encoding = (b'\x42\x00\x00\x08\x00\x00\x00\x03\x01\x02\x03\x00\x00\x00'
|
||||
b'\x00\x00')
|
||||
self.stream = BytearrayStream()
|
||||
value = bytearray(b'\x01\x02\x03')
|
||||
value = b'\x01\x02\x03'
|
||||
bs = ByteString(value)
|
||||
bs.write(self.stream)
|
||||
|
||||
|
@ -21,6 +21,7 @@ from kmip.core.attributes import CryptographicUsageMask
|
||||
from kmip.core.attributes import UniqueIdentifier
|
||||
from kmip.core.attributes import ObjectType
|
||||
from kmip.core.attributes import Name
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum
|
||||
from kmip.core.enums import CryptographicUsageMask as CryptoUsageMaskEnum
|
||||
@ -30,13 +31,17 @@ from kmip.core.enums import ObjectType as ObjectTypeEnum
|
||||
from kmip.core.enums import ResultReason
|
||||
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.messages.contents import KeyFormatType
|
||||
from kmip.core.misc import KeyFormatType
|
||||
|
||||
from kmip.core.objects import KeyBlock
|
||||
from kmip.core.objects import KeyValueStruct
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
from kmip.core.server import KMIPImpl
|
||||
|
||||
@ -466,7 +471,7 @@ class TestKMIPServer(TestCase):
|
||||
def _get_symmetric_key(self):
|
||||
# only need usage attribute
|
||||
attrs = [self._get_attrs()[1]]
|
||||
key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_material = RawKey(self.key)
|
||||
key_value = KeyValueStruct(key_format_type, key_material, attrs)
|
||||
crypto_alg = CryptographicAlgorithm(self.algorithm_name)
|
||||
|
Loading…
x
Reference in New Issue
Block a user