diff --git a/doc/www/pelicanconf.py b/doc/www/pelicanconf.py
index 51305aa05c7b1c5bfc0f61d276b0f41c7a17f0e2..c27b653152dd7e6b55c04fadce786bff7cd651f3 100644
--- a/doc/www/pelicanconf.py
+++ b/doc/www/pelicanconf.py
@@ -39,13 +39,15 @@ TAG_SAVE_AS = ''
 
 STATIC_PATHS = [
     'robots.txt',
-    'ycsb'
+    'ycsb',
+    'js/highcharts.js',
+    'js/tabs.js'
 ]
 EXTRA_PATH_METADATA = {
-    'robots.txt'     : { 'path': 'robots.txt'  },
-    'ycsb'           : { 'path': 'ycsb'        },
-    'js/highlight.js': { 'path': 'highlight.js'},
-    'js/tabs.js'     : { 'path': 'tabs.js'     },
+    'robots.txt'      : { 'path': 'robots.txt'   },
+    'ycsb'            : { 'path': 'ycsb'         },
+    'js/highcharts.js': { 'path': 'highcharts.js'},
+    'js/tabs.js'      : { 'path': 'tabs.js'      },
 }
 
 # Uncomment following line if you want document-relative URLs when developing
diff --git a/src/box/hash_index.cc b/src/box/hash_index.cc
index fb3a4d48484dbb630f55133e903610b2aeeb5899..d8a8db0525af6f9b8e11c03fde870e73db9460f6 100644
--- a/src/box/hash_index.cc
+++ b/src/box/hash_index.cc
@@ -53,6 +53,40 @@ mh_index_eq_key(const char *key, struct tuple *const *tuple,
 				      key_def) == 0;
 }
 
+static inline uint32_t
+mh_hash_field(uint32_t *ph1, uint32_t *pcarry, const char **field,
+	      enum field_type type)
+{
+	const char *f = *field;
+	uint32_t size;
+
+	switch (type) {
+	case STRING:
+		/*
+		 * (!) MP_STR fields hashed **excluding** MsgPack format
+		 * indentifier. We have to do that to keep compatibility
+		 * with old third-party MsgPack (spec-old.md) implementations.
+		 * \sa https://github.com/tarantool/tarantool/issues/522
+		 */
+		f = mp_decode_str(field, &size);
+		break;
+	default:
+		mp_next(field);
+		size = *field - f;  /* calculate the size of field */
+		/*
+		 * (!) All other fields hashed **including** MsgPack format
+		 * identifier (e.g. 0xcc). This was done **intentionally**
+		 * for performance reasons. Please follow MsgPack specification
+		 * and pack all your numbers to the most compact representation.
+		 * If you still want to add support for broken MsgPack,
+		 * please don't forget to patch tuple_compare_field().
+		 */
+		break;
+	}
+	assert(size < INT32_MAX);
+	PMurHash32_Process(ph1, pcarry, f, size);
+	return size;
+}
 
 static inline uint32_t
 mh_index_hash(struct tuple *const *tuple, const struct key_def *key_def)
@@ -76,12 +110,7 @@ mh_index_hash(struct tuple *const *tuple, const struct key_def *key_def)
 
 	for ( ; part < key_def->parts + key_def->part_count; part++) {
 		const char *field = tuple_field(*tuple, part->fieldno);
-		const char *f = field;
-		mp_next(&f);
-		uint32_t size = f - field;
-		assert(size < INT32_MAX);
-		PMurHash32_Process(&h, &carry, field, size);
-		total_size += size;
+		total_size += mh_hash_field(&h, &carry, &field, part->type);
 	}
 
 	return PMurHash32_Result(h, carry, total_size);
@@ -99,13 +128,15 @@ mh_index_hash_key(const char *key, const struct key_def *key_def)
 		return ((uint32_t)((val)>>33^(val)^(val)<<11));
 	}
 
-	/* Calculate key size */
-	const char *k = key;
-	for (uint32_t part = 0; part < key_def->part_count; part++) {
-		mp_next(&k);
-	}
+	uint32_t h = HASH_SEED;
+	uint32_t carry = 0;
+	uint32_t total_size = 0;
+
+	/* Hash fields part by part (see mh_hash_field() comments) */
+	for ( ; part < key_def->parts + key_def->part_count; part++)
+		total_size += mh_hash_field(&h, &carry, &key, part->type);
 
-	return PMurHash32(HASH_SEED, key, k - key);
+	return PMurHash32_Result(h, carry, total_size);
 }
 
 #define mh_int_t uint32_t
diff --git a/test/box/call.test.py b/test/box/call.test.py
index cba95b6cf7dde82d65172ab3d44f74723c4b3092..bfb30d386a9509b7842ada91e683100b23fb9766 100644
--- a/test/box/call.test.py
+++ b/test/box/call.test.py
@@ -122,3 +122,6 @@ sql("call space:delete(4)")
 
 admin("space:drop()")
 admin("box.schema.user.drop('test')")
+
+# Re-connect after removing user
+sql.py_con.close()
diff --git a/test/box/iproto.result b/test/box/iproto.result
index 92cd4fd8ae85c073a7b34fb16e74d933be4d14f7..9b6826200771788236f0f5e126eac12457059c5c 100644
--- a/test/box/iproto.result
+++ b/test/box/iproto.result
@@ -1,3 +1,6 @@
+box.schema.user.grant('guest', 'read,write,execute', 'universe')
+---
+...
 
 #
 # iproto packages test
@@ -106,3 +109,52 @@ box.schema.user.grant('guest', 'read,write,execute', 'space', 'test')
 space:drop()
 ---
 ...
+space = box.schema.create_space('test')
+---
+...
+space:create_index('primary', { type = 'hash', parts = {1, 'str'}})
+---
+...
+STR 1
+--
+0xa1 => ok ok ok ok ok ok
+0xd901 => ok ok ok ok ok ok
+0xda0001 => ok ok ok ok ok ok
+0xdb00000001 => ok ok ok ok ok ok
+
+STR 31
+--
+0xbf => ok ok ok ok ok ok
+0xd91f => ok ok ok ok ok ok
+0xda001f => ok ok ok ok ok ok
+0xdb0000001f => ok ok ok ok ok ok
+
+STR 32
+--
+0xd920 => ok ok ok ok ok
+0xda0020 => ok ok ok ok ok
+0xdb00000020 => ok ok ok ok ok
+
+STR 255
+--
+0xd9ff => ok ok ok ok ok
+0xda00ff => ok ok ok ok ok
+0xdb000000ff => ok ok ok ok ok
+
+STR 256
+--
+0xda0100 => ok ok ok ok
+0xdb00000100 => ok ok ok ok
+
+STR 65535
+--
+0xdaffff => ok ok ok ok
+0xdb0000ffff => ok ok ok ok
+
+STR 65536
+--
+0xdb00010000 => ok ok ok
+
+space:drop()
+---
+...
diff --git a/test/box/iproto.test.py b/test/box/iproto.test.py
index d95af37e1e7f156fb18dfe925d637f7e29bb1c86..c4c60e52bc91ea2fb1a122b306305856c22e7b1b 100644
--- a/test/box/iproto.test.py
+++ b/test/box/iproto.test.py
@@ -5,11 +5,12 @@ import socket
 import msgpack
 from tarantool.const import *
 from tarantool import Connection
-from tarantool.request import RequestInsert
-from tarantool.request import RequestSelect
+from tarantool.request import Request, RequestInsert, RequestSelect
 from tarantool.response import Response
 from lib.tarantool_connection import TarantoolConnection
 
+admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
+
 print """
 #
 # iproto packages test
@@ -149,3 +150,66 @@ c.close()
 
 admin("space:drop()")
 
+#
+# gh-522: Broken compatibility with msgpack-python for strings of size 33..255
+#
+admin("space = box.schema.create_space('test')")
+admin("space:create_index('primary', { type = 'hash', parts = {1, 'str'}})")
+
+class RawInsert(Request):
+    request_type = REQUEST_TYPE_INSERT
+    def __init__(self, conn, space_no, blob):
+        super(RawInsert, self).__init__(conn)
+        request_body = "\x82" + msgpack.dumps(IPROTO_SPACE_ID) + \
+            msgpack.dumps(space_id) + msgpack.dumps(IPROTO_TUPLE) + blob
+        self._bytes = self.header(len(request_body)) + request_body
+
+class RawSelect(Request):
+    request_type = REQUEST_TYPE_SELECT
+    def __init__(self, conn, space_no, blob):
+        super(RawSelect, self).__init__(conn)
+        request_body = "\x83" + msgpack.dumps(IPROTO_SPACE_ID) + \
+            msgpack.dumps(space_id) + msgpack.dumps(IPROTO_KEY) + blob + \
+            msgpack.dumps(IPROTO_LIMIT) + msgpack.dumps(100);
+        self._bytes = self.header(len(request_body)) + request_body
+
+c = sql.py_con
+space = c.space('test')
+space_id = space.space_no
+
+TESTS = [
+    (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
+    (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
+    (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
+    (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
+    (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
+    (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
+    (65536, "\xdb\x00\x01\x00\x00"),
+]
+
+for test in TESTS:
+    it = iter(test)
+    size = next(it)
+    print 'STR', size
+    print '--'
+    for fmt in it:
+        print '0x' + fmt.encode('hex'), '=>',
+        field = '*' * size
+        c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
+        tuple = space.select(field)[0]
+        print len(tuple[0])== size and 'ok' or 'fail',
+        it2 = iter(test)
+        next(it2)
+        for fmt2 in it2:
+            tuple = c._send_request(RawSelect(c, space_id,
+                "\x91" + fmt2 + field))[0]
+            print len(tuple[0]) == size and 'ok' or 'fail',
+        tuple = space.delete(field)[0]
+        print len(tuple[0]) == size and 'ok' or 'fail',
+        print
+    print
+
+admin("space:drop()")
+
+server.stop()
+server.deploy()