Install bcrypt and Passlib
In Python 2 you can you easily use bcrypt by installing the packages python-bcrypt and python-passlib, on Ubuntu do:
sudo apt-get install python-bcrypt python-passlib
I would have preferred to use Python 3, but there isn’t a bcrypt library for Python 3 in Ubuntu’s repository. On the other hand it doesn’t really matter in this case.
Use bcrypt in the Python interpreter
Open a terminal and type the following stuff:
matachi:~$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from passlib.hash import bcrypt
>>> bcrypt.encrypt('kalle', rounds=4, salt='1234567890123456789012')
'$2a$04$123456789012345678901u9TR3ZsWr3m7NxL0UZWrF0pxdXbJe2jO'
>>> bcrypt.encrypt('kalle', rounds=4, salt='123456789012345678901u')
'$2a$04$123456789012345678901u9TR3ZsWr3m7NxL0UZWrF0pxdXbJe2jO'
As you can see, it’s really easy to use and experiment with bcrypt in the Python interpreter. I highly recommend it!
How the salt works
The salt must be at least 22 characters long and it doesn’t matter if it’s longer than that, since all characters in addition to that will be ignored. So use a 22 characters salt.
As you saw in the previous part of this post, two different salts resulted in the same output. There are a couple of reasons behind that. The first one is that the characters you give to bcrypt as salt aren’t interpreted as ASCII or UTF-8 characters, but as base64. However, it’s not the usual base64 alphabet but:
./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
With this alphabet, every character uses 6 bits, instead of 7 as a ASCII character does.
The second reason is that that bcrypt takes a salt of exactly 128 bits. 22 characters where each character uses 6 bits means that they use a total of 132 bits. So the last 4 bits of the last of the 22 characters will be ignored.
. (period) in the alphabet corresponds to 000000 and N corresponds to 001111. Therefore will the hash not differ if the 22th character is . to N. However, O corresponds to 010000, which means that it will result in different hash. Here you can see how it works:
>>> bcrypt.encrypt('kalle', rounds=4, salt='123456789012345678901M')
'$2a$04$123456789012345678901.GZyLszhboAmO/L.DQdxwE7n3c04N7Qa'
>>> bcrypt.encrypt('kalle', rounds=4, salt='123456789012345678901N')
'$2a$04$123456789012345678901.GZyLszhboAmO/L.DQdxwE7n3c04N7Qa'
>>> bcrypt.encrypt('kalle', rounds=4, salt='123456789012345678901O')
'$2a$04$123456789012345678901OYspTNPKklQIIHjaV7fayCuiYOlHRrXu'
As you also can see, if you use the salt 123456789012345678901M, the output’s salt is:
$2a$04$123456789012345678901.GZyLszhboAmO/L.DQdxwE7n3c04N7Qa
Note that it’s a period in the end and not a M.
Link
Here is a nice Stack Oveflow answer I read that explains this very well: