Fix md5crypt and crypt_password test for python3
authorJulien Cristau <julien.cristau@logilab.fr>
Tue, 06 Oct 2015 11:44:51 +0200
changeset 10775 4b3c1069bd4e
parent 10774 0361442e2633
child 10776 b1834143fec8
Fix md5crypt and crypt_password test for python3 Make sure to always work with bytes for hashing.
md5crypt.py
server/test/unittest_utils.py
--- a/md5crypt.py	Mon Oct 05 17:08:38 2015 +0200
+++ b/md5crypt.py	Tue Oct 06 11:44:51 2015 +0200
@@ -38,30 +38,33 @@
  this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
 """
 
-MAGIC = '$1$'                        # Magic string
-ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+MAGIC = b'$1$'                        # Magic string
+ITOA64 = b"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 
 from hashlib import md5 # pylint: disable=E0611
 
+from six import text_type, indexbytes
 from six.moves import range
 
 
 def to64 (v, n):
-    ret = ''
+    ret = bytearray()
     while (n - 1 >= 0):
         n = n - 1
-        ret = ret + ITOA64[v & 0x3f]
+        ret.append(ITOA64[v & 0x3f])
         v = v >> 6
     return ret
 
 def crypt(pw, salt):
-    if isinstance(pw, unicode):
+    if isinstance(pw, text_type):
         pw = pw.encode('utf-8')
+    if isinstance(salt, text_type):
+        salt = salt.encode('ascii')
     # Take care of the magic string if present
     if salt.startswith(MAGIC):
         salt = salt[len(MAGIC):]
     # salt can have up to 8 characters:
-    salt = salt.split('$', 1)[0]
+    salt = salt.split(b'$', 1)[0]
     salt = salt[:8]
     ctx = pw + MAGIC + salt
     final = md5(pw + salt + pw).digest()
@@ -74,7 +77,7 @@
     i = len(pw)
     while i:
         if i & 1:
-            ctx = ctx + chr(0)  #if ($i & 1) { $ctx->add(pack("C", 0)); }
+            ctx = ctx + b'\0'  #if ($i & 1) { $ctx->add(pack("C", 0)); }
         else:
             ctx = ctx + pw[0]
         i = i >> 1
@@ -83,7 +86,7 @@
     # things run slower.
     # my question: WTF???
     for i in range(1000):
-        ctx1 = ''
+        ctx1 = b''
         if i & 1:
             ctx1 = ctx1 + pw
         else:
@@ -98,21 +101,21 @@
             ctx1 = ctx1 + pw
         final = md5(ctx1).digest()
     # Final xform
-    passwd = ''
-    passwd = passwd + to64((int(ord(final[0])) << 16)
-                           |(int(ord(final[6])) << 8)
-                           |(int(ord(final[12]))),4)
-    passwd = passwd + to64((int(ord(final[1])) << 16)
-                           |(int(ord(final[7])) << 8)
-                           |(int(ord(final[13]))), 4)
-    passwd = passwd + to64((int(ord(final[2])) << 16)
-                           |(int(ord(final[8])) << 8)
-                           |(int(ord(final[14]))), 4)
-    passwd = passwd + to64((int(ord(final[3])) << 16)
-                           |(int(ord(final[9])) << 8)
-                           |(int(ord(final[15]))), 4)
-    passwd = passwd + to64((int(ord(final[4])) << 16)
-                           |(int(ord(final[10])) << 8)
-                           |(int(ord(final[5]))), 4)
-    passwd = passwd + to64((int(ord(final[11]))), 2)
+    passwd = b''
+    passwd += to64((indexbytes(final, 0) << 16)
+                   |(indexbytes(final, 6) << 8)
+                   |(indexbytes(final, 12)),4)
+    passwd += to64((indexbytes(final, 1) << 16)
+                   |(indexbytes(final, 7) << 8)
+                   |(indexbytes(final, 13)), 4)
+    passwd += to64((indexbytes(final, 2) << 16)
+                   |(indexbytes(final, 8) << 8)
+                   |(indexbytes(final, 14)), 4)
+    passwd += to64((indexbytes(final, 3) << 16)
+                   |(indexbytes(final, 9) << 8)
+                   |(indexbytes(final, 15)), 4)
+    passwd += to64((indexbytes(final, 4) << 16)
+                   |(indexbytes(final, 10) << 8)
+                   |(indexbytes(final, 5)), 4)
+    passwd += to64((indexbytes(final, 11)), 2)
     return passwd
--- a/server/test/unittest_utils.py	Mon Oct 05 17:08:38 2015 +0200
+++ b/server/test/unittest_utils.py	Tue Oct 06 11:44:51 2015 +0200
@@ -26,13 +26,13 @@
     def test_crypt(self):
         for hash in (
             utils.crypt_password('xxx'), # default sha512
-            'ab$5UsKFxRKKN.d8iBIFBnQ80', # custom md5
-            'ab4Vlm81ZUHlg', # DES
+            b'ab$5UsKFxRKKN.d8iBIFBnQ80', # custom md5
+            b'ab4Vlm81ZUHlg', # DES
             ):
             self.assertEqual(utils.crypt_password('xxx', hash), hash)
             self.assertEqual(utils.crypt_password(u'xxx', hash), hash)
-            self.assertEqual(utils.crypt_password(u'xxx', unicode(hash)), hash)
-            self.assertEqual(utils.crypt_password('yyy', hash), '')
+            self.assertEqual(utils.crypt_password(u'xxx', hash.decode('ascii')), hash.decode('ascii'))
+            self.assertEqual(utils.crypt_password('yyy', hash), b'')
 
         # accept any password for empty hashes (is it a good idea?)
         self.assertEqual(utils.crypt_password('xxx', ''), '')