I'm using passlib==1.7.1 with the following import:
from passlib.apps import custom_app_context as pwd_context
Then hashing the password with the following:
pwd_context.encrypt(password)
I then verify with:
pwd_context.verify(password, self.password_hash)
This is fine, but verification fails with certain characters. e.g. "£" or "$".
Does anyone know why this would be the case please?
Thank you!
Update:
Thank you all very much. Armed with this info I investigated a bit more and it seems that the problem is not passlib but sits somewhere between angular4 where I send a base64 authorisation header to the flask app.
I'm currently using the following to do this:
let headers: Headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa(userLoginRequest.username + ':' + userLoginRequest.password)
});
I have read a lot today about unescape (and it's depreciation in favour of decodeURI()). I have also read a lot about support for unicode in base64 encoding. I tried a number of combinations of these things and it made no difference. I am now really rather confused!
To test what's going on I do the following. In angular4 I execute the following:
let encodedString = btoa('doug:Tree£9')
console.log(encodedString)
console.log(atob(encodedString))
As expected, this prints the following to the console.
ZG91ZzpUcmVlozk=
doug:Tree£9
So it's clearly ok encoding and decoding.
Doing the same process in Python...
import base64
encoded = base64.b64encode('doug:Tree£9')
print encoded
print base64.b64decode(encoded)
I get the the following in terminal.
ZG91ZzpUcmVlwqM5
doug:Tree£9
I note that "ZG91ZzpUcmVlozk=" and "ZG91ZzpUcmVlwqM5" are not the same. However, both methods are working within their own languages.
If I put the "ZG91ZzpUcmVlozk=" encoded string from javascript into python and decode it as follows...
import base64
print base64.b64decode("ZG91ZzpUcmVlozk=")
I get:
doug:Tree�9
Note that the £ character has now been mashed.
Other Unicode characters fail too.
So I think the question is how to I encode the Authorisation header so that python correctly recognises the £ character, and any other character users choose for their passwords?
Thanks so much!
Edit: Resolved!
I found this Using Javascript's atob to decode base64 doesn't properly decode utf-8 strings which goes into some detail. I resolved it by using the following approach recommended by @brandonscript.
b64EncodeUnicode(str) : string{
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode(parseInt(p1, 16))
}))
}
Works perfectly! Phew!