Simple programming language with a md5/sha1 hash command? - python

I'm looking to create a simple brute-force password-cracker which will hash an input from stdin and compare the result to an existing hash (for my securities class).
I've never done any actual programming involving hashes, though, since it's mostly been conceptual/mathematical parts so far. Is there a (relatively) easy-to-learn language which has a simple hash command? A friend of mine recommended Python but I'm not sure if there's anything else out there I could pick up within a day or two. I know a bit of C, but hashing seems relatively complicated and needs additional libraries.
Also, any syntax help with an actual hash command would be appreciated. The program itself needs to be able to support odd hash methods, like hashing a value twice or using a set salt that doesn't change, and be able to take input from stdin (for use with programs like johntheripper).

Assuming that you're only being asked to use the hash functions, and not to implement the hash yourself, Python's hashlib module has routines for md5 and sha1:
[Updated for Python 3, in which hashlib wants bytes, not strings:]
>>> import hashlib
>>> s = 'something to hash'
>>> sb = s.encode("utf8")
>>> hashlib.md5(sb)
<md5 HASH object # 0x7f36f5ce3440>
>>> hashlib.md5(sb).hexdigest()
'6f4815fdf1f1fd3f36ac295bf39d26b4'
>>> hashlib.sha1(sb).hexdigest()
'72668bc961b0a78bfa1633f6141bcea69ca37468'
[Legacy Python 2 version:]
>>> import hashlib
>>> s = 'something to hash'
>>> hashlib.md5(s)
<md5 HASH object # 0xb7714ca0>
>>> hashlib.md5(s).hexdigest()
'6f4815fdf1f1fd3f36ac295bf39d26b4'
>>> hashlib.sha1(s).hexdigest()
'72668bc961b0a78bfa1633f6141bcea69ca37468'

I think python is a fine choice for something like this. It has the hashlib module to start with, and if you need more power, the PyCrypto toolkit is easy to use and supports plenty of cryptographic primitives, including hashing. If you already know some C, then maybe just using that with the openssl libraries will be easier for you to pick up. In any case, it is usually worth the investment to learn a crypto library for your preferred language (especially for a crypto class), because eventually you will want to use something that you won't want to code by hand and be confident that it is implemented correctly.
As for syntax with an actual hash command, here is an example in python with PyCrypto for getting a SHA256 hash (using python 3.2):
import Crypto.Hash.SHA256
to_hash = "hello, how are you?"
sha256 = Crypto.Hash.SHA256.new()
sha256.update(to_hash.encode())
dgst = sha256.hexdigest()
print(dgst)
produces the output
5c1940d2a11cd8b1e256ea4183ba22cddfa7cc0d00610a159bd7f5886d01067a

The hashlib library in python contains the following :
'md5', 'new', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'
for details check:
http://docs.python.org/release/3.1.3/library/hashlib.html
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
>>> m.digest_size
16
>>> m.block_size
64

This small python program suits best for these type of small jobs
hash.py
import hashlib
import sys
try:
hash_name = sys.argv[1]
except IndexError:
print 'Specify the hash name as the first argument.'
else:
try:
data = sys.argv[2]
except IndexError:
print 'Please enter the data to be hashed'
sys.exit()
h = hashlib.new(hash_name)
h.update(data)
print h.hexdigest()
Output
$ python hash.py sha1 password1
e38ad214943daad1d64c102faec29de4afe9da3d
$ python hash.py sha256 password1
0b14d501a594442a01c6859541bcb3e8164d183d32937b851835442f69d5c94e
$ python hash.py md5 password1
7c6a180b36896a0a8c02787eeafb0e4c

No programming language worth its salt can be learned in a few days. You may be able to get the syntax figured out, but not much beyond that. I like this article: http://norvig.com/21-days.html
There is probably not a best programming language for this. I can recommend C#, as it has simple cryptography classes in System.Security.Cryptography.
To find the MD5 hash of a byte array, you can use something like this:
byte[] hash = System.Security.Cryptography.MD5.Create().ComputeHash(myByteArray);
To use SHA1, just replace MD5 with SHA1.
If you want to get the hash of an ASCII string, you can get a byte array like so:
byte[] myByteArray = System.Text.Encoding.ASCII.GetBytes(myString);
An example function for converting a string to a hash:
// At the top of the file:
// using System.Security.Cryptography;
// using System.Text;
byte[] GetHash(string message)
{
return MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(message));
}

Related

MD5 hash in Python

I have been given a file with user and passwords in the format: $id$salt$hashed.
Where ID stands for the type of encryption and id=1 stands for FreeBSD-style MD5.
There is an example in which I know the password= "alice"
jsmith: $1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/:10063:0:99999:7:::
So I have done this in Python to check
import hashlib
passw='alice'
salt='kDHTx'
hashed= hashlib.md5(salt+passw).hexdigest()
print('What i get is: '+hashed)
print('What i should: '+'WKRXXT1P7UtjvU7CQ9eWs')
But I dont even get the format correctly:
What i get is: ba359e6dd36371c4dc5c187aac11e0d8
What i should: WKRXXT1P7UtjvU7CQ9eWs
What am I doing wrong? Or even understanding wrong from the begining?
You need to use the crypt library instead of hashlib.
>>> import crypt
>>> crypt.crypt('alice', crypt.METHOD_MD5)
$1$tlyP8ine$I9F3AiUCIgOjREqbx6WUg0
The salt is generated by the function when you pass in crypt.METHOD_MD5.
To re-create an existing hash, you can pass it in as the second argument:
>>> crypt.crypt('alice', '$1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/')
$1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/

hashlib vs crypt.crypt() in Python. Why different results?

I'm learning Python. I can't figure out why hashlib.sha512(salt + password).hexdigest() doesn't give the expected results.
I'm looking for a pure Python implementation of the equivalent of Ulrich Drepper's sha512crypt.c algorithm. (It took me a while to figure out what I was looking for.)
According to the man page for crypt on my Ubuntu 12.04 system, crypt is using SHA-512 (because the strings start with $6$).
The code below verifies that the behavior is as expected when I call Python's wrapper of the system crypt (i.e., crypt.crypt()). I want to use hashlib.sha512 or some other Python lib to produce the same result as crypt.crypt(). How?
This code shows the problem I'm encountering:
import hashlib, crypt
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = hashlib.sha512(salt + password).hexdigest() #what's wrong with this one?
value2 = crypt.crypt(password, insalt) #this one is correct on Ubuntu 12.04
if not value1 == value2:
print("{}\n{}\n\n".format(value1, value2))
According to the crypt man page, SHA-512 is 86 chars. The crypt() call in the code above conforms to that. However, the output of hashlib.sha512 is longer than 86 chars, so something is way off between these two implmentations...
Here's the output for those who don't want to run the code:
051f606027bd42c1aae0d71d049fdaedbcfd28bad056597b3f908d22f91cbe7b29fd0cdda4b26956397b044ed75d50c11d0c3331d3cb157eecd9481c4480e455
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/
Another attempt based on initial feedback here. No success yet:
import hashlib, crypt, base64
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = base64.b64encode(hashlib.sha512(salt + password).digest())
value2 = crypt.crypt(password, insalt) #this one is correct
if not value1 == value2:
print("{}\n{}\n\n".format(value1, value2))
Here's the solution. There is also more detail at this other question: Python implementation of sha512_crypt.c where it shows that the backend of passlib contains a pure Python implementation of sha512_crypt (and the Python implementation is called if crypt.crypt() isn't available on the OS).
$ sudo pip install passlib
import passlib.hash, crypt
ctype = "6" #for sha512 (see man crypt)
salt = "qwerty"
insalt = '${}${}$'.format(ctype, salt)
password = "AMOROSO8282"
value1 = sha512_crypt.encrypt(password, salt=salt, rounds=5000)
value2 = crypt.crypt(password, insalt)
if not value1 == value2:
print("algorithms do not match")
print("{}\n{}\n\n".format(value1, value2))
Here is the output:
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/
$6$qwerty$wZZxE91RvJb4ETR0svmCb69rVCevicDV1Fw.Y9Qyg9idcZUioEoYmOzAv23wyEiNoyMLuBLGXPSQbd5ETanmq/
One key point is that Passlib has a pure Python implementation of sha512_crypt that it will use when the system doesn't have the crypt implementation that current Linux systems have (e.g., http://www.akkadia.org/drepper/SHA-crypt.txt).
See the documentation for PassLib here:
passlib - password hashing library for python - Google Project Hosting
https://code.google.com/p/passlib/
Passlib 1.6.2 documentation — Passlib v1.6.2 Documentation
http://pythonhosted.org/passlib/
passlib-users - Google Groups
https://groups.google.com/forum/#!forum/passlib-users
New Application Quickstart Guide — Passlib v1.6.2 Documentation
http://pythonhosted.org/passlib/new_app_quickstart.html#sha512-crypt
passlib.hash.sha512_crypt - SHA-512 Crypt — Passlib v1.6.2 Documentation
http://pythonhosted.org/passlib/lib/passlib.hash.sha512_crypt.html#passlib.hash.sha512_crypt
The manual of crypt is imprecise (even misleading). The algorithms used by crypt with the “MD5”, “SHA-256” or “SHA-512” monikers are in fact algorithms built on these primitives. They are password-based key derivation functions, using the hash to perform key strengthening.
A good password hashing algorithm has two properties: it must combine the password with a unique salt (to defeat attempts to crack many passwords at once), and it must be slow (because that hurts the attacker more than the defender, since the attacker needs to try a huge number of combinations). Everyday hash algorithms like MD5 and the SHA families are designed to be fast, as fast as possible while still having the desired security properties. One way to build a password hash algorithm is to take a cryptographic hash algorithm and iterate it many times. While this isn't ideal (because there are better techniques that make it more difficult to build dedicated hardware for password cracking), it is adequate.
The Wikipedia article for crypt(3) provides a brief explanation and has pointers to primary sources. Linux and FreeBSD's man pages are poor, but Solaris's has enough information not to be misleading (follow the links to crypt.conf(4) and then crypt_sha512 and the others). You can also read Is user password in ubuntu 13.04 in plain text? and Is there repetition in the Solaris 11 hash routine? Can I add some?
The right way to compute the output of crypt in Python is to call crypt.crypt.
Your passwords are not the same length, that is because the crypt()
output is base64 encoded and you use hexdigest for value1.
Instead of hexdigest, you should try to do something like
value1 = crypt_base64(hashlib.sha512(salt + password))
with crypt_base64 like the bash implementation, final part of
doHash() function.

Python with etc/Shadow

so I'm writing this program that needs to check the password hash in etc/shadow and compare it to the password the user entered. I tried encrypting the password with hashlib.sha512, but the result was not the same. I think it's salted some how, but I don't know if it uses a universal salt or how I can get the salt each time.
tldr; I need a way for a user to enter a password, then have the program hash it and check it against the etc/shadow. Any ideas?
Try this https://pypi.python.org/pypi/pam . First link in google by python pam.
Look at distribution package manager for python-pam if exists. Else install with pip or easy_install.
Small example:
>>> import pam
>>> pam.authenticate('fred', 'fredspassword')
False
>>> import crypt
>>> line = 'bob:$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.:15965:0:99999:7:::'
>>> encript = line.split(':')[1]
>>> encript
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
>>> i = encript.rfind('$')
>>> salt = encript[:i]
>>> salt
--> '$1$qda8YAO9'
>>> crypt.crypt('bob_password',salt)
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
>>> encript
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
The passwd field is not just a SHA-512 hash of the password.*
This is explained in the crypt manpage. The format is $id$salt$hash, where id specifies the hash method (1 for MD5, 2a for Blowfish, 5 for SHA-256, 6 for SHA-512), salt specifies the salt to use with that algorithm, and hash specifies what the result should be.
As the manpage implies, you can actually pass the whole $id$salt$ to the crypt function in place of the salt, and it will automatically use the appropriate algorithm. This wouldn't be too hard to do via, say, ctypes.
At any rate, what you're doing is almost certainly a bad idea. You'll need to run as root in order to have access to /etc/shadow, and you'll need to simulate more than just password verification if you actually want to verify that the user can log in, and of course you'll need to handle secure input and make sure you don't end up saving the password in plaintext somewhere and so on. It's a lot simpler and safer to just let PAM do the work for you.
* I believe that in theory, it can be—if it doesn't start with a $ it's interpreted as some legacy format… presumably meaning it's interpreted as POSIX crypt using the DES algorithm.

Salt and hash a password in Python

This code is supposed to hash a password with a salt. The salt and hashed password are being saved in the database. The password itself is not.
Given the sensitive nature of the operation, I wanted to make sure everything was kosher.
import hashlib
import base64
import uuid
password = 'test_password'
salt = base64.urlsafe_b64encode(uuid.uuid4().bytes)
t_sha = hashlib.sha512()
t_sha.update(password+salt)
hashed_password = base64.urlsafe_b64encode(t_sha.digest())
Based on the other answers to this question, I've implemented a new approach using bcrypt.
Why use bcrypt
If I understand correctly, the argument to use bcrypt over SHA512 is that bcrypt is designed to be slow. bcrypt also has an option to adjust how slow you want it to be when generating the hashed password for the first time:
# The '12' is the number that dictates the 'slowness'
bcrypt.hashpw(password, bcrypt.gensalt( 12 ))
Slow is desirable because if a malicious party gets their hands on the table containing hashed passwords, then it is much more difficult to brute force them.
Implementation
def get_hashed_password(plain_text_password):
# Hash a password for the first time
# (Using bcrypt, the salt is saved into the hash itself)
return bcrypt.hashpw(plain_text_password, bcrypt.gensalt())
def check_password(plain_text_password, hashed_password):
# Check hashed password. Using bcrypt, the salt is saved into the hash itself
return bcrypt.checkpw(plain_text_password, hashed_password)
Notes
I was able to install the library pretty easily in a linux system using:
pip install py-bcrypt
However, I had more trouble installing it on my windows systems. It appears to need a patch. See this Stack Overflow question: py-bcrypt installing on win 7 64bit python
EDIT: This answer is wrong. A single iteration of SHA512 is fast, which makes it inappropriate for use as a password hashing function. Use one of the other answers here instead.
Looks fine by me. However, I'm pretty sure you don't actually need base64. You could just do this:
import hashlib, uuid
salt = uuid.uuid4().hex
hashed_password = hashlib.sha512(password + salt).hexdigest()
If it doesn't create difficulties, you can get slightly more efficient storage in your database by storing the salt and hashed password as raw bytes rather than hex strings. To do so, replace hex with bytes and hexdigest with digest.
Edit:
The library suggested in this answer is now outdated, and the hashlib key derivation functionality mentioned in this answer: https://stackoverflow.com/a/56915300/893857 is a good suggestion to use nowadays.
Original Answer
The smart thing is not to write the crypto yourself but to use something like passlib: https://passlib.readthedocs.io/en/stable/#
It is easy to mess up writing your crypto code in a secure way. The nasty thing is that with non crypto code you often immediately notice it when it is not working since your program crashes. While with crypto code you often only find out after it is to late and your data has been compromised. Therefore I think it is better to use a package written by someone else who is knowledgeable about the subject and which is based on battle tested protocols.
Also passlib has some nice features which make it easy to use and also easy to upgrade to a newer password hashing protocol if an old protocol turns out to be broken.
Also just a single round of sha512 is more vulnerable to dictionary attacks. sha512 is designed to be fast and this is actually a bad thing when trying to store passwords securely. Other people have thought long and hard about all this sort issues so you better take advantage of this.
As of Python 3.4, the hashlib module in the standard library contains key derivation functions which are "designed for secure password hashing".
So use one of those, like hashlib.pbkdf2_hmac, with a salt generated using os.urandom:
from typing import Tuple
import os
import hashlib
import hmac
def hash_new_password(password: str) -> Tuple[bytes, bytes]:
"""
Hash the provided password with a randomly-generated salt and return the
salt and hash to store in the database.
"""
salt = os.urandom(16)
pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return salt, pw_hash
def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool:
"""
Given a previously-stored salt and hash, and a password provided by a user
trying to log in, check whether the password is correct.
"""
return hmac.compare_digest(
pw_hash,
hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
)
# Example usage:
salt, pw_hash = hash_new_password('correct horse battery staple')
assert is_correct_password(salt, pw_hash, 'correct horse battery staple')
assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3')
assert not is_correct_password(salt, pw_hash, 'rosebud')
Note that:
The use of a 16-byte salt and 100000 iterations of PBKDF2 match the minimum numbers recommended in the Python docs. Further increasing the number of iterations will make your hashes slower to compute, and therefore more secure.
os.urandom always uses a cryptographically secure source of randomness
hmac.compare_digest, used in is_correct_password, is basically just the == operator for strings but without the ability to short-circuit, which makes it immune to timing attacks. That probably doesn't really provide any extra security value, but it doesn't hurt, either, so I've gone ahead and used it.
For theory on what makes a good password hash and a list of other functions appropriate for hashing passwords with, see https://security.stackexchange.com/q/211/29805.
For this to work in Python 3 you'll need to UTF-8 encode for example:
hashed_password = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()
Otherwise you'll get:
Traceback (most recent call last):
File "", line 1, in
hashed_password = hashlib.sha512(password + salt).hexdigest()
TypeError: Unicode-objects must be encoded before hashing
passlib seems to be useful if you need to use hashes stored by an existing system. If you have control of the format, use a modern hash like bcrypt or scrypt. At this time, bcrypt seems to be much easier to use from python.
passlib supports bcrypt, and it recommends installing py-bcrypt as a backend: http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html
You could also use py-bcrypt directly if you don't want to install passlib. The readme has examples of basic use.
see also: How to use scrypt to generate hash for password and salt in Python
I don' want to resurrect an old thread, but... anyone who wants to use a modern up to date secure solution, use argon2.
https://pypi.python.org/pypi/argon2_cffi
It won the the password hashing competition. ( https://password-hashing.net/ ) It is easier to use than bcrypt, and it is more secure than bcrypt.
I did the same thing in NodeJs before:
echo "console.log(require('crypto').createHmac('sha256', 'salt').update('password').digest('hex'))" | node
it's equivalent in python is:
python3 -c 'import hashlib;import base64;import hmac;print(hmac.new(b"salt", "password".encode(), hashlib.sha256).hexdigest())'
And the equivalent shell command is:
echo -n "password" | openssl sha256 -hmac "salt"

python hex hmac md5 of passwords not matching javascript

i have a javascript password coder
md5 = hex_hmac_md5(secret, password)
How can i emulate this in python - ive tried md5 but that is not the same value
i got my md5 javascript code from this website:
Pajs Home
(md5.js)
He states the use is as follows:
In many uses of hashes you end up
wanting to combine a key with some
data. It isn't so bad to do this by
simple concatenation, but HMAC is
specifically designed for this use.
The usage is:
hash = hex_hmac_md5("key", "data");
The HMAC result is also available
base-64 encoded or as a binary string,
using b64_hmac_* or str_hmac_*.
Some other hash libraries have the
arguments the other way round. If the
JavaScript HMAC doesn't match the
value your server library generates,
try swapping the order.
I have tried some python like this:
> def md5_test(secret, password):
>
> return md5(secret+password).hexdigest()
Can anyone tell me what the code should be in python to get the same value?
Thanks
That's what Python's hmac module is for, don't use the MD5 function directly.
# Right
import hmac
# Note that hmac.new defaults to using MD5
hmac.new("password", "message").hexdigest() # 'f37438341e3d22aa11b4b2e838120dcf'
# Wrong
from hashlib import md5
md5("message"+"password").hexdigest() # 'd0647ee3be62a57c9475541c378b1fac'
md5("password"+"message").hexdigest() # 'c494404d2dd827b05e27bd1f30a763d2'
Also take a look at how HMAC is implemented (e.g. on Wikipedia).

Categories

Resources