Hudzilla.org - the homepage of Paul Hudson
Contents > Functions > Playing with strings Wish List | Report Bug | About Me ]

4.7.10     Making a secure data hash: sha1()

This is NOT the latest copy of this book; click here for the latest version.

string sha1 ( string source [, bool raw_output])

SHA stands for the "Secure Hash Algorithm", and it is a way of converting a string of any size into a 40-bit hexadecimal number that can be used for verification. If you did not know what hashes are, they are like unidirectional (one-way) encryption designed to check the accuracy of input. By unidirectional I mean that you cannot run $hash = sha1($somestring), then somehow decrypt $hash to get $somestring - it is just not possible, because a hash does not contain its original text. What, then, are hashes good for?

Well, imagine you have users enter a password. How do you check the password is correct?

<?php
    
if ($password == "Frosties") {
        
// ........
    
}
?>

While that solution certainly works, it means that whoever reads your source code gets your password. Similarly if you store all your users' passwords in your database and someone cracks it, you are going to look pretty dumb. If you have the passwords of people on your database, or in your files, then malicious users will not be able to retrieve the original password.

The downside of that is that authorised users will not be able to get at the passwords either - whether or not that is a good thing varies from case to case, but usually having hashed passwords is worthwhile, and people who forget their password must simply reset it to a new password as opposed to retrieving it.

Hashing is also commonly used to check whether files have downloaded properly - if your hash is equal to the correct hash value, then you have downloaded the file without problem.

The process of data hashing involves taking a value and converting it into a semi-meaningless string of letters and numbers of a fixed length. There is no way - no way whatsoever - to "decrypt" a hash to obtain the original value. The only way to hack a hash is to try all possible combinations of input, which, given that the input for the hash can be as long as you want, can take millions of years.

Consider this script:

<?php
    
print sha1("hello") . "\n";
    print
sha1("Hello") . "\n";
    print
sha1("hello") . "\n";
    print
sha1("This is a very, very, very, very, very, very, very long test");
?>

Here is the output I get:

aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
66f52c9f1a93eac0630566c9b82b26f91d727001

There are three key things to notice there: firstly, all the output is exactly 40 characters in length, and always will be. Secondly, the difference between the hash of "hello" and the hash of "Hello" is gigantic despite the only difference being a small caps change. Finally, notice that there is no way to distinguish between long strings and short strings - because the hash is not reversible (that is, you cannot extract the original input from the hash), you can create a hash of strings of millions of characters in just 40 bytes.

If you had stored your users' passwords hashed in your database, then you need to hash the password they provide before you compare it against the value in your database. One thing that is key to remember is that sha1() will always give the same output for a given input.

Author's Note: If you set the optional second parameter to true, the SHA1 hash is returned in raw binary format and will have a length of 20.





<< 4.7.9 Changing string case: strtoupper(), strtolower(), ucfirst(), and ucwords()   4.7.11 Alternative data hashing: md5() >>
Table of Contents
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.



My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!



Top-right shadow
 
Bottom-left shadow Bottom shadow

Comments from other readers
A PHP User - 30 Aug 2008

> how do i sent the original password
> to the user if he forgets it

If the password is a dictionary word (such as "dolphin"), you can write a PHP script to hack it in under a second. There are about 60,000 words in an English dictionary, and PHP can test about 300,000 sha1's per second (on my computer).

What if the user chose a good password? Then you don't hack it. You ask him to enter a new password.

To see why, assume that the password is 10 characters long, made up of random letters. The total number of possible passwords is 26^10 = 141167095653376. You could probably try 300,000 per second on one computer, so that's 470,556,985 seconds, or about FIFTEEN YEARS. There are probably math tricks to make it faster, but you'll need a lot of processor time to break the code.

Nitin Kushwaha - 30 Aug 2008

Decryptum doesnt crack the password, instead they strip off the 40-bit hash from the file-open password and they give you back ur file without password.

Thats how Decryptum works.

Nitin Kushwaha

CHFI.CEH.CIW-SA.ITIL.SCSCSA.MCSE.MCSA

A PHP User - 30 Aug 2008

how do i sent the original password to the user if he forgets it

Rajneesh Noonia - 30 Aug 2008

YES SEE http://md5encryption.com/?mod=decrypt

deathgod - 30 Aug 2008

the number of possible different has combinations is 255^40(255 to the power of 40). on window's default calculator program 255^40=1.8264476014903146144805026366139e+96. You are going to need the biggest database in the world if you are going to compile 1.8264476014903146144805026366139e+96 possible values :)

A PHP User - 30 Aug 2008

Nice text. But there seems to be a little problem.
"Finally, notice that there is no way to distinguish between long strings and short strings - because the hash is not reversible (that is, you cannot extract the original input from the hash), you can create a hash of strings of millions of characters in just 40 bytes."
Yeah, right. You can't feel any difference between short lines and long texts. And here comes the problem of colision.

Gus Jones - 30 Aug 2008

Outstanding. A topic that's always complicated in other books and here Paul Hudson explains it clearly. I really appreciate this web book!

Unix Programmer - 30 Aug 2008

IN the sentence

"If you have the passwords of people on your database, or in your files, then malicious users will not be able to retrieve the original password.",

I assume that you mean

"If you hash the passwords of people on your database, or in your files, then malicious users will not be able to retrieve the original password.",

A PHP User - 30 Aug 2008

The second argument only works for PHP >= 5.

PGP User - 30 Aug 2008

In fact, if you can decrypt this within my lifetime, I'll give you $50.

69177c6f2ba9d87a0e2eeeb003ac13d67ce5c91c

Today is August 9th, 2005. My email is in the encrypted hash.

PGP User - 30 Aug 2008

First of all, www.decryptum only decrypts Word documents, it seems.

You need to understand encryption. For more info on encryption, visit:
http://www.inet2000.com/public/encryption.htm

QUOTE
It would take significantly longer than the age of the universe to crack a 128-bit key.
END QUOTE

PGP User - 30 Aug 2008

First of all, www.decryptum only decrypts Word documents, it seems.

You need to understand encryption. For more info on encryption, visit:
http://www.inet2000.com/public/encryption.htm

QUOTE
It would take significantly longer than the age of the universe to crack a 128-bit key.
END QUOTE

A PHP User - 30 Aug 2008

There is a website. http://www.decryptum.com , make a Word document, password protect it using *128* bit encryption key, and then upload it to this website. They will crack it in less than 3 minutes :) :) :) Millions of Years?

A PHP User - 30 Aug 2008

The million years to crack thing is a bit exaggerated. While it COULD take that long, most hackers are able to use rainbow tables and other password cracking emthods to retrieve basic passwords in little time.

A PHP User - 30 Aug 2008

Can I retrieve the original string from the hashed string?

Kidding. Good job, maybe just a bit too many repeats of the answer to my question.



Add comment
Please note that by posting a comment here you are committing it to the public domain. This is important so that others can make use of your code themselves, and also so that I can incorporate helpful notes directly into the main text. Comments are limited to 2000 characters in length.

If you are reporting an error in the content, please tell me directly.

Your name/email address:
Your comment:
 
Now, in order to verify that you're a real person, please answer this simple question: what is one plus three?
The answer is:
(please write in
numbers, eg 19)


Top-right shadow
 
Bottom-left shadow Bottom shadow