0

I'm working on a Google App Engine application, and I need to hash a password and salt it, and for that I'm using the method below:

def hash_password(password):
    #Create salt
    salt = base64.urlsafe_b64encode(os.urandom(8))
    salted = base64.b64encode(base64.urlsafe_b64decode(salt) + password)
    hashed = hashlib.md5(salted).digest()
    return base64.b64encode(hashed)

The problem is when trying to decode the salt from base64, as the salt generated through urandom has non-ascii characters. It results on the error:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd8 in position 2: ordinal not in range(128)

I can't skip the step of decoding the salt on base64, as I already have a datastore with passwords and salts generated this way, that was populated through java code.

How can I preserve this structure, and still get a valid hashed password, that I can use to compare with the hashed passwords already on my datastore?

When I execute that same method on my terminal, using the python interpreter, it run without any issues, however when running it on GAE's dev server (locally, using the same python interpreter), it results in that error.

ivanvlopes
  • 75
  • 7

1 Answers1

1

I think you are mixing urlsafe_b64encode and decodestring. Check out the documentation.

You should either use urlsafe_b64encode and urlsafe_b64decode or b64encode and b64decode

def hash_password(pw):
    #Create salt
    salt = base64.b64encode(os.urandom(8))
    salted = base64.b64encode(base64.b64decode(salt) + pw)
    hashed = hashlib.md5(salted).digest()
    return base64.b64encode(hashed)

EDIT

binascii did the trick, working with the following code:

def hash_password(pw):
    #Create salt
    salt = base64.b64encode(os.urandom(8))
    salted = base64.b64encode(binascii.a2b_base64(salt) + pw)
    hashed = hashlib.md5(salted).digest()
    return base64.b64encode(hashed)
ivanvlopes
  • 75
  • 7
wenzul
  • 3,948
  • 2
  • 21
  • 33
  • I'm really sorry, it was a mistake of mine. I was already using urlsafe_b64decode before, however I was messing around with different methods, trying to get it to work, and by accident I copied the wrong version on my question. Already edited it. – ivanvlopes Oct 13 '14 at 20:06
  • Is there any reason why you are using the urlsafe functions? – wenzul Oct 13 '14 at 20:16
  • I have no GAE server to test that. But are you really sure that you are running the latest version of your script? salt is an ascii string because its b64encoded. But I think you look on that too... :) – wenzul Oct 13 '14 at 20:30
  • I just used urlsafe methods to make sure I didn't run into future problems. However, even if I don't use urlsafe I run into the same problems. I see why it is an ascii string, but my problem is what was generated previously, such as the urandom(8) salt. For instance, an existing salt is LG/Y9PrTjHQ=. This was not generated by me, it's the sort of salt already on the datastore. If you decode that, you'll see that it contains non-ascii charactes. And unfortunately, I somehow have to successfully decode it under GAE. – ivanvlopes Oct 13 '14 at 20:33
  • 1
    Thanks for the example. Weird. Have you tried to use [binascii](https://docs.python.org/2/library/binascii.html)? binascii.a2b_base64(salt) – wenzul Oct 13 '14 at 20:45
  • Thank you! Using binascii did the trick. Not sure wh though, since base64 uses binascii. – ivanvlopes Oct 13 '14 at 22:13