user1801517
user1801517

Reputation:

A Confusing Case in Python

Im new to pyqt and there is something i didnt get.I made an app using hashlib and of course gui with pyqt.

 self.pushButton.connect(self.pushButton,QtCore.SIGNAL("clicked()"),self.clickedButton)

and click button:

def clickedButton(self):
        if self.comboBox.currentText() == "MD5":
            self.MD5(self.lineEdit.text())

and MD5:

 def MD5(self,text):
        self.hash = hashlib.md5(text).hexdigest()
        self.textEdit.setText(self.hash)

the result for "hello": a6f145a01ad0127e555c051d15806eb5

No error.It looks ok.But trying same thing on python shell:

 >>> print hashlib.md5("hello").hexdigest()
 5d41402abc4b2a76b9719d911017c592
 >>> 

is this an error or why am i getting different results?

Upvotes: 1

Views: 205

Answers (1)

Matteo Italia
Matteo Italia

Reputation: 126787

The problem is that you are passing to md5 a QString, not a regular Python string. From some experimentation, I can see that both a regular string and a unicode string in Python produce the same result - from here i can tell that it tries to convert the unicode version to a sequence of "narrow" characters using the ascii codec.

>>> print hashlib.md5("hello").hexdigest()
5d41402abc4b2a76b9719d911017c592
>>> print hashlib.md5(u"hello").hexdigest()
5d41402abc4b2a76b9719d911017c592

The QString, instead, gets hashed differently, as in your program:

>>> a=PyQt4.QtCore.QString("hello")
>>> print hashlib.md5(a).hexdigest()
a6f145a01ad0127e555c051d15806eb5

although its UTF-8 or Latin 1 representation (both of which are the same as the output of the ascii codec, since we are dealing only with alphabetic characters) are hashed the same way as Python strings:

>>> print hashlib.md5(a.toUtf8()).hexdigest()
5d41402abc4b2a76b9719d911017c592
>>> print hashlib.md5(a.toLatin1()).hexdigest()
5d41402abc4b2a76b9719d911017c592

Probably what's happening here is that the hashing algorithm is working on the internal representation of the QString, which is UTF-16, which obviously differs from the UTF-8 representation, producing different outputs.

Thus, the lesson here is that before performing any hashing on text you have to choose explicitly its encoding before passing it to the hashing function - which works just with bytes - since there ain't no such thing as plain text.


Edit: it's not working on the UTF-16 representation (otherwise you would get the same result with

>>> print hashlib.md5(u'hello'.encode('utf_16')).hexdigest()
25af7f84a93a6cf5cb00967c60910c7d

) but on something else; still, the point is that hashlib isn't thought to work with QString, so it produces some "strange" output. Again, before using it convert the QString to a narrow string in some adequate encoding.

Upvotes: 3

Related Questions