Example #1
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {
            'content-type': 'application/json',
            'X-Auth-Token': str(SYS_TOKEN.token)
        }
        post_resp = cls.app.post_json('/v1/actions',
                                      cls.action,
                                      headers=headers)
        cls.action['id'] = post_resp.json['id']

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json('/v1/actions',
                                      cls.action_encrypt,
                                      headers=headers)
        cls.action_encrypt['id'] = post_resp.json['id']

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {
                'name':
                'secret',
                'secret':
                True,
                'value':
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               'foo')
            },
            {
                'name':
                'user1:secret',
                'secret':
                True,
                'scope':
                FULL_USER_SCOPE,
                'value':
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               'bar')
            },
        ]
        cls.kvps = [
            KeyValuePair.add_or_update(KeyValuePairDB(**x))
            for x in register_items
        ]
Example #2
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {
            "content-type": "application/json",
            "X-Auth-Token": str(SYS_TOKEN.token),
        }
        post_resp = cls.app.post_json("/v1/actions",
                                      cls.action,
                                      headers=headers)
        cls.action["id"] = post_resp.json["id"]

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json("/v1/actions",
                                      cls.action_encrypt,
                                      headers=headers)
        cls.action_encrypt["id"] = post_resp.json["id"]

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {
                "name":
                "secret",
                "secret":
                True,
                "value":
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               "foo"),
            },
            {
                "name":
                "user1:secret",
                "secret":
                True,
                "scope":
                FULL_USER_SCOPE,
                "value":
                crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                               "bar"),
            },
        ]
        cls.kvps = [
            KeyValuePair.add_or_update(KeyValuePairDB(**x))
            for x in register_items
        ]
Example #3
0
    def setUpClass(cls):
        super(SystemScopeDatastoreFunctionTest, cls).setUpClass()
        user = auth_db.UserDB(name="stanley")
        user.save()
        scope = kvp_const.FULL_SYSTEM_SCOPE
        cls.kvps = {}

        # Plain key
        keys = {"foo": "bar", "foo_empty": "", "foo_null": None}

        for k, v in six.iteritems(keys):
            instance = kvp_db.KeyValuePairDB(name=k, value=v, scope=scope)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)

        # Secret key
        keys = {"fu": "bar", "fu_empty": ""}

        for k, v in six.iteritems(keys):
            value = crypto.symmetric_encrypt(
                kvp_api.KeyValuePairAPI.crypto_key, v)
            instance = kvp_db.KeyValuePairDB(name=k,
                                             value=value,
                                             scope=scope,
                                             secret=True)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)
Example #4
0
    def setUpClass(cls):
        super(UserScopeDatastoreFunctionTest, cls).setUpClass()
        user = auth_db.UserDB(name='stanley')
        user.save()
        scope = kvp_const.FULL_USER_SCOPE
        cls.kvps = {}

        # Plain keys
        keys = {
            'stanley:foo': 'bar',
            'stanley:foo_empty': '',
            'stanley:foo_null': None
        }

        for k, v in six.iteritems(keys):
            instance = kvp_db.KeyValuePairDB(name=k, value=v, scope=scope)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)

        # Secret key
        keys = {'stanley:fu': 'bar', 'stanley:fu_empty': ''}

        for k, v in six.iteritems(keys):
            value = crypto.symmetric_encrypt(
                kvp_api.KeyValuePairAPI.crypto_key, v)
            instance = kvp_db.KeyValuePairDB(name=k,
                                             value=value,
                                             scope=scope,
                                             secret=True)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)
 def test_symmetric_encrypt_decrypt(self):
     original = 'secret'
     crypto = crypto_utils.symmetric_encrypt(
         CryptoUtilsTestCase.test_crypto_key, original)
     plain = crypto_utils.symmetric_decrypt(
         CryptoUtilsTestCase.test_crypto_key, crypto)
     self.assertEqual(plain, original)
Example #6
0
    def setUpClass(cls):
        super(UserScopeDatastoreFunctionTest, cls).setUpClass()
        user = auth_db.UserDB(name='stanley')
        user.save()
        scope = kvp_const.FULL_USER_SCOPE
        cls.kvps = {}

        # Plain keys
        keys = {
            'stanley:foo': 'bar',
            'stanley:foo_empty': '',
            'stanley:foo_null': None
        }

        for k, v in six.iteritems(keys):
            instance = kvp_db.KeyValuePairDB(name=k, value=v, scope=scope)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)

        # Secret key
        keys = {
            'stanley:fu': 'bar',
            'stanley:fu_empty': ''
        }

        for k, v in six.iteritems(keys):
            value = crypto.symmetric_encrypt(kvp_api.KeyValuePairAPI.crypto_key, v)
            instance = kvp_db.KeyValuePairDB(name=k, value=value, scope=scope, secret=True)
            cls.kvps[k] = kvp_db_access.KeyValuePair.add_or_update(instance)
Example #7
0
    def to_model(cls, kvp):
        if not KeyValuePairAPI.crypto_setup:
            KeyValuePairAPI._setup_crypto()

        name = getattr(kvp, 'name', None)
        description = getattr(kvp, 'description', None)
        value = kvp.value
        secret = False

        if getattr(kvp, 'ttl', None):
            expire_timestamp = (date_utils.get_datetime_utc_now() +
                                datetime.timedelta(seconds=kvp.ttl))
        else:
            expire_timestamp = None

        if getattr(kvp, 'secret', False):
            if not KeyValuePairAPI.crypto_key:
                msg = ('Crypto key not found in %s. Unable to encrypt value for key %s.' %
                       (KeyValuePairAPI.crypto_key_path, name))
                raise CryptoKeyNotSetupException(msg)
            value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value)
            secret = True

        model = cls.model(name=name, description=description, value=value,
                          secret=secret,
                          expire_timestamp=expire_timestamp)

        return model
Example #8
0
    def test_encrypt_output_is_diff_due_to_diff_IV(self):
        original = 'Kami is a little boy.'
        cryptos = set()

        for _ in range(0, 10000):
            crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key, original)
            self.assertTrue(crypto not in cryptos)
            cryptos.add(crypto)
Example #9
0
    def test_encrypt_output_is_diff_due_to_diff_IV(self):
        original = 'Kami is a little boy.'
        cryptos = set()

        for _ in range(0, 10000):
            crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key,
                                       original)
            self.assertNotIn(crypto, cryptos)
            cryptos.add(crypto)
    def setUp(self):
        super(JinjaUtilsDecryptTestCase, self).setUp()

        crypto_key_path = cfg.CONF.keyvalue.encryption_key_path
        crypto_key = read_crypto_key(key_path=crypto_key_path)

        self.secret = 'Build a wall'
        self.secret_value = symmetric_encrypt(encrypt_key=crypto_key, plaintext=self.secret)
        self.env = jinja_utils.get_jinja_environment()
    def setUp(self):
        super(JinjaUtilsDecryptTestCase, self).setUp()

        crypto_key_path = cfg.CONF.keyvalue.encryption_key_path
        crypto_key = read_crypto_key(key_path=crypto_key_path)

        self.secret = 'Build a wall'
        self.secret_value = symmetric_encrypt(encrypt_key=crypto_key, plaintext=self.secret)
        self.env = jinja_utils.get_jinja_environment()
Example #12
0
    def test_get_config_dynamic_config_item_under_additional_properties(self):
        pack_name = "dummy_pack_schema_with_additional_properties_1"
        loader = ContentPackConfigLoader(pack_name=pack_name)

        encrypted_value = crypto.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                                   "v1_encrypted")
        KeyValuePair.add_or_update(
            KeyValuePairDB(name="k1_encrypted",
                           value=encrypted_value,
                           secret=True))

        ####################
        # values in objects under an object with additionalProperties
        values = {
            "profiles": {
                "dev": {
                    # no host or port to test default value
                    "token": "hard-coded-secret",
                },
                "prod": {
                    "host": "127.1.2.7",
                    "port": 8282,
                    # encrypted in datastore
                    "token": "{{st2kv.system.k1_encrypted}}",
                    # schema declares `secret: true` which triggers auto-decryption.
                    # If this were not encrypted, it would try to decrypt it and fail.
                },
            }
        }
        config_db = ConfigDB(pack=pack_name, values=values)
        config_db = Config.add_or_update(config_db)

        config_rendered = loader.get_config()

        self.assertEqual(
            config_rendered,
            {
                "region": "us-east-1",
                "profiles": {
                    "dev": {
                        "host": "127.0.0.3",
                        "port": 8080,
                        "token": "hard-coded-secret",
                    },
                    "prod": {
                        "host": "127.1.2.7",
                        "port": 8282,
                        "token": "v1_encrypted",
                    },
                },
            },
        )

        config_db.delete()
Example #13
0
    def setUp(self):
        super(UserScopeDatastoreFunctionTest, self).setUp()
        scope = kvp_const.FULL_USER_SCOPE

        # Plain key
        key_id = 'stanley:foo'
        instance = kvp_db.KeyValuePairDB(name=key_id, value='bar', scope=scope)
        self.kvp = kvp_db_access.KeyValuePair.add_or_update(instance)

        # Secret key
        key_id = 'stanley:fu'
        value = crypto.symmetric_encrypt(kvp_api.KeyValuePairAPI.crypto_key, 'bar')
        instance = kvp_db.KeyValuePairDB(name=key_id, value=value, scope=scope, secret=True)
        self.secret_kvp = kvp_db_access.KeyValuePair.add_or_update(instance)
Example #14
0
    def setUpClass(cls):
        super(ActionExecutionControllerTestCaseAuthEnabled, cls).setUpClass()
        cls.action = copy.deepcopy(ACTION_1)
        headers = {'content-type': 'application/json', 'X-Auth-Token': str(SYS_TOKEN.token)}
        post_resp = cls.app.post_json('/v1/actions', cls.action, headers=headers)
        cls.action['id'] = post_resp.json['id']

        cls.action_encrypt = copy.deepcopy(ACTION_DEFAULT_ENCRYPT)
        post_resp = cls.app.post_json('/v1/actions', cls.action_encrypt, headers=headers)
        cls.action_encrypt['id'] = post_resp.json['id']

        FixturesLoader().save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                             fixtures_dict=FIXTURES)

        # register datastore values which are used in this tests
        KeyValuePairAPI._setup_crypto()
        register_items = [
            {'name': 'secret', 'secret': True,
             'value': crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key, 'foo')},
            {'name': 'user1:secret', 'secret': True, 'scope': FULL_USER_SCOPE,
             'value': crypto_utils.symmetric_encrypt(KeyValuePairAPI.crypto_key, 'bar')},
        ]
        cls.kvps = [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items]
Example #15
0
    def setUp(self):
        super(UserScopeDatastoreFunctionTest, self).setUp()
        scope = kvp_const.FULL_USER_SCOPE

        # Plain key
        key_id = 'stanley:foo'
        instance = kvp_db.KeyValuePairDB(name=key_id, value='bar', scope=scope)
        self.kvp = kvp_db_access.KeyValuePair.add_or_update(instance)

        # Secret key
        key_id = 'stanley:fu'
        value = crypto.symmetric_encrypt(kvp_api.KeyValuePairAPI.crypto_key, 'bar')
        instance = kvp_db.KeyValuePairDB(name=key_id, value=value, scope=scope, secret=True)
        self.secret_kvp = kvp_db_access.KeyValuePair.add_or_update(instance)
Example #16
0
    def test_symmetric_encrypt_decrypt_utf8_character(self):
        values = [
            u'£', u'£££', u'££££££', u'č š hello đ č p ž Ž', u'hello 💩',
            u'💩💩💩💩💩'
            u'💩💩💩', u'💩😁'
        ]

        for index, original in enumerate(values):
            crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key,
                                       original)
            plain = symmetric_decrypt(CryptoUtilsTestCase.test_crypto_key,
                                      crypto)
            self.assertEqual(plain, original)

        self.assertEqual(index, (len(values) - 1))
Example #17
0
    def test_symmetric_encrypt_decrypt_utf8_character(self):
        values = [
            u'£',
            u'£££',
            u'££££££',
            u'č š hello đ č p ž Ž',
            u'hello 💩',
            u'💩💩💩💩💩'
            u'💩💩💩',
            u'💩😁'
        ]

        for index, original in enumerate(values):
            crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key, original)
            plain = symmetric_decrypt(CryptoUtilsTestCase.test_crypto_key, crypto)
            self.assertEqual(plain, original)

        self.assertEqual(index, (len(values) - 1))
Example #18
0
    def to_model(cls, kvp):
        if not KeyValuePairAPI.crypto_setup:
            KeyValuePairAPI._setup_crypto()

        kvp_id = getattr(kvp, 'id', None)
        name = getattr(kvp, 'name', None)
        description = getattr(kvp, 'description', None)
        value = kvp.value
        secret = False

        if getattr(kvp, 'ttl', None):
            expire_timestamp = (date_utils.get_datetime_utc_now() +
                                datetime.timedelta(seconds=kvp.ttl))
        else:
            expire_timestamp = None

        secret = getattr(kvp, 'secret', False)

        if secret:
            if not KeyValuePairAPI.crypto_key:
                msg = (
                    'Crypto key not found in %s. Unable to encrypt value for key %s.'
                    % (KeyValuePairAPI.crypto_key_path, name))
                raise CryptoKeyNotSetupException(msg)
            value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value)

        scope = getattr(kvp, 'scope', FULL_SYSTEM_SCOPE)

        if scope not in ALLOWED_SCOPES:
            raise InvalidScopeException(
                'Invalid scope "%s"! Allowed scopes are %s.' %
                (scope, ALLOWED_SCOPES))

        model = cls.model(id=kvp_id,
                          name=name,
                          description=description,
                          value=value,
                          secret=secret,
                          scope=scope,
                          expire_timestamp=expire_timestamp)

        return model
    def test_filter_decrypt_kv(self):
        secret = 'Build a wall'
        crypto_key_path = cfg.CONF.keyvalue.encryption_key_path
        crypto_key = read_crypto_key(key_path=crypto_key_path)
        secret_value = symmetric_encrypt(encrypt_key=crypto_key, plaintext=secret)
        KeyValuePair.add_or_update(KeyValuePairDB(name='k8', value=secret_value,
                                                  scope=FULL_SYSTEM_SCOPE,
                                                  secret=True))
        env = jinja_utils.get_jinja_environment()

        context = {}
        context.update({SYSTEM_SCOPE: KeyValueLookup(scope=SYSTEM_SCOPE)})
        context.update({
            DATASTORE_PARENT_SCOPE: {
                SYSTEM_SCOPE: KeyValueLookup(scope=FULL_SYSTEM_SCOPE)
            }
        })

        template = '{{st2kv.system.k8 | decrypt_kv}}'
        actual = env.from_string(template).render(context)
        self.assertEqual(actual, secret)
Example #20
0
    def to_model(cls, kvp):
        if not KeyValuePairAPI.crypto_setup:
            KeyValuePairAPI._setup_crypto()

        kvp_id = getattr(kvp, 'id', None)
        name = getattr(kvp, 'name', None)
        description = getattr(kvp, 'description', None)
        value = kvp.value
        secret = False

        if getattr(kvp, 'ttl', None):
            expire_timestamp = (date_utils.get_datetime_utc_now() +
                                datetime.timedelta(seconds=kvp.ttl))
        else:
            expire_timestamp = None

        secret = getattr(kvp, 'secret', False)

        if secret:
            if not KeyValuePairAPI.crypto_key:
                msg = ('Crypto key not found in %s. Unable to encrypt value for key %s.' %
                       (KeyValuePairAPI.crypto_key_path, name))
                raise CryptoKeyNotSetupException(msg)
            value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value)

        scope = getattr(kvp, 'scope', FULL_SYSTEM_SCOPE)

        if scope not in ALLOWED_SCOPES:
            raise InvalidScopeException('Invalid scope "%s"! Allowed scopes are %s.' % (
                scope, ALLOWED_SCOPES)
            )

        model = cls.model(id=kvp_id, name=name, description=description, value=value,
                          secret=secret, scope=scope,
                          expire_timestamp=expire_timestamp)

        return model
    def test_filter_decrypt_kv(self):
        secret = 'Build a wall'
        crypto_key_path = cfg.CONF.keyvalue.encryption_key_path
        crypto_key = read_crypto_key(key_path=crypto_key_path)
        secret_value = symmetric_encrypt(encrypt_key=crypto_key,
                                         plaintext=secret)
        KeyValuePair.add_or_update(
            KeyValuePairDB(name='k8',
                           value=secret_value,
                           scope=FULL_SYSTEM_SCOPE,
                           secret=True))
        env = jinja_utils.get_jinja_environment()

        context = {}
        context.update({SYSTEM_SCOPE: KeyValueLookup(scope=SYSTEM_SCOPE)})
        context.update({
            DATASTORE_PARENT_SCOPE: {
                SYSTEM_SCOPE: KeyValueLookup(scope=FULL_SYSTEM_SCOPE)
            }
        })

        template = '{{st2kv.system.k8 | decrypt_kv}}'
        actual = env.from_string(template).render(context)
        self.assertEqual(actual, secret)
Example #22
0
    def to_model(cls, kvp):
        if not KeyValuePairAPI.crypto_setup:
            KeyValuePairAPI._setup_crypto()

        kvp_id = getattr(kvp, "id", None)
        name = getattr(kvp, "name", None)
        description = getattr(kvp, "description", None)
        value = kvp.value
        original_value = value
        secret = False

        if getattr(kvp, "ttl", None):
            expire_timestamp = date_utils.get_datetime_utc_now(
            ) + datetime.timedelta(seconds=kvp.ttl)
        else:
            expire_timestamp = None

        encrypted = getattr(kvp, "encrypted", False)
        secret = getattr(kvp, "secret", False)

        # If user transmitted the value in an pre-encrypted format, we perform the decryption here
        # to ensure data integrity. Besides that, we store data as-is.
        # Keep in mind that encrypted=True also always implies secret=True. If we didn't do
        # that and supported encrypted=True, secret=False, this would allow users to decrypt
        # any encrypted value.
        if encrypted:
            secret = True

            cls._verif_key_is_set_up(name=name)

            try:
                symmetric_decrypt(KeyValuePairAPI.crypto_key, value)
            except Exception:
                msg = (
                    'Failed to verify the integrity of the provided value for key "%s". Ensure '
                    "that the value is encrypted with the correct key and not corrupted."
                    % (name))
                raise ValueError(msg)

            # Additional safety check to ensure that the value hasn't been decrypted
            if value != original_value:
                raise ValueError(
                    f"The encrypted value {value} is not the"
                    f" same original encrypted value {original_value}.")
        elif secret:
            cls._verif_key_is_set_up(name=name)

            value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value)

        scope = getattr(kvp, "scope", FULL_SYSTEM_SCOPE)

        if scope not in ALLOWED_SCOPES:
            raise InvalidScopeException(
                'Invalid scope "%s"! Allowed scopes are %s.' %
                (scope, ALLOWED_SCOPES))

        # NOTE: For security reasons, encrypted always implies secret=True. See comment
        # above for explanation.
        if encrypted and not secret:
            raise ValueError(
                "encrypted option can only be used in combination with secret "
                "option")

        model = cls.model(
            id=kvp_id,
            name=name,
            description=description,
            value=value,
            secret=secret,
            scope=scope,
            expire_timestamp=expire_timestamp,
        )

        return model
Example #23
0
 def test_symmetric_encrypt_decrypt_short_string_needs_to_be_padded(self):
     original = u'a'
     crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key, original)
     plain = symmetric_decrypt(CryptoUtilsTestCase.test_crypto_key, crypto)
     self.assertEqual(plain, original)
Example #24
0
 def test_symmetric_encrypt_decrypt(self):
     original = 'secret'
     crypto = crypto_utils.symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key, original)
     plain = crypto_utils.symmetric_decrypt(CryptoUtilsTestCase.test_crypto_key, crypto)
     self.assertEqual(plain, original)
Example #25
0
    def to_model(cls, kvp):
        if not KeyValuePairAPI.crypto_setup:
            KeyValuePairAPI._setup_crypto()

        kvp_id = getattr(kvp, 'id', None)
        name = getattr(kvp, 'name', None)
        description = getattr(kvp, 'description', None)
        value = kvp.value
        original_value = value
        secret = False

        if getattr(kvp, 'ttl', None):
            expire_timestamp = (date_utils.get_datetime_utc_now() +
                                datetime.timedelta(seconds=kvp.ttl))
        else:
            expire_timestamp = None

        encrypted = getattr(kvp, 'encrypted', False)
        secret = getattr(kvp, 'secret', False)

        # If user transmitted the value in an pre-encrypted format, we perform the decryption here
        # to ensure data integrity. Besides that, we store data as-is.
        # Keep in mind that encrypted=True also always implies secret=True. If we didn't do
        # that and supported encrypted=True, secret=False, this would allow users to decrypt
        # any encrypted value.
        if encrypted:
            secret = True

            cls._verif_key_is_set_up(name=name)

            try:
                symmetric_decrypt(KeyValuePairAPI.crypto_key, value)
            except Exception:
                msg = ('Failed to verify the integrity of the provided value for key "%s". Ensure '
                       'that the value is encrypted with the correct key and not corrupted.' %
                       (name))
                raise ValueError(msg)

            # Additional safety check to ensure that the value hasn't been decrypted
            assert value == original_value
        elif secret:
            cls._verif_key_is_set_up(name=name)

            value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value)

        scope = getattr(kvp, 'scope', FULL_SYSTEM_SCOPE)

        if scope not in ALLOWED_SCOPES:
            raise InvalidScopeException('Invalid scope "%s"! Allowed scopes are %s.' % (
                scope, ALLOWED_SCOPES)
            )

        # NOTE: For security reasons, encrypted always implies secret=True. See comment
        # above for explanation.
        if encrypted and not secret:
            raise ValueError('encrypted option can only be used in combination with secret '
                             'option')

        model = cls.model(id=kvp_id, name=name, description=description, value=value,
                          secret=secret, scope=scope,
                          expire_timestamp=expire_timestamp)

        return model
Example #26
0
 def test_symmetric_encrypt_decrypt_short_string_needs_to_be_padded(self):
     original = u'a'
     crypto = symmetric_encrypt(CryptoUtilsTestCase.test_crypto_key,
                                original)
     plain = symmetric_decrypt(CryptoUtilsTestCase.test_crypto_key, crypto)
     self.assertEqual(plain, original)