diff --git a/kmip/pie/objects.py b/kmip/pie/objects.py index 0ef86fa..f91090f 100644 --- a/kmip/pie/objects.py +++ b/kmip/pie/objects.py @@ -14,6 +14,7 @@ # under the License. from abc import abstractmethod +import sqlalchemy from sqlalchemy import Column, event, ForeignKey, Integer, String, VARBINARY from sqlalchemy import Boolean from sqlalchemy.ext.associationproxy import association_proxy @@ -1051,6 +1052,264 @@ event.listen(PrivateKey._names, 'append', sql.attribute_append_factory("name_index"), retval=False) +class SplitKey(Key): + """ + """ + + __mapper_args__ = {"polymorphic_identity": "SplitKey"} + __table_args__ = {"sqlite_autoincrement": True} + __tablename__ = "split_keys" + + unique_identifier = sqlalchemy.Column( + "uid", + sqlalchemy.Integer, + sqlalchemy.ForeignKey("keys.uid"), + primary_key=True + ) + + # Split Key object fields + _split_key_parts = sqlalchemy.Column( + "_split_key_parts", + sqlalchemy.Integer, + default=None + ) + _key_part_identifier = sqlalchemy.Column( + "_key_part_identifier", + sqlalchemy.Integer, + default=None + ) + _split_key_threshold = sqlalchemy.Column( + "_split_key_threshold", + sqlalchemy.Integer, + default=None + ) + _split_key_method = sqlalchemy.Column( + "_split_key_method", + sql.EnumType(enums.SplitKeyMethod), + default=None + ) + _prime_field_size = sqlalchemy.Column( + "_prime_field_size", + sqlalchemy.BigInteger, + default=None + ) + + def __init__(self, + cryptographic_algorithm=None, + cryptographic_length=None, + key_value=None, + cryptographic_usage_masks=None, + name="Split Key", + key_format_type=enums.KeyFormatType.RAW, + key_wrapping_data=None, + split_key_parts=None, + key_part_identifier=None, + split_key_threshold=None, + split_key_method=None, + prime_field_size=None): + """ + Create a SplitKey. + + Args: + cryptographic_algorithm(enum): A CryptographicAlgorithm enumeration + identifying the type of algorithm for the split key. Required. + cryptographic_length(int): The length in bits of the split key. + Required. + key_value(bytes): The bytes representing the split key. Required. + cryptographic_usage_masks(list): A list of CryptographicUsageMask + enumerations defining how the split key will be used. Optional, + defaults to None. + name(string): The string name of the split key. Optional, defaults + to "Split Key". + key_format_type (enum): A KeyFormatType enumeration specifying the + format of the split key. Optional, defaults to Raw. + key_wrapping_data(dict): A dictionary containing key wrapping data + settings, describing how the split key has been wrapped. + Optional, defaults to None. + split_key_parts (int): An integer specifying the total number of + parts of the split key. Required. + key_part_identifier (int): An integer specifying which key part + of the split key this key object represents. Required. + split_key_threshold (int): An integer specifying the minimum + number of key parts required to reconstruct the split key. + Required. + split_key_method (enum): A SplitKeyMethod enumeration specifying + how the key was split. Required. + prime_field_size (int): A big integer specifying the prime field + size used for the Polynomial Sharing Prime Field split key + method. Optional, defaults to None. + """ + super(SplitKey, self).__init__(key_wrapping_data=key_wrapping_data) + + self._object_type = enums.ObjectType.SPLIT_KEY + + self.key_format_type = key_format_type + self.value = key_value + self.cryptographic_algorithm = cryptographic_algorithm + self.cryptographic_length = cryptographic_length + self.names = [name] + + if cryptographic_usage_masks: + self.cryptographic_usage_masks.extend(cryptographic_usage_masks) + + self.split_key_parts = split_key_parts + self.key_part_identifier = key_part_identifier + self.split_key_threshold = split_key_threshold + self.split_key_method = split_key_method + self.prime_field_size = prime_field_size + + @property + def split_key_parts(self): + return self._split_key_parts + + @split_key_parts.setter + def split_key_parts(self, value): + if (value is None) or (isinstance(value, six.integer_types)): + self._split_key_parts = value + else: + raise TypeError("The split key parts must be an integer.") + + @property + def key_part_identifier(self): + return self._key_part_identifier + + @key_part_identifier.setter + def key_part_identifier(self, value): + if (value is None) or (isinstance(value, six.integer_types)): + self._key_part_identifier = value + else: + raise TypeError("The key part identifier must be an integer.") + + @property + def split_key_threshold(self): + return self._split_key_threshold + + @split_key_threshold.setter + def split_key_threshold(self, value): + if (value is None) or (isinstance(value, six.integer_types)): + self._split_key_threshold = value + else: + raise TypeError("The split key threshold must be an integer.") + + @property + def split_key_method(self): + return self._split_key_method + + @split_key_method.setter + def split_key_method(self, value): + if (value is None) or (isinstance(value, enums.SplitKeyMethod)): + self._split_key_method = value + else: + raise TypeError( + "The split key method must be a SplitKeyMethod enumeration." + ) + + @property + def prime_field_size(self): + return self._prime_field_size + + @prime_field_size.setter + def prime_field_size(self, value): + if (value is None) or (isinstance(value, six.integer_types)): + self._prime_field_size = value + else: + raise TypeError("The prime field size must be an integer.") + + def __repr__(self): + cryptographic_algorithm = "cryptographic_algorithm={0}".format( + self.cryptographic_algorithm + ) + cryptographic_length = "cryptographic_length={0}".format( + self.cryptographic_length + ) + key_value = "key_value={0}".format(binascii.hexlify(self.value)) + key_format_type = "key_format_type={0}".format(self.key_format_type) + key_wrapping_data = "key_wrapping_data={0}".format( + self.key_wrapping_data + ) + cryptographic_usage_masks = "cryptographic_usage_masks={0}".format( + self.cryptographic_usage_masks + ) + names = "name={0}".format(self.names) + split_key_parts = "split_key_parts={0}".format(self.split_key_parts) + key_part_identifier = "key_part_identifier={0}".format( + self.key_part_identifier + ) + split_key_threshold = "split_key_threshold={0}".format( + self.split_key_threshold + ) + split_key_method = "split_key_method={0}".format(self.split_key_method) + prime_field_size = "prime_field_size={0}".format(self.prime_field_size) + + return "SplitKey({0})".format( + ", ".join( + [ + cryptographic_algorithm, + cryptographic_length, + key_value, + key_format_type, + key_wrapping_data, + cryptographic_usage_masks, + names, + split_key_parts, + key_part_identifier, + split_key_threshold, + split_key_method, + prime_field_size + ] + ) + ) + + def __str__(self): + return str(binascii.hexlify(self.value)) + + def __eq__(self, other): + if isinstance(other, SplitKey): + if self.value != other.value: + return False + elif self.key_format_type != other.key_format_type: + return False + elif self.cryptographic_algorithm != other.cryptographic_algorithm: + return False + elif self.cryptographic_length != other.cryptographic_length: + return False + elif self.key_wrapping_data != other.key_wrapping_data: + return False + elif self.cryptographic_usage_masks != \ + other.cryptographic_usage_masks: + return False + elif self.names != other.names: + return False + elif self.split_key_parts != other.split_key_parts: + return False + elif self.key_part_identifier != other.key_part_identifier: + return False + elif self.split_key_threshold != other.split_key_threshold: + return False + elif self.split_key_method != other.split_key_method: + return False + elif self.prime_field_size != other.prime_field_size: + return False + else: + return True + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, SplitKey): + return not (self == other) + else: + return NotImplemented + + +event.listen( + SplitKey._names, + "append", + sql.attribute_append_factory("name_index"), + retval=False +) + + class Certificate(CryptographicObject): """ The Certificate class of the simplified KMIP object hierarchy. diff --git a/kmip/tests/unit/pie/objects/test_split_key.py b/kmip/tests/unit/pie/objects/test_split_key.py new file mode 100644 index 0000000..a81c304 --- /dev/null +++ b/kmip/tests/unit/pie/objects/test_split_key.py @@ -0,0 +1,637 @@ +# Copyright (c) 2019 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. + +import binascii +import testtools +import sqlalchemy + +from kmip.core import enums + +from kmip.pie import objects +from kmip.pie import sqltypes + + +class TestSplitKey(testtools.TestCase): + """ + Test suite for SplitKey. + """ + + def setUp(self): + super(TestSplitKey, self).setUp() + + self.engine = sqlalchemy.create_engine("sqlite:///:memory:", echo=True) + sqltypes.Base.metadata.create_all(self.engine) + + def tearDown(self): + super(TestSplitKey, self).tearDown() + + def test_init(self): + """ + Test that a SplitKey object can be instantiated. + """ + split_key = objects.SplitKey() + + self.assertIsNone(split_key.cryptographic_algorithm) + self.assertIsNone(split_key.cryptographic_length) + self.assertIsNone(split_key.value) + self.assertEqual(split_key.key_format_type, enums.KeyFormatType.RAW) + self.assertEqual(split_key.cryptographic_usage_masks, []) + self.assertEqual(split_key.names, ["Split Key"]) + self.assertIsNone(split_key.split_key_parts) + self.assertIsNone(split_key.key_part_identifier) + self.assertIsNone(split_key.split_key_threshold) + self.assertIsNone(split_key.split_key_method) + self.assertIsNone(split_key.prime_field_size) + + def test_init_with_args(self): + """ + Test that a SplitKey object can be instantiated with all arguments. + """ + split_key = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + + self.assertEqual( + split_key.cryptographic_algorithm, + enums.CryptographicAlgorithm.AES + ) + self.assertEqual(split_key.cryptographic_length, 128) + self.assertEqual( + split_key.value, + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ) + self.assertEqual(split_key.key_format_type, enums.KeyFormatType.RAW) + self.assertEqual( + split_key.cryptographic_usage_masks, + [enums.CryptographicUsageMask.EXPORT] + ) + self.assertEqual(split_key.names, ["Test Split Key"]) + self.assertEqual(split_key.split_key_parts, 4) + self.assertEqual(split_key.key_part_identifier, 1) + self.assertEqual(split_key.split_key_threshold, 2) + self.assertEqual( + split_key.split_key_method, + enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8 + ) + self.assertEqual(split_key.prime_field_size, 104729) + + def test_invalid_split_key_parts(self): + """ + Test that a TypeError is raised when an invalid split key parts value + is used to construct a SplitKey. + """ + kwargs = {"split_key_parts": "invalid"} + + self.assertRaisesRegex( + TypeError, + "The split key parts must be an integer.", + objects.SplitKey, + **kwargs + ) + + args = ( + objects.SplitKey(), + "split_key_parts", + "invalid" + ) + self.assertRaisesRegex( + TypeError, + "The split key parts must be an integer.", + setattr, + *args + ) + + def test_invalid_key_part_identifier(self): + """ + Test that a TypeError is raised when an invalid key part identifier + value is used to construct a SplitKey. + """ + kwargs = {"key_part_identifier": "invalid"} + + self.assertRaisesRegex( + TypeError, + "The key part identifier must be an integer.", + objects.SplitKey, + **kwargs + ) + + args = ( + objects.SplitKey(), + "key_part_identifier", + "invalid" + ) + self.assertRaisesRegex( + TypeError, + "The key part identifier must be an integer.", + setattr, + *args + ) + + def test_invalid_split_key_threshold(self): + """ + Test that a TypeError is raised when an invalid split key threshold + value is used to construct a SplitKey. + """ + kwargs = {"split_key_threshold": "invalid"} + + self.assertRaisesRegex( + TypeError, + "The split key threshold must be an integer.", + objects.SplitKey, + **kwargs + ) + + args = ( + objects.SplitKey(), + "split_key_threshold", + "invalid" + ) + self.assertRaisesRegex( + TypeError, + "The split key threshold must be an integer.", + setattr, + *args + ) + + def test_invalid_split_key_method(self): + """ + Test that a TypeError is raised when an invalid split key method value + is used to construct a SplitKey. + """ + kwargs = {"split_key_method": "invalid"} + + self.assertRaisesRegex( + TypeError, + "The split key method must be a SplitKeyMethod enumeration.", + objects.SplitKey, + **kwargs + ) + + args = ( + objects.SplitKey(), + "split_key_method", + "invalid" + ) + self.assertRaisesRegex( + TypeError, + "The split key method must be a SplitKeyMethod enumeration.", + setattr, + *args + ) + + def test_invalid_prime_field_size(self): + """ + Test that a TypeError is raised when an invalid prime field size value + is used to construct a SplitKey. + """ + kwargs = {"prime_field_size": "invalid"} + + self.assertRaisesRegex( + TypeError, + "The prime field size must be an integer.", + objects.SplitKey, + **kwargs + ) + + args = ( + objects.SplitKey(), + "prime_field_size", + "invalid" + ) + self.assertRaisesRegex( + TypeError, + "The prime field size must be an integer.", + setattr, + *args + ) + + def test_repr(self): + """ + Test that repr can be applied to a SplitKey. + """ + split_key = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + + args = [ + "cryptographic_algorithm={}".format( + enums.CryptographicAlgorithm.AES + ), + "cryptographic_length={}".format(128), + "key_value={}".format( + binascii.hexlify( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ) + ), + "key_format_type={}".format(enums.KeyFormatType.RAW), + "key_wrapping_data={}".format({}), + "cryptographic_usage_masks={}".format( + [enums.CryptographicUsageMask.EXPORT] + ), + "name={}".format(["Test Split Key"]), + "split_key_parts=4", + "key_part_identifier=1", + "split_key_threshold=2", + "split_key_method={}".format( + enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8 + ), + "prime_field_size=104729" + ] + + expected = "SplitKey({})".format(", ".join(args)) + observed = repr(split_key) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to a SplitKey. + """ + split_key = objects.SplitKey( + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ) + ) + + expected = str(binascii.hexlify(split_key.value)) + observed = str(split_key) + + self.assertEqual(expected, observed) + + def test_comparison_on_equal(self): + """ + Test that the equality/inequality operators return True/False when + comparing two SplitKey objects with the same data. + """ + a = objects.SplitKey() + b = objects.SplitKey() + + self.assertTrue(a == b) + self.assertTrue(b == a) + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + b = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_comparison_on_different_cryptographic_algorithms(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different cryptographic algorithms. + """ + a = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES + ) + b = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_cryptographic_lengths(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different cryptographic lengths. + """ + a = objects.SplitKey(cryptographic_length=128) + b = objects.SplitKey(cryptographic_length=256) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_values(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different values. + """ + a = objects.SplitKey(key_value=b'\x00') + b = objects.SplitKey(key_value=b'\xFF') + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_key_format_types(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different key format types. + """ + a = objects.SplitKey(key_format_type=enums.KeyFormatType.RAW) + b = objects.SplitKey(key_format_type=enums.KeyFormatType.OPAQUE) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_key_wrapping_data(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different key wrapping data. + """ + a = objects.SplitKey(key_wrapping_data={}) + b = objects.SplitKey( + key_wrapping_data={"wrapping_method": enums.WrappingMethod.ENCRYPT} + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_cryptographic_usage_masks(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different cryptographic usage + masks. + """ + a = objects.SplitKey( + cryptographic_usage_masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + b = objects.SplitKey( + cryptographic_usage_masks=[enums.CryptographicUsageMask.EXPORT] + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_names(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different names. + """ + a = objects.SplitKey(name="Test Split Key") + b = objects.SplitKey(name="Split Key Test") + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_split_key_parts(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different split key parts. + """ + a = objects.SplitKey(split_key_parts=4) + b = objects.SplitKey(split_key_parts=5) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_key_part_identifiers(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different key part identifiers. + """ + a = objects.SplitKey(key_part_identifier=1) + b = objects.SplitKey(key_part_identifier=2) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_split_key_thresholds(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different split key thresholds. + """ + a = objects.SplitKey(split_key_threshold=1) + b = objects.SplitKey(split_key_threshold=2) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_split_key_methods(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different split key methods. + """ + a = objects.SplitKey(split_key_method=enums.SplitKeyMethod.XOR) + b = objects.SplitKey( + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8 + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_different_prime_field_sizes(self): + """ + Test that the equality/inequality operators return False/True when + comparing two SplitKey objects with different prime field sizes. + """ + a = objects.SplitKey(prime_field_size=13) + b = objects.SplitKey(prime_field_size=104729) + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_comparison_on_type_mismatch(self): + """ + Test that the equality/inequality operators return False/True when + comparing a SplitKey object to a non-SplitKey object. + """ + a = objects.SplitKey() + b = "invalid" + + self.assertFalse(a == b) + self.assertFalse(b == a) + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_save(self): + """ + Test that a SplitKey object can be saved using SQLAlchemy. This will + add it to the database, verify that no exceptions are thrown, and check + that its unique identifier was set. + """ + split_key = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + + session = sqlalchemy.orm.sessionmaker(bind=self.engine)() + session.add(split_key) + session.commit() + + self.assertIsNotNone(split_key.unique_identifier) + + def test_get(self): + """ + Test that a SplitKey object can be saved and then retrieved using + SQLAlchemy. This test adds the object to the database and then + retrieves it by ID and verifies some of the attributes. + """ + split_key = objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ), + key_format_type=enums.KeyFormatType.RAW, + cryptographic_usage_masks=[ + enums.CryptographicUsageMask.EXPORT + ], + name="Test Split Key", + split_key_parts=4, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8, + prime_field_size=104729 + ) + + session = sqlalchemy.orm.sessionmaker(bind=self.engine)() + session.add(split_key) + session.commit() + + session = sqlalchemy.orm.sessionmaker(bind=self.engine)() + retrieved_key = session.query(objects.SplitKey).filter( + objects.ManagedObject.unique_identifier == + split_key.unique_identifier + ).one() + session.commit() + + self.assertEqual(retrieved_key.names, ["Test Split Key"]) + self.assertEqual( + retrieved_key.cryptographic_algorithm, + enums.CryptographicAlgorithm.AES + ) + self.assertEqual(retrieved_key.cryptographic_length, 128) + self.assertEqual( + retrieved_key.value, + ( + b'\x66\xC4\x6A\x77\x54\xF9\x4D\xE4' + b'\x20\xC7\xB1\xA7\xFF\xF5\xEC\x56' + ) + ) + self.assertEqual( + retrieved_key.key_format_type, + enums.KeyFormatType.RAW + ) + self.assertEqual( + retrieved_key.cryptographic_usage_masks, + [enums.CryptographicUsageMask.EXPORT] + ) + self.assertEqual(retrieved_key.split_key_parts, 4) + self.assertEqual(retrieved_key.key_part_identifier, 1) + self.assertEqual(retrieved_key.split_key_threshold, 2) + self.assertEqual( + retrieved_key.split_key_method, + enums.SplitKeyMethod.POLYNOMIAL_SHARING_GF_2_8 + ) + self.assertEqual(retrieved_key.prime_field_size, 104729)