Merge pull request #11 from OpenKMIP/feat/add-certificate

Adding support for the Certificate managed object
This commit is contained in:
Peter Hamilton 2015-05-07 09:57:26 -04:00
commit 55e2996b91
10 changed files with 607 additions and 31 deletions

View File

@ -15,6 +15,7 @@
from kmip.core import enums
from kmip.core.enums import CertificateTypeEnum
from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
from kmip.core.enums import Tags
@ -283,16 +284,28 @@ class CryptographicParameters(Struct):
pass
# 3.8
class CertificateType(Enumeration):
ENUM_TYPE = enums.CertificateType
"""
An encodeable wrapper for the CertificateType enumeration.
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CERTIFICATE_TYPE)
Used to specify the type of the encoded bytes of a Certificate Managed
Object. See Sections 2.2.1 and 3.8 of the KMIP v1.1 specification for more
information.
"""
ENUM_TYPE = enums.CertificateTypeEnum
def __init__(self, value=CertificateTypeEnum.X_509):
"""
Construct a CertificateType object.
Args:
value (CertificateTypeEnum): A CertificateTypeEnum enumeration
value, (e.g., CertificateTypeEnum.PGP). Optional, defaults to
CertificateTypeEnum.X_509.
"""
super(CertificateType, self).__init__(value, Tags.CERTIFICATE_TYPE)
# 3.17
class DigestValue(ByteString):
"""
A byte string representing the hash value of a Digest.

View File

@ -349,7 +349,12 @@ class WrappingMethod(Enum):
# 9.1.3.2.6
class CertificateType(Enum):
class CertificateTypeEnum(Enum):
"""
The type of a Certificate Managed Object.
For more information, see Section 2.2.1 of the KMIP 1.1 specification.
"""
X_509 = 0x00000001
PGP = 0x00000002

View File

@ -28,6 +28,7 @@ from kmip.core.objects import KeyMaterial
from kmip.core.objects import KeyWrappingData
from kmip.core.objects import KeyValue
from kmip.core.secrets import Certificate
from kmip.core.secrets import OpaqueObject
from kmip.core.secrets import PrivateKey
from kmip.core.secrets import PublicKey
@ -68,7 +69,7 @@ class SecretFactory(object):
SymmetricKey(...)
"""
if secret_type is ObjectType.CERTIFICATE:
return self._create_certificate(value)
return self._create_certificate()
elif secret_type is ObjectType.SYMMETRIC_KEY:
return self._create_symmetric_key(value)
elif secret_type is ObjectType.PUBLIC_KEY:
@ -87,8 +88,8 @@ class SecretFactory(object):
raise TypeError("Unrecognized secret type: {0}".format(
secret_type))
def _create_certificate(self, value):
raise NotImplementedError()
def _create_certificate(self):
return Certificate()
def _create_symmetric_key(self, value):
if value is None:

View File

@ -17,6 +17,7 @@ from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
from kmip.core.enums import Tags
from kmip.core.enums import QueryFunction as QueryFunctionEnum
from kmip.core.primitives import ByteString
from kmip.core.primitives import Enumeration
from kmip.core.primitives import Interval
from kmip.core.primitives import Struct
@ -25,6 +26,27 @@ from kmip.core.primitives import TextString
from kmip.core.utils import BytearrayStream
class CertificateValue(ByteString):
"""
The bytes of a DER-encoded X.509 public key certificate.
Used by the Certificate Managed Object to store the bytes of the
certificate. See Section 2.2.1 of the KMIP 1.1. specification for more
information.
"""
def __init__(self, value=b''):
"""
Construct a CertificateValue byte string.
Args:
value (bytes): A byte string (e.g., b'\x00\x01...') containing the
certificate bytes to store. Optional, defaults to the empty
byte string.
"""
super(CertificateValue, self).__init__(value, Tags.CERTIFICATE_VALUE)
class Offset(Interval):
"""
An integer representing a positive change in time.

View File

@ -420,8 +420,7 @@ class Enumeration(Integer):
return "{0}(value={1})".format(type(self).__name__, self.enum)
def __str__(self):
return "{0} - {1} - {2}".format(
type(self.enum), self.enum.name, self.enum.value)
return "{0}.{1}".format(type(self.enum).__name__, self.enum.name)
class Boolean(Base):

View File

@ -18,6 +18,8 @@ from kmip.core.attributes import CertificateType
from kmip.core import enums
from kmip.core.enums import Tags
from kmip.core.misc import CertificateValue
from kmip.core.objects import Attribute
from kmip.core.objects import KeyBlock
@ -33,52 +35,102 @@ from kmip.core.utils import BytearrayStream
# 2.2
# 2.2.1
class Certificate(Struct):
"""
A structure representing a DER-encoded X.509 public key certificate.
class CertificateValue(ByteString):
See Section 2.2.1 of the KMIP 1.1 specification for more information.
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CERTIFICATE_VALUE)
Attributes:
certificate_type: The type of the certificate.
certificate_value: The bytes of the certificate.
"""
def __init__(self,
certificate_type=None,
certificate_value=None):
super(self.__class__, self).__init__(Tags.CERTIFICATE)
self.certificate_type = certificate_type
self.certificate_value = certificate_value
self.validate()
"""
Construct a Certificate object.
Args:
certificate_type (CertificateTypeEnum): The type of the
certificate. Optional, defaults to None.
certificate_value (bytes): The bytes of the certificate. Optional,
defaults to None.
"""
super(Certificate, self).__init__(Tags.CERTIFICATE)
if certificate_type is None:
self.certificate_type = CertificateType()
else:
self.certificate_type = CertificateType(certificate_type)
if certificate_value is None:
self.certificate_value = CertificateValue()
else:
self.certificate_value = CertificateValue(certificate_value)
def read(self, istream):
super(self.__class__, self).read(istream)
"""
Read the data encoding the Certificate 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(Certificate, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.certificate_type = CertificateType()
self.certificate_value = Certificate.CertificateValue()
self.certificate_value = CertificateValue()
self.certificate_type.read(tstream)
self.certificate_value.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
"""
Write the data encoding the Certificate 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()
# Write the details of the certificate
self.certificate_type.write(tstream)
self.certificate_value.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
super(Certificate, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __eq__(self, other):
if isinstance(other, Certificate):
if self.certificate_type != other.certificate_type:
return False
elif self.certificate_value != other.certificate_value:
return False
else:
return True
else:
return NotImplemented
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
def __ne__(self, other):
if isinstance(other, Certificate):
return not (self == other)
else:
return NotImplemented
def __repr__(self):
return "{0}(certificate_type={1}, certificate_value=b'{2}')".format(
type(self).__name__,
str(self.certificate_type),
str(self.certificate_value))
def __str__(self):
return "{0}".format(str(self.certificate_value))
# 2.2.2

View File

@ -17,10 +17,12 @@ from testtools import TestCase
from kmip.core.attributes import ApplicationData
from kmip.core.attributes import ApplicationNamespace
from kmip.core.attributes import CertificateType
from kmip.core.attributes import DigestValue
from kmip.core.attributes import HashingAlgorithm
from kmip.core.attributes import OperationPolicyName
from kmip.core.enums import CertificateTypeEnum
from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum
from kmip.core.utils import BytearrayStream
@ -140,6 +142,50 @@ class TestHashingAlgorithm(TestCase):
self._test_init("invalid")
# TODO (peter-hamilton) Replace with generic Enumeration subclass test suite.
class TestCertificateType(TestCase):
"""
A test suite for the CertificateType class.
Since CertificateType is a simple wrapper for the Enumeration primitive,
only a few tests pertaining to construction are needed.
"""
def setUp(self):
super(TestCertificateType, self).setUp()
def tearDown(self):
super(TestCertificateType, self).tearDown()
def _test_init(self, value):
if (isinstance(value, CertificateTypeEnum)) or (value is None):
if value is None:
certificate_type = CertificateType()
value = CertificateTypeEnum.X_509
else:
certificate_type = CertificateType(value)
msg = "expected {0}, observed {1}".format(
value, certificate_type.enum)
self.assertEqual(value, certificate_type.enum, msg)
else:
self.assertRaises(TypeError, CertificateType, value)
def test_init_with_none(self):
"""
Test that a CertificateType object can be constructed with no specified
value.
"""
self._test_init(None)
def test_init_with_valid(self):
"""
Test that a CertificateType object can be constructed with valid byte
data.
"""
self._test_init(CertificateTypeEnum.PGP)
class TestDigestValue(TestCase):
"""
A test suite for the DigestValue class.

View File

@ -13,17 +13,63 @@
# License for the specific language governing permissions and limitations
# under the License.
from six import binary_type
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 CertificateValue
from kmip.core.misc import KeyFormatType
from kmip.core.misc import QueryFunction
from kmip.core.misc import VendorIdentification
# TODO (peter-hamilton) Replace with generic ByteString subclass test suite.
class TestCertificateValue(TestCase):
"""
A test suite for the CertificateValue class.
Since CertificateValue is a simple wrapper for the ByteString primitive,
only a few tests pertaining to construction are needed.
"""
def setUp(self):
super(TestCertificateValue, self).setUp()
def tearDown(self):
super(TestCertificateValue, self).tearDown()
def _test_init(self, value):
if (isinstance(value, binary_type)) or (value is None):
certificate_value = CertificateValue(value)
if value is None:
value = b''
msg = "expected {0}, observed {1}".format(
value, certificate_value.value)
self.assertEqual(value, certificate_value.value, msg)
else:
self.assertRaises(TypeError, CertificateValue, value)
def test_init_with_none(self):
"""
Test that a CertificateValue object can be constructed with no
specified value.
"""
self._test_init(None)
def test_init_with_valid(self):
"""
Test that a CertificateValue object can be constructed with a valid,
byte-string value.
"""
self._test_init(b'\x00\x01\x02')
class TestQueryFunction(TestCase):
"""
A test suite for the QueryFunction class.

View File

@ -0,0 +1,14 @@
# 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.

View File

@ -0,0 +1,378 @@
# 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 CertificateType
from kmip.core.enums import CertificateTypeEnum
from kmip.core.misc import CertificateValue
from kmip.core.secrets import Certificate
from kmip.core.utils import BytearrayStream
class TestCertificate(TestCase):
"""
A test suite for the Certificate class.
"""
def setUp(self):
super(TestCertificate, self).setUp()
self.certificate_type_a = None
self.certificate_type_b = CertificateTypeEnum.X_509
# Encodings obtained from Section 13.2 of KMIP 1.1 Test Cases document.
self.certificate_value_a = None
self.certificate_value_b = (
b'\x30\x82\x03\x12\x30\x82\x01\xFA\xA0\x03\x02\x01\x02\x02\x01\x01'
b'\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30'
b'\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D'
b'\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x54\x45\x53\x54\x31\x0E\x30'
b'\x0C\x06\x03\x55\x04\x0B\x13\x05\x4F\x41\x53\x49\x53\x31\x0D\x30'
b'\x0B\x06\x03\x55\x04\x03\x13\x04\x4B\x4D\x49\x50\x30\x1E\x17\x0D'
b'\x31\x30\x31\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x17\x0D\x32'
b'\x30\x31\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x3B\x31\x0B'
b'\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06'
b'\x03\x55\x04\x0A\x13\x04\x54\x45\x53\x54\x31\x0E\x30\x0C\x06\x03'
b'\x55\x04\x0B\x13\x05\x4F\x41\x53\x49\x53\x31\x0D\x30\x0B\x06\x03'
b'\x55\x04\x03\x13\x04\x4B\x4D\x49\x50\x30\x82\x01\x22\x30\x0D\x06'
b'\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F'
b'\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAB\x7F\x16\x1C\x00\x42'
b'\x49\x6C\xCD\x6C\x6D\x4D\xAD\xB9\x19\x97\x34\x35\x35\x77\x76\x00'
b'\x3A\xCF\x54\xB7\xAF\x1E\x44\x0A\xFB\x80\xB6\x4A\x87\x55\xF8\x00'
b'\x2C\xFE\xBA\x6B\x18\x45\x40\xA2\xD6\x60\x86\xD7\x46\x48\x34\x6D'
b'\x75\xB8\xD7\x18\x12\xB2\x05\x38\x7C\x0F\x65\x83\xBC\x4D\x7D\xC7'
b'\xEC\x11\x4F\x3B\x17\x6B\x79\x57\xC4\x22\xE7\xD0\x3F\xC6\x26\x7F'
b'\xA2\xA6\xF8\x9B\x9B\xEE\x9E\x60\xA1\xD7\xC2\xD8\x33\xE5\xA5\xF4'
b'\xBB\x0B\x14\x34\xF4\xE7\x95\xA4\x11\x00\xF8\xAA\x21\x49\x00\xDF'
b'\x8B\x65\x08\x9F\x98\x13\x5B\x1C\x67\xB7\x01\x67\x5A\xBD\xBC\x7D'
b'\x57\x21\xAA\xC9\xD1\x4A\x7F\x08\x1F\xCE\xC8\x0B\x64\xE8\xA0\xEC'
b'\xC8\x29\x53\x53\xC7\x95\x32\x8A\xBF\x70\xE1\xB4\x2E\x7B\xB8\xB7'
b'\xF4\xE8\xAC\x8C\x81\x0C\xDB\x66\xE3\xD2\x11\x26\xEB\xA8\xDA\x7D'
b'\x0C\xA3\x41\x42\xCB\x76\xF9\x1F\x01\x3D\xA8\x09\xE9\xC1\xB7\xAE'
b'\x64\xC5\x41\x30\xFB\xC2\x1D\x80\xE9\xC2\xCB\x06\xC5\xC8\xD7\xCC'
b'\xE8\x94\x6A\x9A\xC9\x9B\x1C\x28\x15\xC3\x61\x2A\x29\xA8\x2D\x73'
b'\xA1\xF9\x93\x74\xFE\x30\xE5\x49\x51\x66\x2A\x6E\xDA\x29\xC6\xFC'
b'\x41\x13\x35\xD5\xDC\x74\x26\xB0\xF6\x05\x02\x03\x01\x00\x01\xA3'
b'\x21\x30\x1F\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x04\xE5'
b'\x7B\xD2\xC4\x31\xB2\xE8\x16\xE1\x80\xA1\x98\x23\xFA\xC8\x58\x27'
b'\x3F\x6B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05'
b'\x00\x03\x82\x01\x01\x00\xA8\x76\xAD\xBC\x6C\x8E\x0F\xF0\x17\x21'
b'\x6E\x19\x5F\xEA\x76\xBF\xF6\x1A\x56\x7C\x9A\x13\xDC\x50\xD1\x3F'
b'\xEC\x12\xA4\x27\x3C\x44\x15\x47\xCF\xAB\xCB\x5D\x61\xD9\x91\xE9'
b'\x66\x31\x9D\xF7\x2C\x0D\x41\xBA\x82\x6A\x45\x11\x2F\xF2\x60\x89'
b'\xA2\x34\x4F\x4D\x71\xCF\x7C\x92\x1B\x4B\xDF\xAE\xF1\x60\x0D\x1B'
b'\xAA\xA1\x53\x36\x05\x7E\x01\x4B\x8B\x49\x6D\x4F\xAE\x9E\x8A\x6C'
b'\x1D\xA9\xAE\xB6\xCB\xC9\x60\xCB\xF2\xFA\xE7\x7F\x58\x7E\xC4\xBB'
b'\x28\x20\x45\x33\x88\x45\xB8\x8D\xD9\xAE\xEA\x53\xE4\x82\xA3\x6E'
b'\x73\x4E\x4F\x5F\x03\xB9\xD0\xDF\xC4\xCA\xFC\x6B\xB3\x4E\xA9\x05'
b'\x3E\x52\xBD\x60\x9E\xE0\x1E\x86\xD9\xB0\x9F\xB5\x11\x20\xC1\x98'
b'\x34\xA9\x97\xB0\x9C\xE0\x8D\x79\xE8\x13\x11\x76\x2F\x97\x4B\xB1'
b'\xC8\xC0\x91\x86\xC4\xD7\x89\x33\xE0\xDB\x38\xE9\x05\x08\x48\x77'
b'\xE1\x47\xC7\x8A\xF5\x2F\xAE\x07\x19\x2F\xF1\x66\xD1\x9F\xA9\x4A'
b'\x11\xCC\x11\xB2\x7E\xD0\x50\xF7\xA2\x7F\xAE\x13\xB2\x05\xA5\x74'
b'\xC4\xEE\x00\xAA\x8B\xD6\x5D\x0D\x70\x57\xC9\x85\xC8\x39\xEF\x33'
b'\x6A\x44\x1E\xD5\x3A\x53\xC6\xB6\xB6\x96\xF1\xBD\xEB\x5F\x7E\xA8'
b'\x11\xEB\xB2\x5A\x7F\x86')
self.encoding_a = BytearrayStream((
b'\x42\x00\x13\x01\x00\x00\x00\x18\x42\x00\x1D\x05\x00\x00\x00\x04'
b'\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x1E\x08\x00\x00\x00'
b'\x00'))
self.encoding_b = BytearrayStream((
b'\x42\x00\x13\x01\x00\x00\x03\x30\x42\x00\x1D\x05\x00\x00\x00\x04'
b'\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x1E\x08\x00\x00\x03\x16'
b'\x30\x82\x03\x12\x30\x82\x01\xFA\xA0\x03\x02\x01\x02\x02\x01\x01'
b'\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30'
b'\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D'
b'\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x54\x45\x53\x54\x31\x0E\x30'
b'\x0C\x06\x03\x55\x04\x0B\x13\x05\x4F\x41\x53\x49\x53\x31\x0D\x30'
b'\x0B\x06\x03\x55\x04\x03\x13\x04\x4B\x4D\x49\x50\x30\x1E\x17\x0D'
b'\x31\x30\x31\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x17\x0D\x32'
b'\x30\x31\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x3B\x31\x0B'
b'\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06'
b'\x03\x55\x04\x0A\x13\x04\x54\x45\x53\x54\x31\x0E\x30\x0C\x06\x03'
b'\x55\x04\x0B\x13\x05\x4F\x41\x53\x49\x53\x31\x0D\x30\x0B\x06\x03'
b'\x55\x04\x03\x13\x04\x4B\x4D\x49\x50\x30\x82\x01\x22\x30\x0D\x06'
b'\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F'
b'\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAB\x7F\x16\x1C\x00\x42'
b'\x49\x6C\xCD\x6C\x6D\x4D\xAD\xB9\x19\x97\x34\x35\x35\x77\x76\x00'
b'\x3A\xCF\x54\xB7\xAF\x1E\x44\x0A\xFB\x80\xB6\x4A\x87\x55\xF8\x00'
b'\x2C\xFE\xBA\x6B\x18\x45\x40\xA2\xD6\x60\x86\xD7\x46\x48\x34\x6D'
b'\x75\xB8\xD7\x18\x12\xB2\x05\x38\x7C\x0F\x65\x83\xBC\x4D\x7D\xC7'
b'\xEC\x11\x4F\x3B\x17\x6B\x79\x57\xC4\x22\xE7\xD0\x3F\xC6\x26\x7F'
b'\xA2\xA6\xF8\x9B\x9B\xEE\x9E\x60\xA1\xD7\xC2\xD8\x33\xE5\xA5\xF4'
b'\xBB\x0B\x14\x34\xF4\xE7\x95\xA4\x11\x00\xF8\xAA\x21\x49\x00\xDF'
b'\x8B\x65\x08\x9F\x98\x13\x5B\x1C\x67\xB7\x01\x67\x5A\xBD\xBC\x7D'
b'\x57\x21\xAA\xC9\xD1\x4A\x7F\x08\x1F\xCE\xC8\x0B\x64\xE8\xA0\xEC'
b'\xC8\x29\x53\x53\xC7\x95\x32\x8A\xBF\x70\xE1\xB4\x2E\x7B\xB8\xB7'
b'\xF4\xE8\xAC\x8C\x81\x0C\xDB\x66\xE3\xD2\x11\x26\xEB\xA8\xDA\x7D'
b'\x0C\xA3\x41\x42\xCB\x76\xF9\x1F\x01\x3D\xA8\x09\xE9\xC1\xB7\xAE'
b'\x64\xC5\x41\x30\xFB\xC2\x1D\x80\xE9\xC2\xCB\x06\xC5\xC8\xD7\xCC'
b'\xE8\x94\x6A\x9A\xC9\x9B\x1C\x28\x15\xC3\x61\x2A\x29\xA8\x2D\x73'
b'\xA1\xF9\x93\x74\xFE\x30\xE5\x49\x51\x66\x2A\x6E\xDA\x29\xC6\xFC'
b'\x41\x13\x35\xD5\xDC\x74\x26\xB0\xF6\x05\x02\x03\x01\x00\x01\xA3'
b'\x21\x30\x1F\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x04\xE5'
b'\x7B\xD2\xC4\x31\xB2\xE8\x16\xE1\x80\xA1\x98\x23\xFA\xC8\x58\x27'
b'\x3F\x6B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05'
b'\x00\x03\x82\x01\x01\x00\xA8\x76\xAD\xBC\x6C\x8E\x0F\xF0\x17\x21'
b'\x6E\x19\x5F\xEA\x76\xBF\xF6\x1A\x56\x7C\x9A\x13\xDC\x50\xD1\x3F'
b'\xEC\x12\xA4\x27\x3C\x44\x15\x47\xCF\xAB\xCB\x5D\x61\xD9\x91\xE9'
b'\x66\x31\x9D\xF7\x2C\x0D\x41\xBA\x82\x6A\x45\x11\x2F\xF2\x60\x89'
b'\xA2\x34\x4F\x4D\x71\xCF\x7C\x92\x1B\x4B\xDF\xAE\xF1\x60\x0D\x1B'
b'\xAA\xA1\x53\x36\x05\x7E\x01\x4B\x8B\x49\x6D\x4F\xAE\x9E\x8A\x6C'
b'\x1D\xA9\xAE\xB6\xCB\xC9\x60\xCB\xF2\xFA\xE7\x7F\x58\x7E\xC4\xBB'
b'\x28\x20\x45\x33\x88\x45\xB8\x8D\xD9\xAE\xEA\x53\xE4\x82\xA3\x6E'
b'\x73\x4E\x4F\x5F\x03\xB9\xD0\xDF\xC4\xCA\xFC\x6B\xB3\x4E\xA9\x05'
b'\x3E\x52\xBD\x60\x9E\xE0\x1E\x86\xD9\xB0\x9F\xB5\x11\x20\xC1\x98'
b'\x34\xA9\x97\xB0\x9C\xE0\x8D\x79\xE8\x13\x11\x76\x2F\x97\x4B\xB1'
b'\xC8\xC0\x91\x86\xC4\xD7\x89\x33\xE0\xDB\x38\xE9\x05\x08\x48\x77'
b'\xE1\x47\xC7\x8A\xF5\x2F\xAE\x07\x19\x2F\xF1\x66\xD1\x9F\xA9\x4A'
b'\x11\xCC\x11\xB2\x7E\xD0\x50\xF7\xA2\x7F\xAE\x13\xB2\x05\xA5\x74'
b'\xC4\xEE\x00\xAA\x8B\xD6\x5D\x0D\x70\x57\xC9\x85\xC8\x39\xEF\x33'
b'\x6A\x44\x1E\xD5\x3A\x53\xC6\xB6\xB6\x96\xF1\xBD\xEB\x5F\x7E\xA8'
b'\x11\xEB\xB2\x5A\x7F\x86\x00\x00'))
def tearDown(self):
super(TestCertificate, self).tearDown()
def test_init(self):
pass
def _test_read(self, stream, certificate_type, certificate_value):
certificate = Certificate()
certificate.read(stream)
if certificate_type is None:
expected = CertificateType()
else:
expected = CertificateType(certificate_type)
observed = certificate.certificate_type
msg = "certificate type encoding mismatch; "
msg += "expected {0}, observed {1}".format(expected, observed)
self.assertEqual(expected, observed)
if certificate_value is None:
expected = CertificateValue()
else:
expected = CertificateValue(certificate_value)
observed = certificate.certificate_value
msg = "certificate value encoding mismatch; "
msg += "expected {0}, observed {1}".format(expected, observed)
self.assertEqual(expected, observed, msg)
def test_read_a(self):
"""
Test that a Certificate object with no data can be read from a data
stream.
"""
self._test_read(self.encoding_a, self.certificate_type_a,
self.certificate_value_a)
def test_read_b(self):
"""
Test that a Certificate object with data can be read from a data
stream.
"""
self._test_read(self.encoding_b, self.certificate_type_b,
self.certificate_value_b)
def _test_write(self, stream, certificate_type, certificate_value):
certificate = Certificate(
certificate_type=certificate_type,
certificate_value=certificate_value)
expected = stream
observed = BytearrayStream()
certificate.write(observed)
msg = "encoding mismatch;\nexpected:\n{0}\nobserved:\n{1}".format(
expected, observed)
self.assertEqual(expected, observed, msg)
def test_write_a(self):
"""
Test that a Certificate object with no data can be written to a data
stream.
"""
self._test_write(self.encoding_a, self.certificate_type_a,
self.certificate_value_a)
def test_write_b(self):
"""
Test that a Certificate object with data can be written to a data
stream.
"""
self._test_write(self.encoding_b, self.certificate_type_b,
self.certificate_value_b)
def test_equal_on_equal(self):
"""
Test that the equality operator returns True when comparing two
Certificate objects with the same internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
b = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_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
Certificate objects with no internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
b = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
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
Certificate objects with different sets of internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
b = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
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
Certificate object with a non-Certificate object.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
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
Certificate objects with the same internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
b = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_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
Certificate objects with no internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
b = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
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
Certificate objects with different sets of internal data.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
b = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
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 a
Certificate object with a non-Certificate object.
"""
a = Certificate(
certificate_type=self.certificate_type_a,
certificate_value=self.certificate_value_a)
b = "invalid"
self.assertTrue(a != b)
self.assertTrue(b != a)
def test_repr(self):
"""
Test that the representation of a Certificate object with data is
formatted properly.
"""
certificate = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
certificate_type = "certificate_type={0}".format(
str(self.certificate_type_b))
certificate_value = "certificate_value=b'{0}'".format(
str(self.certificate_value_b))
expected = "Certificate({0}, {1})".format(
certificate_type, certificate_value)
observed = repr(certificate)
msg = "\nexpected:\n{0}\nobserved:\n{1}".format(expected, observed)
self.assertEqual(expected, observed, msg)
# NOTE (peter-hamilton) Testing with eval won't work due to null bytes.
def test_str(self):
"""
Test that the string representation of a Certificate object is
formatted properly.
"""
certificate = Certificate(
certificate_type=self.certificate_type_b,
certificate_value=self.certificate_value_b)
expected = str(self.certificate_value_b)
observed = str(certificate)
msg = "expected:\n{0}\nobserved:\n{1}".format(expected, observed)
self.assertEqual(expected, observed, msg)