solero / houdini

A Club Penguin private server written in Python 3
https://houdini.readthedocs.io/
MIT License
281 stars 54 forks source link

Use UTF-8 default and support numbers #6

Closed ghost closed 5 years ago

ghost commented 5 years ago

hash() will always expect a string, so standardizing UTF-8 is a must. Also in this PR we support numbers to be hashed.

ItsGravix commented 5 years ago

such change

ghost commented 5 years ago

such change

Big change @ItsGravix

ben-pearce commented 5 years ago

I have tested this code on my local environment and encountered the following attribute error when logging in.

2019-09-30 15:07:11,840 [INFO ]  basil is logging in!
2019-09-30 15:07:12,058 [INFO ]  basil has logged in successfully
2019-09-30 15:07:12,058 [ERROR]  <traceback object at 0x7f7b2c4ae748>
Traceback (most recent call last):
  File "/home/ben/Workspace/houdini-asyncio/houdini/spheniscidae.py", line 186, in run
    await self.__data_received(data)
  File "/home/ben/Workspace/houdini-asyncio/houdini/spheniscidae.py", line 169, in __data_received
    await self.__handle_xml_data(data)
  File "/home/ben/Workspace/houdini-asyncio/houdini/spheniscidae.py", line 129, in __handle_xml_data
    await listener(self, body_tag)
  File "/home/ben/Workspace/houdini-asyncio/houdini/handlers/__init__.py", line 105, in __call__
    return await self.callback(*handler_call_arguments)
  File "/home/ben/Workspace/houdini-asyncio/houdini/handlers/login/login.py", line 98, in handle_login
    confirmation_hash = Crypto.hash(os.urandom(24))
  File "/home/ben/Workspace/houdini-asyncio/houdini/crypto.py", line 21, in hash
    return hashlib.md5(undigested.encode('utf-8')).hexdigest()
AttributeError: 'bytes' object has no attribute 'encode'

I think this is because of this line in the login handler. Which passes the result of os.urandom() (a bytes-like object) into the Crypto.hash method.

We only ever need to call encode when Crypto.hash() has been passed a string. So to add support for integers being passed.

@staticmethod
def hash(undigested):
    if type(undigested) == str:
        undigested = undigested.encode('utf-8')
    elif type(undigested) == int:
        undigested = str(undigested).encode('utf-8')
    return hashlib.md5(undigested).hexdigest()

I am happy for you to amend your pull request and i'll merge.

Although, I am not sure what benefit this method being able to hash integers has? It seems like it would only be useful in the case that perhaps a plugin or handler needs to pass an int at some point, I feel like it would be more efficient to manually convert the int to a string each time since we're performing an additional check even when no integers are being passed (which is most of the time).

Like this:

Crypto.hash(str(integer_to_hash))