The Basics
What is hashing?
Hashing is an algorithm that is used to transform data of any length into a fixed length and is only one way. What this means is that you there is not a purpose to reverse hashing. The hashed the passwords would live hashed in a password database for the rest of their lives. When a user wants to authenticate, the password gets hashed and then the hashes are compared to see if they match character for character. There many different hashing algorithms, they different by:
- length
- speed
All of which will determine how secure they are.
import hashlib
dude = hashlib.sha256("mypassword").hexdigest()
print(dude)
Output
89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8
What is Salt or Salting?
Salt is random data, bit/bytes, that is used to make a unique direction for a hash. Instead of just telling something to hash this password, the salt gives it a more unique one off hash that will give the hackers one more layer to dig through.
import hashlib
import string
import random
def id_generator(size=6, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
return ''.join(random.choice(chars) for _ in range(size))
salt = id_generator(25)
dude = hashlib.sha256("mypassword" + salt).hexdigest()
print(dude)
Output
a998c90881afb36166b2b7c18c35c744c62b72cffb8656805952175a2b727165
What is encryption?
It’s like hashing, but it’s two way. If a person or computer wants to read or digest something in plain text but needs to be encrypted to safety send it to the recieptient, in order to do this, a key is needed. A key is used to encrypt and decrypt the password, so it is important to save it in a secure location. For example, do not leave it on a shared drive that everyone has access to.
For example, an encrypted email is:
- typed up in clear text
- encrypted
- sent
- decrypted
- read in clear text
What are the recommended Hashing Methods?
Important, it’s recommended to alway use a hash plus salt. Hackers have many ways to calculate what the stored clear text value is:
- rainbow tables
- reverse lookup tables
- lookup tables
All of these methods:
- hash a clear text password
- evaluate if it matches that hash they found/hacked
- if it matches, they now know you password
In other words, they can perform a brute force attack on a hash with out having to attempt to authenticate. Once they have found and hash/password match, they will now know your password.
If the password or value is salted or has extra bits added, then even if they are able to brute force hack it (which is unlikely), they will only have a clear text value that is useless.
What is Key Stretching?
Key Stretching is a method of creating a key by giving it a unique length and some extra random bits via salt.
What are the recommended Encryption Methods?
Python Modules
Secure Hashing Python Modules
bcrypt – The current defacto for hashing passwords. Keys can also be generated as well. It is still new (2012) so it is not widely adopted.
PBKDF2 – More of a Key Hashing, but can be used to hash passwords. The key is needed for encryption.
scrypt – A replacement for bcrypt and PDKDF2. You can install scrypt here
Secure Encryption Python Modules
bcrypt and scrypt both use AES to encrypt, but its really just one way.
Use pycrypto
>>> from Crypto.Cipher import AES
>>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
>>> message = "The answer is no"
>>> ciphertext = obj.encrypt(message)
>>> ciphertext
'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
>>> obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
>>> obj2.decrypt(ciphertext)
'The answer is no'
Hacky way to just use base64 with “Salting” or “Padding”
Base64 Without Salting
password = 'mypassword12345'
hashed = base64.b64encode(password)
print(password)
print(hashed)
print(base64.b64decode(hashed))
Output
mypassword12345
bXlwYXNzd29yZDEyMzQ1
mypassword12345
Base64 With Salting
import string
import random
def id_generator(size=6, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
return ''.join(random.choice(chars) for _ in range(size))
# Save this somewhere so you know what to strip out
salt = id_generator(25)
password = 'mypassword12345'
hashed = base64.b64encode(password + salt)
print(salt)
print(password)
print(hashed)
print(base64.b64decode(hashed))
Output
SUVCo6V2JUo0dITspOjR0N6OF
mypassword12345
bXlwYXNzd29yZDEyMzQ1U1VWQ282VjJKVW8wZElUc3BPalIwTjZPRg==
mypassword12345SUVCo6V2JUo0dITspOjR0N6OF
References
Salted Password Hashing – Doing it Right
I need to securely store a username and password in Python, what are my options?
The scrypt key derivation function
An example usage of an encryption algorithm (AES, in this case) is
Hey Dan,
Nice breakdown.
I have pretty much used Bcrypt for every project in the last few years. It is pretty solid. I will checkout out scrypt and see what some of the advantages of that might be.
Keep posting cool stuff, I hope all is well.
Thanks Shane! Good to hear from you. Scrypt seems good, just a little new. There are some really cool tests that are being done how with this. The neatest feature is being able to specify how long it should take to hash the bytes.
Hope all is well, posting on wordpress has really helped my brain to be able to focus and provides clarity.