)]}'
{"keystoneclient/middleware/auth_token.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"f480038f159d8d56ba4b133ba57ebd21a4ebfa80","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                self._memcache_security_strategy.upper()"},{"line_number":473,"context_line":"            if isinstance(self._memcache_security_strategy, six.text_type):"},{"line_number":474,"context_line":"                self._memcache_security_strategy \u003d \\"},{"line_number":475,"context_line":"                    self._memcache_security_strategy.encode(\u0027utf-8\u0027)"},{"line_number":476,"context_line":"        self._memcache_secret_key \u003d \\"},{"line_number":477,"context_line":"            self._conf_get(\u0027memcache_secret_key\u0027)"},{"line_number":478,"context_line":"        if isinstance(self._memcache_secret_key, six.text_type):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BU7I%3D","line":475,"updated":"2014-01-28 00:25:05.000000000","message":"use () to continue lines rather than \\. See http://www.python.org/dev/peps/pep-0008/#maximum-line-length\n\nI don\u0027t see why self._memcache_security_strategy shouldn\u0027t be a string here... it was the value read from the config file, which is going to be a string, so just leave it that way until you need it.","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"539ee2483059f9dc7af7f28d247fc866ce10d091","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                self._memcache_security_strategy.upper()"},{"line_number":473,"context_line":"            if isinstance(self._memcache_security_strategy, six.text_type):"},{"line_number":474,"context_line":"                self._memcache_security_strategy \u003d \\"},{"line_number":475,"context_line":"                    self._memcache_security_strategy.encode(\u0027utf-8\u0027)"},{"line_number":476,"context_line":"        self._memcache_secret_key \u003d \\"},{"line_number":477,"context_line":"            self._conf_get(\u0027memcache_secret_key\u0027)"},{"line_number":478,"context_line":"        if isinstance(self._memcache_secret_key, six.text_type):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BQAY%3D","line":475,"in_reply_to":"AAAAUH%2F%2BU7I%3D","updated":"2014-01-28 17:52:23.000000000","message":"OK, will do.","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"f480038f159d8d56ba4b133ba57ebd21a4ebfa80","unresolved":false,"context_lines":[{"line_number":1063,"context_line":"        if self._memcache_security_strategy is None:"},{"line_number":1064,"context_line":"            cache_key \u003d CACHE_KEY_TEMPLATE % token_id"},{"line_number":1065,"context_line":"            data_to_store \u003d serialized_data"},{"line_number":1066,"context_line":"        else:"},{"line_number":1067,"context_line":"            keys \u003d memcache_crypt.derive_keys("},{"line_number":1068,"context_line":"                token_id,"},{"line_number":1069,"context_line":"                self._memcache_secret_key,"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BU4w%3D","line":1066,"updated":"2014-01-28 00:25:05.000000000","message":"so this would be like\n\n security_strategy \u003d self._memcache_security_strategy\n if isinstance(security_strategy, six.string_types):\n     security_strategy \u003d security_strategy.decode(\u0027utf-8\u0027)\n\n then use that at 1070","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"f480038f159d8d56ba4b133ba57ebd21a4ebfa80","unresolved":false,"context_lines":[{"line_number":1070,"context_line":"                self._memcache_security_strategy)"},{"line_number":1071,"context_line":"            cache_key \u003d CACHE_KEY_TEMPLATE % memcache_crypt.get_cache_key(keys)"},{"line_number":1072,"context_line":"            if isinstance(serialized_data, six.text_type):"},{"line_number":1073,"context_line":"                serialized_data \u003d serialized_data.encode(\u0027utf-8\u0027)"},{"line_number":1074,"context_line":"            data_to_store \u003d memcache_crypt.protect_data(keys, serialized_data)"},{"line_number":1075,"context_line":""},{"line_number":1076,"context_line":"        # Historically the swift cache connection used the argument"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BU4U%3D","line":1073,"updated":"2014-01-28 00:25:05.000000000","message":"we just built serialized_data at line 1062, and we don\u0027t know what the type is?","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"539ee2483059f9dc7af7f28d247fc866ce10d091","unresolved":false,"context_lines":[{"line_number":1070,"context_line":"                self._memcache_security_strategy)"},{"line_number":1071,"context_line":"            cache_key \u003d CACHE_KEY_TEMPLATE % memcache_crypt.get_cache_key(keys)"},{"line_number":1072,"context_line":"            if isinstance(serialized_data, six.text_type):"},{"line_number":1073,"context_line":"                serialized_data \u003d serialized_data.encode(\u0027utf-8\u0027)"},{"line_number":1074,"context_line":"            data_to_store \u003d memcache_crypt.protect_data(keys, serialized_data)"},{"line_number":1075,"context_line":""},{"line_number":1076,"context_line":"        # Historically the swift cache connection used the argument"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BQAE%3D","line":1073,"in_reply_to":"AAAAUH%2F%2BU4U%3D","updated":"2014-01-28 17:52:23.000000000","message":"In Python 2, json.dumps() return bytes, but not in Python 3.","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"f480038f159d8d56ba4b133ba57ebd21a4ebfa80","unresolved":false,"context_lines":[{"line_number":1080,"context_line":"        # this could get removed."},{"line_number":1081,"context_line":"        try:"},{"line_number":1082,"context_line":"            self._cache.set(cache_key,"},{"line_number":1083,"context_line":"                            data_to_store,"},{"line_number":1084,"context_line":"                            time\u003dself.token_cache_time)"},{"line_number":1085,"context_line":"        except(TypeError):"},{"line_number":1086,"context_line":"            self._cache.set(cache_key,"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BU4I%3D","line":1083,"updated":"2014-01-28 00:25:05.000000000","message":"seems like sometimes we\u0027re storing a string and sometimes it\u0027s bytes... e.g., at 1062 it might be string or bytes and then it\u0027s converted to bytes at 1074?","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"539ee2483059f9dc7af7f28d247fc866ce10d091","unresolved":false,"context_lines":[{"line_number":1080,"context_line":"        # this could get removed."},{"line_number":1081,"context_line":"        try:"},{"line_number":1082,"context_line":"            self._cache.set(cache_key,"},{"line_number":1083,"context_line":"                            data_to_store,"},{"line_number":1084,"context_line":"                            time\u003dself.token_cache_time)"},{"line_number":1085,"context_line":"        except(TypeError):"},{"line_number":1086,"context_line":"            self._cache.set(cache_key,"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAUH%2F%2BP%2FA%3D","line":1083,"in_reply_to":"AAAAUH%2F%2BU4I%3D","updated":"2014-01-28 17:52:23.000000000","message":"indeed, data_to_store should always be bytes, I missed the \u0027if\u0027.","commit_id":"c734ba361a5d0e79cc0ad895bb479f46d570e1a3"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e0d0c10dca65762c7ff56412b28e6dfd8435223b","unresolved":false,"context_lines":[{"line_number":491,"context_line":""},{"line_number":492,"context_line":"    def _assert_valid_memcache_protection_config(self):"},{"line_number":493,"context_line":"        if self._memcache_security_strategy:"},{"line_number":494,"context_line":"            if self._memcache_security_strategy not in (b\u0027MAC\u0027, b\u0027ENCRYPT\u0027):"},{"line_number":495,"context_line":"                raise ConfigurationError(\u0027memcache_security_strategy must be \u0027"},{"line_number":496,"context_line":"                                         \u0027ENCRYPT or MAC\u0027)"},{"line_number":497,"context_line":"            if not self._memcache_secret_key:"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BP4w%3D","line":494,"updated":"2014-01-28 20:49:41.000000000","message":"I think self._memcache_security_strategy is a string now, so can revert this change.","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"54a268444311211ac1e32f231e31f85423493836","unresolved":false,"context_lines":[{"line_number":491,"context_line":""},{"line_number":492,"context_line":"    def _assert_valid_memcache_protection_config(self):"},{"line_number":493,"context_line":"        if self._memcache_security_strategy:"},{"line_number":494,"context_line":"            if self._memcache_security_strategy not in (b\u0027MAC\u0027, b\u0027ENCRYPT\u0027):"},{"line_number":495,"context_line":"                raise ConfigurationError(\u0027memcache_security_strategy must be \u0027"},{"line_number":496,"context_line":"                                         \u0027ENCRYPT or MAC\u0027)"},{"line_number":497,"context_line":"            if not self._memcache_secret_key:"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BNwo%3D","line":494,"in_reply_to":"AAAAUH%2F%2BP4w%3D","updated":"2014-01-29 00:30:26.000000000","message":"Done","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e0d0c10dca65762c7ff56412b28e6dfd8435223b","unresolved":false,"context_lines":[{"line_number":994,"context_line":""},{"line_number":995,"context_line":"        if self._cache and token_id:"},{"line_number":996,"context_line":"            if self._memcache_security_strategy is None:"},{"line_number":997,"context_line":"                key \u003d CACHE_KEY_TEMPLATE % token_id"},{"line_number":998,"context_line":"                serialized \u003d self._cache.get(key)"},{"line_number":999,"context_line":"            else:"},{"line_number":1000,"context_line":"                keys \u003d memcache_crypt.derive_keys("}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BO7k%3D","line":997,"updated":"2014-01-28 20:49:41.000000000","message":"do we get strings or bytes out of _cache? seems like it should be strings, so let\u0027s not decode in this case.","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"54a268444311211ac1e32f231e31f85423493836","unresolved":false,"context_lines":[{"line_number":994,"context_line":""},{"line_number":995,"context_line":"        if self._cache and token_id:"},{"line_number":996,"context_line":"            if self._memcache_security_strategy is None:"},{"line_number":997,"context_line":"                key \u003d CACHE_KEY_TEMPLATE % token_id"},{"line_number":998,"context_line":"                serialized \u003d self._cache.get(key)"},{"line_number":999,"context_line":"            else:"},{"line_number":1000,"context_line":"                keys \u003d memcache_crypt.derive_keys("}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BNwY%3D","line":997,"in_reply_to":"AAAAUH%2F%2BO7k%3D","updated":"2014-01-29 00:30:26.000000000","message":"I think we get whatever we put in there in the first place. Then again, in Python 2, strings __are__ bytes.","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e0d0c10dca65762c7ff56412b28e6dfd8435223b","unresolved":false,"context_lines":[{"line_number":1006,"context_line":"                raw_cached \u003d self._cache.get(cache_key)"},{"line_number":1007,"context_line":"                try:"},{"line_number":1008,"context_line":"                    # unprotect_data will return None if raw_cached is None"},{"line_number":1009,"context_line":"                    serialized \u003d memcache_crypt.unprotect_data(keys,"},{"line_number":1010,"context_line":"                                                               raw_cached)"},{"line_number":1011,"context_line":"                except Exception:"},{"line_number":1012,"context_line":"                    msg \u003d \u0027Failed to decrypt/verify cache data\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BO7U%3D","line":1009,"updated":"2014-01-28 20:49:41.000000000","message":"we know we get bytes here, so decode in this case.\n\nSuggest move the code from 1024 to after this line, since don\u0027t need to check if need to decode in case where get serialized from _cache.","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e0d0c10dca65762c7ff56412b28e6dfd8435223b","unresolved":false,"context_lines":[{"line_number":1077,"context_line":"        # grizzly, we still need to handle folsom for a while until"},{"line_number":1078,"context_line":"        # this could get removed."},{"line_number":1079,"context_line":"        try:"},{"line_number":1080,"context_line":"            self._cache.set(cache_key,"},{"line_number":1081,"context_line":"                            data_to_store,"},{"line_number":1082,"context_line":"                            time\u003dself.token_cache_time)"},{"line_number":1083,"context_line":"        except(TypeError):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BO58%3D","line":1080,"updated":"2014-01-28 20:49:41.000000000","message":"can\u0027t we store strings in _cache?","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"54a268444311211ac1e32f231e31f85423493836","unresolved":false,"context_lines":[{"line_number":1077,"context_line":"        # grizzly, we still need to handle folsom for a while until"},{"line_number":1078,"context_line":"        # this could get removed."},{"line_number":1079,"context_line":"        try:"},{"line_number":1080,"context_line":"            self._cache.set(cache_key,"},{"line_number":1081,"context_line":"                            data_to_store,"},{"line_number":1082,"context_line":"                            time\u003dself.token_cache_time)"},{"line_number":1083,"context_line":"        except(TypeError):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BNvw%3D","line":1080,"in_reply_to":"AAAAUH%2F%2BO58%3D","updated":"2014-01-29 00:30:26.000000000","message":"The idea is to make sure that data_to_store is bytes, since protect_data() returns bytes. That\u0027s why I encoded serialized_data before the if/else: \n\n- if we get inside the if, data_to_store is set to a bytes value\n- if we get inside the else, data_to_store is set to the output of protect_data(), which is bytes.\n\nThis is why we have to decode() the value we get in _cache_get. And if we don\u0027t, the call to jsonutils.loads() will fail anyway.","commit_id":"93c305975f1c02df49ce4e5512b4ce4977cea822"}],"keystoneclient/middleware/memcache_crypt.py":[{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        return f(*args, **kwds)"},{"line_number":83,"context_line":"    return wrapper"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"def constant_time_compare(first, second):"},{"line_number":87,"context_line":"    \"\"\"Returns True if both string inputs are equal, otherwise False."},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHr0%3D","line":85,"updated":"2014-01-17 08:48:33.000000000","message":"Python 3.3 provides a new safe hmac.compare_digest() function. Its C implementation has more reliable timing and so is safer than the Python version. constant_time_compare() should just be an alias of hmac.compare_digest() on Python 3.3.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"2d7aac1ff006b8edbf627573ebd3e26006b79e8e","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        return f(*args, **kwds)"},{"line_number":83,"context_line":"    return wrapper"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"def constant_time_compare(first, second):"},{"line_number":87,"context_line":"    \"\"\"Returns True if both string inputs are equal, otherwise False."},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FFOU%3D","line":85,"in_reply_to":"AAAAUH%2F%2FHr0%3D","updated":"2014-01-17 16:23:48.000000000","message":"Will do.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":93,"context_line":"    if len(first) !\u003d len(second):"},{"line_number":94,"context_line":"        return False"},{"line_number":95,"context_line":"    result \u003d 0"},{"line_number":96,"context_line":"    for x, y in zip(first, second):"},{"line_number":97,"context_line":"        result |\u003d ord(x) ^ ord(y)"},{"line_number":98,"context_line":"    return result \u003d\u003d 0"},{"line_number":99,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHpw%3D","line":96,"updated":"2014-01-17 08:48:33.000000000","message":"A digest is a bytestring, it looks like this implementation only works on Python 2. Iterating on a byte string in Python 3 yields integers, not substrings of 1 byte. If you reuse hmac.compare_digest(), it doesn\u0027t matter on Python 3.3, but it matters on Python 3.2. I don\u0027t know if OpenStack should support Python 3.2?\n\nOn Python 3.2, you can add a new version without ord(). Something like:\n\nif sys.version_info \u003e (3,):\n    for x, y in zip(first, second):\n        result |\u003d x ^ y\nelse:\n    for x, y in zip(first, second):\n        result |\u003d ord(x) ^ ord(y)\n\nhmac.compare_digest() of Python 3.3 supports Unicode strings but if they only contains ASCII characters (U+0000-U+007F). Calling str.encode(\"ascii\") timing (to convert to bytes or to check if the strings are pure ASCII) depends on the length of the string. I don\u0027t know if it matters. hmac.compare_digest() may leak the length of the strings according to the documentation.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"4a4331acf8e2476885f11964a2b68b239a1f13b5","unresolved":false,"context_lines":[{"line_number":93,"context_line":"    if len(first) !\u003d len(second):"},{"line_number":94,"context_line":"        return False"},{"line_number":95,"context_line":"    result \u003d 0"},{"line_number":96,"context_line":"    for x, y in zip(first, second):"},{"line_number":97,"context_line":"        result |\u003d ord(x) ^ ord(y)"},{"line_number":98,"context_line":"    return result \u003d\u003d 0"},{"line_number":99,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2Bl64%3D","line":96,"in_reply_to":"AAAAUH%2F%2BoYc%3D","updated":"2014-01-24 02:21:49.000000000","message":"Done","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":2230,"name":"Paul McMillan","email":"paul@mcmillan.ws","username":"paul-mcmillan"},"change_message_id":"c4d0e261d6f3440115f7a8190fd0d393e471d2bb","unresolved":false,"context_lines":[{"line_number":93,"context_line":"    if len(first) !\u003d len(second):"},{"line_number":94,"context_line":"        return False"},{"line_number":95,"context_line":"    result \u003d 0"},{"line_number":96,"context_line":"    for x, y in zip(first, second):"},{"line_number":97,"context_line":"        result |\u003d ord(x) ^ ord(y)"},{"line_number":98,"context_line":"    return result \u003d\u003d 0"},{"line_number":99,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2BoYc%3D","line":96,"in_reply_to":"AAAAUH%2F%2FFOI%3D","updated":"2014-01-23 18:30:31.000000000","message":"You want to check to make sure both strings are bytes in py3. I suggest you copy the Django implementation, which does so.\n\nhttps://github.com/django/django/blob/master/django/utils/crypto.py#L77","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"2d7aac1ff006b8edbf627573ebd3e26006b79e8e","unresolved":false,"context_lines":[{"line_number":93,"context_line":"    if len(first) !\u003d len(second):"},{"line_number":94,"context_line":"        return False"},{"line_number":95,"context_line":"    result \u003d 0"},{"line_number":96,"context_line":"    for x, y in zip(first, second):"},{"line_number":97,"context_line":"        result |\u003d ord(x) ^ ord(y)"},{"line_number":98,"context_line":"    return result \u003d\u003d 0"},{"line_number":99,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FFOI%3D","line":96,"in_reply_to":"AAAAUH%2F%2FHpw%3D","updated":"2014-01-17 16:23:48.000000000","message":"Wow. OK, I\u0027ll have to try all that.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":112,"context_line":"    for each desired key."},{"line_number":113,"context_line":"    \"\"\""},{"line_number":114,"context_line":"    if isinstance(secret, six.text_type):"},{"line_number":115,"context_line":"        secret \u003d secret.encode()"},{"line_number":116,"context_line":"    msg \u003d token + strategy"},{"line_number":117,"context_line":"    if isinstance(msg, six.text_type):"},{"line_number":118,"context_line":"        msg \u003d msg.encode()"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHtQ%3D","line":115,"updated":"2014-01-17 08:48:33.000000000","message":"On Python2, unicode.encode() uses sys.getdefaultencoding() which is \"ascii\" by default. I would prefer UTF-8, which is also the default on Python 3. So replace .encode() with .encode(\"utf-8\").\n\nI\u0027m not sure that derive_keys() is supposed to accept Unicode, the encode should maybe done in the caller of the function.\n\nIf derive_keys() is changed to accept Unicode, it should be at least documented in the docstring.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"2d7aac1ff006b8edbf627573ebd3e26006b79e8e","unresolved":false,"context_lines":[{"line_number":112,"context_line":"    for each desired key."},{"line_number":113,"context_line":"    \"\"\""},{"line_number":114,"context_line":"    if isinstance(secret, six.text_type):"},{"line_number":115,"context_line":"        secret \u003d secret.encode()"},{"line_number":116,"context_line":"    msg \u003d token + strategy"},{"line_number":117,"context_line":"    if isinstance(msg, six.text_type):"},{"line_number":118,"context_line":"        msg \u003d msg.encode()"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FFNQ%3D","line":115,"in_reply_to":"AAAAUH%2F%2FHtQ%3D","updated":"2014-01-17 16:23:48.000000000","message":"Yeah, I tried to change only the implemntation of the functions in this file, so that it would not change anything for the callers, leaving the API untouched. Now, I do not know the code, so I think I could use a few pointers from the core devs.\n\nJamie, Brant (and otehrs :p), what would be the way to go ?","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        secret \u003d secret.encode()"},{"line_number":116,"context_line":"    msg \u003d token + strategy"},{"line_number":117,"context_line":"    if isinstance(msg, six.text_type):"},{"line_number":118,"context_line":"        msg \u003d msg.encode()"},{"line_number":119,"context_line":"    digest \u003d hmac.new(secret, msg, HASH_FUNCTION).digest()"},{"line_number":120,"context_line":"    return {\u0027CACHE_KEY\u0027: digest[:DIGEST_SPLIT],"},{"line_number":121,"context_line":"            \u0027MAC\u0027: digest[DIGEST_SPLIT: 2 * DIGEST_SPLIT],"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHs8%3D","line":118,"updated":"2014-01-17 08:48:33.000000000","message":"If you choose to accept Unicode parameters, you should encode token and strategy, not msg, to raise encoding errors earlier (so it\u0027s possible to know if the error comes from token or strategy). For your information, the UTF-8 encoder of Python 3 now raises UnicodeEncodeError on surrogate characters (U+D800..U+DFFF).","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":126,"context_line":"def sign_data(key, data):"},{"line_number":127,"context_line":"    \"\"\"Sign the data using the defined function and the derived key.\"\"\""},{"line_number":128,"context_line":"    if isinstance(data, six.text_type):"},{"line_number":129,"context_line":"        data \u003d data.encode()"},{"line_number":130,"context_line":"    mac \u003d hmac.new(key, data, HASH_FUNCTION).digest()"},{"line_number":131,"context_line":"    return base64.b64encode(mac)"},{"line_number":132,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHss%3D","line":129,"updated":"2014-01-17 08:48:33.000000000","message":"Same comments:\n- does it make sense to accept Unicode here?\n- if yes: use explicit \"utf-8\" encoding, mention the accepted Unicode type and the UTF-8 encoding in the docstring","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":139,"context_line":"    \"\"\""},{"line_number":140,"context_line":"    iv \u003d os.urandom(16)"},{"line_number":141,"context_line":"    cipher \u003d AES.new(key, AES.MODE_CBC, iv)"},{"line_number":142,"context_line":"    if isinstance(data, six.text_type):"},{"line_number":143,"context_line":"        padding \u003d 16 - len(data.encode(\u0027utf-8\u0027)) % 16"},{"line_number":144,"context_line":"    else:"},{"line_number":145,"context_line":"        padding \u003d 16 - len(data) % 16"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHsk%3D","line":142,"updated":"2014-01-17 08:48:33.000000000","message":"ditto","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":153,"context_line":"    cipher \u003d AES.new(key, AES.MODE_CBC, iv)"},{"line_number":154,"context_line":"    try:"},{"line_number":155,"context_line":"        result \u003d cipher.decrypt(data[16:])"},{"line_number":156,"context_line":"        if not isinstance(result, six.string_types):"},{"line_number":157,"context_line":"            result \u003d result.decode()"},{"line_number":158,"context_line":"    except Exception:"},{"line_number":159,"context_line":"        raise DecryptError(\u0027Encrypted data appears to be corrupted.\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHsg%3D","line":156,"updated":"2014-01-17 08:48:33.000000000","message":"ditto","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":172,"context_line":"    if keys[\u0027strategy\u0027] \u003d\u003d \u0027ENCRYPT\u0027:"},{"line_number":173,"context_line":"        data \u003d encrypt_data(keys[\u0027ENCRYPTION\u0027], data)"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"    if isinstance(data, six.text_type):"},{"line_number":176,"context_line":"        data \u003d data.encode()"},{"line_number":177,"context_line":"    encoded_data \u003d base64.b64encode(data)"},{"line_number":178,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHsY%3D","line":175,"updated":"2014-01-17 08:48:33.000000000","message":"etc.","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"37ae0bdd61f5fe85726002e1e3a81de97bc6b672","unresolved":false,"context_lines":[{"line_number":197,"context_line":"        signed_data[DIGEST_LENGTH_B64:])"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    # Then verify that it matches the provided value"},{"line_number":200,"context_line":"    provided_mac \u003d provided_mac.decode()"},{"line_number":201,"context_line":"    calculated_mac \u003d calculated_mac.decode()"},{"line_number":202,"context_line":"    if not constant_time_compare(provided_mac, calculated_mac):"},{"line_number":203,"context_line":"        raise InvalidMacError(\u0027Invalid MAC; data appears to be corrupted.\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FHpE%3D","line":200,"updated":"2014-01-17 08:48:33.000000000","message":"ditto","commit_id":"10b312eb14d2e45147b8715b26971cdc2b60653e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"76a81b513beea09058789e875d58a89c29ea2bf2","unresolved":false,"context_lines":[{"line_number":142,"context_line":"    cipher \u003d AES.new(key, AES.MODE_CBC, iv)"},{"line_number":143,"context_line":"    padding \u003d 16 - len(data) % 16"},{"line_number":144,"context_line":"    padding_char \u003d chr(padding)"},{"line_number":145,"context_line":"    if isinstance(padding_char, six.text_type):"},{"line_number":146,"context_line":"        padding_char \u003d padding_char.encode(\u0027utf-8\u0027)"},{"line_number":147,"context_line":"    return iv + cipher.encrypt(data + padding_char * padding)"},{"line_number":148,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAUH%2F%2BY0k%3D","line":145,"updated":"2014-01-27 13:33:03.000000000","message":"On Python 3, you should directly create a bytes string:\n\nif six.PY3:\n   padding_char \u003d bytes((padding,))\nelse:\n   padding_char \u003d chr(padding)\n\nchr(padding).encode(\u0027utf-8\u0027) changes the result on Python 3 for padding \u003e\u003d 128.","commit_id":"0e81044c133af826496f8c1c28a3d6569c9ac83e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"76a81b513beea09058789e875d58a89c29ea2bf2","unresolved":false,"context_lines":[{"line_number":161,"context_line":"    # the plaintext"},{"line_number":162,"context_line":"    if not isinstance(result, six.string_types):"},{"line_number":163,"context_line":"        result \u003d result.decode(\u0027utf-8\u0027)"},{"line_number":164,"context_line":"        padding \u003d ord(result[-1])"},{"line_number":165,"context_line":"        return result[:-1 * padding].encode(\u0027utf-8\u0027)"},{"line_number":166,"context_line":"    else:"},{"line_number":167,"context_line":"        padding \u003d ord(result[-1])"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAUH%2F%2BY0I%3D","line":164,"updated":"2014-01-27 13:33:03.000000000","message":"Decode from UTF-8 before getting the padding looks wrong to me. You should use:\n\nif six.PY3:\n   padding \u003d result[-1]\n   return result[:-padding].decode(\u0027utf-8\u0027)\nelse:\n   ...\n\n(-1 * padding can be simplified to -padding ;-))","commit_id":"0e81044c133af826496f8c1c28a3d6569c9ac83e"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"1c49d8de2d9373b3ff73aff9eb047becdb6840d1","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    iv \u003d os.urandom(16)"},{"line_number":142,"context_line":"    cipher \u003d AES.new(key, AES.MODE_CBC, iv)"},{"line_number":143,"context_line":"    padding \u003d 16 - len(data) % 16"},{"line_number":144,"context_line":"    return iv + cipher.encrypt(data + six.int2byte(padding) * padding)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"@assert_crypto_availability"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9rbk%3D","line":144,"updated":"2014-02-05 02:27:59.000000000","message":"Note to reviewers: http://pythonhosted.org/six/#six.int2byte","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"1c49d8de2d9373b3ff73aff9eb047becdb6840d1","unresolved":false,"context_lines":[{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    # Strip the last n padding bytes where n is the last value in"},{"line_number":158,"context_line":"    # the plaintext"},{"line_number":159,"context_line":"    return result[:-1 * six.byte2int([result[-1]])]"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"def protect_data(keys, data):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9rbs%3D","line":159,"updated":"2014-02-05 02:27:59.000000000","message":"Note to reviewers: http://pythonhosted.org/six/#six.byte2int","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    # Strip the last n padding bytes where n is the last value in"},{"line_number":158,"context_line":"    # the plaintext"},{"line_number":159,"context_line":"    return result[:-1 * six.byte2int([result[-1]])]"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"def protect_data(keys, data):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9jw8%3D","line":159,"in_reply_to":"AAAAUH%2F9puw%3D","updated":"2014-02-06 02:25:03.000000000","message":"\u003e\u003e\u003e l\u003d[1,2,3]\n\n\u003e\u003e\u003e l[-1]\n\n3\n\n\u003e\u003e\u003e l[-2:1]\n\n[]\n\nSo I guess you meant result[-1:]. This would probably work, but I\u0027m not sure whether it\u0027s clearer/more efficient.","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"f4b74b86e51befdbfaefb601fe8c90e2a8a63a29","unresolved":false,"context_lines":[{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    # Strip the last n padding bytes where n is the last value in"},{"line_number":158,"context_line":"    # the plaintext"},{"line_number":159,"context_line":"    return result[:-1 * six.byte2int([result[-1]])]"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"def protect_data(keys, data):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9puw%3D","line":159,"in_reply_to":"AAAAUH%2F9rbs%3D","updated":"2014-02-05 10:34:54.000000000","message":"Does six.byte2int(result[-2:-1]) work?","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"}],"keystoneclient/tests/test_memcache_crypt.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"6143db5efaa9a176dff83b3acd0a43176764df96","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class MemcacheCryptPositiveTests(testtools.TestCase):"},{"line_number":22,"context_line":"    def _setup_keys(self, strategy):"},{"line_number":23,"context_line":"        if isinstance(strategy, six.text_type):"},{"line_number":24,"context_line":"            strategy \u003d strategy.encode(\u0027utf-8\u0027)"},{"line_number":25,"context_line":"        return memcache_crypt.derive_keys(b\u0027token\u0027, b\u0027secret\u0027, strategy)"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9sRE%3D","line":23,"updated":"2014-02-04 23:04:16.000000000","message":"seems like for a test we should be able to pass in what we need rather than having to figure it out.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"e571c24f7ab603fc585faa6ee76a0ff31a1afe62","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class MemcacheCryptPositiveTests(testtools.TestCase):"},{"line_number":22,"context_line":"    def _setup_keys(self, strategy):"},{"line_number":23,"context_line":"        if isinstance(strategy, six.text_type):"},{"line_number":24,"context_line":"            strategy \u003d strategy.encode(\u0027utf-8\u0027)"},{"line_number":25,"context_line":"        return memcache_crypt.derive_keys(b\u0027token\u0027, b\u0027secret\u0027, strategy)"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9rj4%3D","line":23,"in_reply_to":"AAAAUH%2F9sRE%3D","updated":"2014-02-05 02:26:38.000000000","message":"Indeed, I\u0027ll remove this.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"6143db5efaa9a176dff83b3acd0a43176764df96","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        self.assertFalse(ctc(\u0027\u0027, \u0027abc\u0027))"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def test_derive_keys(self):"},{"line_number":39,"context_line":"        keys \u003d self._setup_keys(\u0027strategy\u0027)"},{"line_number":40,"context_line":"        self.assertEqual(len(keys[\u0027ENCRYPTION\u0027]),"},{"line_number":41,"context_line":"                         len(keys[\u0027CACHE_KEY\u0027]))"},{"line_number":42,"context_line":"        self.assertEqual(len(keys[\u0027CACHE_KEY\u0027]),"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9sQ4%3D","line":39,"updated":"2014-02-04 23:04:16.000000000","message":"can\u0027t the calls to _setup_keys use b\u0027strategy\u0027?","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"e571c24f7ab603fc585faa6ee76a0ff31a1afe62","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        self.assertFalse(ctc(\u0027\u0027, \u0027abc\u0027))"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def test_derive_keys(self):"},{"line_number":39,"context_line":"        keys \u003d self._setup_keys(\u0027strategy\u0027)"},{"line_number":40,"context_line":"        self.assertEqual(len(keys[\u0027ENCRYPTION\u0027]),"},{"line_number":41,"context_line":"                         len(keys[\u0027CACHE_KEY\u0027]))"},{"line_number":42,"context_line":"        self.assertEqual(len(keys[\u0027CACHE_KEY\u0027]),"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9rkE%3D","line":39,"in_reply_to":"AAAAUH%2F9sQ4%3D","updated":"2014-02-05 02:26:38.000000000","message":"Yes, it makes more sense.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"6143db5efaa9a176dff83b3acd0a43176764df96","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def test_sign_data(self):"},{"line_number":54,"context_line":"        keys \u003d self._setup_keys(\u0027MAC\u0027)"},{"line_number":55,"context_line":"        sig \u003d memcache_crypt.sign_data(keys[\u0027MAC\u0027], \u0027data\u0027.encode(\u0027utf-8\u0027))"},{"line_number":56,"context_line":"        self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64)"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def test_encryption(self):"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9sQY%3D","line":55,"updated":"2014-02-04 23:04:16.000000000","message":"isn\u0027t \u0027data\u0027.encode(\u0027utf-8\u0027) the same as b\u0027data\u0027 ?","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"e571c24f7ab603fc585faa6ee76a0ff31a1afe62","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def test_sign_data(self):"},{"line_number":54,"context_line":"        keys \u003d self._setup_keys(\u0027MAC\u0027)"},{"line_number":55,"context_line":"        sig \u003d memcache_crypt.sign_data(keys[\u0027MAC\u0027], \u0027data\u0027.encode(\u0027utf-8\u0027))"},{"line_number":56,"context_line":"        self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64)"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def test_encryption(self):"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9roI%3D","line":55,"in_reply_to":"AAAAUH%2F9sQY%3D","updated":"2014-02-05 02:26:38.000000000","message":"Oops, must have hit \u0027repeat\u0027 in vim too quickly :) You\u0027re right.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"6143db5efaa9a176dff83b3acd0a43176764df96","unresolved":false,"context_lines":[{"line_number":63,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":64,"context_line":"                encoded_data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":65,"context_line":"            else:"},{"line_number":66,"context_line":"                encoded_data \u003d data"},{"line_number":67,"context_line":"            crypt \u003d memcache_crypt.encrypt_data(keys[\u0027ENCRYPTION\u0027],"},{"line_number":68,"context_line":"                                                encoded_data)"},{"line_number":69,"context_line":"            decrypt \u003d memcache_crypt.decrypt_data(keys[\u0027ENCRYPTION\u0027], crypt)"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9sQA%3D","line":66,"updated":"2014-02-04 23:04:16.000000000","message":"seems like the data defined on line 61 should be bytes instead or line 63-66.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"e571c24f7ab603fc585faa6ee76a0ff31a1afe62","unresolved":false,"context_lines":[{"line_number":63,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":64,"context_line":"                encoded_data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":65,"context_line":"            else:"},{"line_number":66,"context_line":"                encoded_data \u003d data"},{"line_number":67,"context_line":"            crypt \u003d memcache_crypt.encrypt_data(keys[\u0027ENCRYPTION\u0027],"},{"line_number":68,"context_line":"                                                encoded_data)"},{"line_number":69,"context_line":"            decrypt \u003d memcache_crypt.decrypt_data(keys[\u0027ENCRYPTION\u0027], crypt)"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9rcg%3D","line":66,"in_reply_to":"AAAAUH%2F9sQA%3D","updated":"2014-02-05 02:26:38.000000000","message":"Indeed.","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"6143db5efaa9a176dff83b3acd0a43176764df96","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        for strategy in [\u0027MAC\u0027, \u0027ENCRYPT\u0027]:"},{"line_number":78,"context_line":"            keys \u003d self._setup_keys(strategy)"},{"line_number":79,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":80,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":81,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":82,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":83,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9sP0%3D","line":80,"updated":"2014-02-04 23:04:16.000000000","message":"change line 76 to b\u0027My Pretty Little Data\u0027","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"e571c24f7ab603fc585faa6ee76a0ff31a1afe62","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        for strategy in [\u0027MAC\u0027, \u0027ENCRYPT\u0027]:"},{"line_number":78,"context_line":"            keys \u003d self._setup_keys(strategy)"},{"line_number":79,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":80,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":81,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":82,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":83,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAUH%2F9rn4%3D","line":80,"in_reply_to":"AAAAUH%2F9sP0%3D","updated":"2014-02-05 02:26:38.000000000","message":"Done","commit_id":"b7b581fecc53501d2f6573d0651d526b01e93c90"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"25a7747e799f4d83a8887e2db404212d22666970","unresolved":false,"context_lines":[{"line_number":26,"context_line":"        # make sure it works as a compare, the \"constant time\" aspect"},{"line_number":27,"context_line":"        # isn\u0027t appropriate to test in unittests"},{"line_number":28,"context_line":"        ctc \u003d memcache_crypt.constant_time_compare"},{"line_number":29,"context_line":"        self.assertTrue(ctc(\u0027abcd\u0027, \u0027abcd\u0027))"},{"line_number":30,"context_line":"        self.assertTrue(ctc(\u0027\u0027, \u0027\u0027))"},{"line_number":31,"context_line":"        self.assertFalse(ctc(\u0027abcd\u0027, \u0027efgh\u0027))"},{"line_number":32,"context_line":"        self.assertFalse(ctc(\u0027abc\u0027, \u0027abcd\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j8A%3D","line":29,"updated":"2014-02-06 01:45:29.000000000","message":"does memcache_crypt.constant_time_compare take bytes like memcache_crypt.derive_keys? seems like should be passing b\u0027abcd\u0027 here?","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":26,"context_line":"        # make sure it works as a compare, the \"constant time\" aspect"},{"line_number":27,"context_line":"        # isn\u0027t appropriate to test in unittests"},{"line_number":28,"context_line":"        ctc \u003d memcache_crypt.constant_time_compare"},{"line_number":29,"context_line":"        self.assertTrue(ctc(\u0027abcd\u0027, \u0027abcd\u0027))"},{"line_number":30,"context_line":"        self.assertTrue(ctc(\u0027\u0027, \u0027\u0027))"},{"line_number":31,"context_line":"        self.assertFalse(ctc(\u0027abcd\u0027, \u0027efgh\u0027))"},{"line_number":32,"context_line":"        self.assertFalse(ctc(\u0027abc\u0027, \u0027abcd\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9jz8%3D","line":29,"in_reply_to":"AAAAUH%2F9j8A%3D","updated":"2014-02-06 02:25:03.000000000","message":"It should work with both. In Python \u003e\u003d 3.3, we use hmac.compare_digest, whose documentation indicates that arguments must have the same type but may be str or bytes; in other versions, we have a hand-written function that should work with both. I\u0027ll add a test with bytes here.","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"25a7747e799f4d83a8887e2db404212d22666970","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def test_sign_data(self):"},{"line_number":52,"context_line":"        keys \u003d self._setup_keys(b\u0027MAC\u0027)"},{"line_number":53,"context_line":"        sig \u003d memcache_crypt.sign_data(keys[\u0027MAC\u0027], \u0027data\u0027.encode(\u0027utf-8\u0027))"},{"line_number":54,"context_line":"        self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def test_encryption(self):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9kAQ%3D","line":53,"updated":"2014-02-06 01:45:29.000000000","message":"isn\u0027t \u0027data\u0027.encode(\u0027utf-8\u0027) the same as b\u0027data\u0027 ? (suggest change to b\u0027data\u0027)","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def test_sign_data(self):"},{"line_number":52,"context_line":"        keys \u003d self._setup_keys(b\u0027MAC\u0027)"},{"line_number":53,"context_line":"        sig \u003d memcache_crypt.sign_data(keys[\u0027MAC\u0027], \u0027data\u0027.encode(\u0027utf-8\u0027))"},{"line_number":54,"context_line":"        self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def test_encryption(self):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j18%3D","line":53,"in_reply_to":"AAAAUH%2F9kAQ%3D","updated":"2014-02-06 02:25:03.000000000","message":"Done","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"25a7747e799f4d83a8887e2db404212d22666970","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        # what you put in is what you get out"},{"line_number":59,"context_line":"        for data in [b\u0027data\u0027, b\u00271234567890123456\u0027, b\u0027\\x00\\xFF\u0027 * 13"},{"line_number":60,"context_line":"                     ] + [six.int2byte(x % 256) * x for x in range(768)]:"},{"line_number":61,"context_line":"            encoded_data \u003d data"},{"line_number":62,"context_line":"            crypt \u003d memcache_crypt.encrypt_data(keys[\u0027ENCRYPTION\u0027],"},{"line_number":63,"context_line":"                                                encoded_data)"},{"line_number":64,"context_line":"            decrypt \u003d memcache_crypt.decrypt_data(keys[\u0027ENCRYPTION\u0027], crypt)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j%2FY%3D","line":61,"updated":"2014-02-06 01:45:29.000000000","message":"I don\u0027t think there\u0027s any need for the encoded_data variable, just use data.","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        # what you put in is what you get out"},{"line_number":59,"context_line":"        for data in [b\u0027data\u0027, b\u00271234567890123456\u0027, b\u0027\\x00\\xFF\u0027 * 13"},{"line_number":60,"context_line":"                     ] + [six.int2byte(x % 256) * x for x in range(768)]:"},{"line_number":61,"context_line":"            encoded_data \u003d data"},{"line_number":62,"context_line":"            crypt \u003d memcache_crypt.encrypt_data(keys[\u0027ENCRYPTION\u0027],"},{"line_number":63,"context_line":"                                                encoded_data)"},{"line_number":64,"context_line":"            decrypt \u003d memcache_crypt.decrypt_data(keys[\u0027ENCRYPTION\u0027], crypt)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j1k%3D","line":61,"in_reply_to":"AAAAUH%2F9j%2FY%3D","updated":"2014-02-06 02:25:03.000000000","message":"Done","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"25a7747e799f4d83a8887e2db404212d22666970","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        for strategy in [b\u0027MAC\u0027, b\u0027ENCRYPT\u0027]:"},{"line_number":73,"context_line":"            keys \u003d self._setup_keys(strategy)"},{"line_number":74,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":75,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":76,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":77,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":78,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j%2Bs%3D","line":75,"updated":"2014-02-06 01:45:29.000000000","message":"we don\u0027t need to do 74 \u0026 75 anymore, right? we made sure that data is the correct format for memcache_crypt.protect_data already by making it b\u0027\u0027","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        for strategy in [b\u0027MAC\u0027, b\u0027ENCRYPT\u0027]:"},{"line_number":73,"context_line":"            keys \u003d self._setup_keys(strategy)"},{"line_number":74,"context_line":"            if isinstance(data, six.text_type):"},{"line_number":75,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":76,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":77,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":78,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j1c%3D","line":75,"in_reply_to":"AAAAUH%2F9j%2Bs%3D","updated":"2014-02-06 02:25:03.000000000","message":"Done","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"25a7747e799f4d83a8887e2db404212d22666970","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":76,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":77,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":78,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"},{"line_number":79,"context_line":"                self.assertNotIn(data, protected)"},{"line_number":80,"context_line":"            unprotected \u003d memcache_crypt.unprotect_data(keys, protected)"},{"line_number":81,"context_line":"            self.assertEqual(data, unprotected)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j%2Bg%3D","line":78,"updated":"2014-02-06 01:45:29.000000000","message":"should be b\u0027ENCRYPT\u0027 for consistency ?","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"0394fd281b4c568fd19dcd1b6ca06946b2c7c438","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                data \u003d data.encode(\u0027utf-8\u0027)"},{"line_number":76,"context_line":"            protected \u003d memcache_crypt.protect_data(keys, data)"},{"line_number":77,"context_line":"            self.assertNotEqual(protected, data)"},{"line_number":78,"context_line":"            if strategy \u003d\u003d \u0027ENCRYPT\u0027:"},{"line_number":79,"context_line":"                self.assertNotIn(data, protected)"},{"line_number":80,"context_line":"            unprotected \u003d memcache_crypt.unprotect_data(keys, protected)"},{"line_number":81,"context_line":"            self.assertEqual(data, unprotected)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAUH%2F9j0w%3D","line":78,"in_reply_to":"AAAAUH%2F9j%2Bg%3D","updated":"2014-02-06 02:25:03.000000000","message":"Done","commit_id":"46e2688460466af334074abcbae5dba67c796dfc"}]}
