
|
View Full Version : I still do not understand how to decode md5
lexington 03-07-2008, 06:14 PM The php.net site sucks when it tries to explain md5 and I asked here but no one seemed to answer my question. I want to store a password in a cookie so I use:
$blah = md5($pass);
setcookie("pass", $blah);
How do I make the script read the password from the MD5 jibberish? I want to have an if statement such as
if ( $blah == ADMIN_PASS )
{
echo "password works";
}
However I do not know how to make it work. Does this only work with databases where I md5 the password into a db table and later check that table with md5 to see if they match?
orbitz 03-07-2008, 06:26 PM md5 is irreversible; you can't decode that.
To compare $blah with the value of constant ADMIN_PASS, make sure you need to md5 the constant as well.
lexington 03-07-2008, 06:30 PM Well I'll be darn thanks it works now. I thought I had tried that already and it didn't work but I guess my page was cached or something.
$blah = md5($pass);
setcookie("pass", $blah);
if ( $blah == md5(ADMIN_PASS) )
{
echo "password works";
}
Works great thanks :D
lexington 03-08-2008, 10:08 AM Thanks again I totally understand how md5 works now. I have one final question. Is it ok if I use substr to chop md5 down to about 16 characters for passwords? I think that having 32 chars for every db row would waste space. I know a very little amount but if I can make things more efficent I tend to do so. I doubt the security would be highly compromised if I shorten the limit? Like:
substr(md5($test), 0, 16);
Thanks
DephNet[Paul] 03-08-2008, 10:41 AM No, MD5 checksums are always 32 characters as far as I am aware.
Cutting them down to 16 characters will invalidate the checksum.
Paul
fwwebs 03-08-2008, 10:43 AM I'm not absolutely positive, but I believe you should be able to do that.
lexington 03-08-2008, 10:43 AM Cutting them down to 16 characters will invalidate the checksum.
Meaning that it will not be secure or?
DephNet[Paul] 03-08-2008, 10:47 AM Meaning that it will not be secure or?MD5 checksums are not secure anyway.
Paul
mcrilly 03-08-2008, 01:30 PM ;4998879']MD5 checksums are not secure anyway.
Paul
Why not? They're only bruteforcable. Also, what is "secure", exactly?
DephNet[Paul] 03-08-2008, 01:37 PM MD5 was designed by Ron Rivest in 1991 to replace an earlier hash function, MD4. In 1996, a flaw was found with the design of MD5; while it was not a clearly fatal weakness, cryptographers began recommending the use of other algorithms, such as SHA-1 (which has since been found vulnerable itself). In 2004, more serious flaws were discovered making further use of the algorithm for security purposes questionable. In 2007 a group of researchers including Arjen Lenstra described how to create a pair of files that share the same MD5 checksum.I think that answers your question.
Paul
mcrilly 03-08-2008, 01:39 PM ;4999099']I think that answers your question.
Paul
No actually, it doesn't, as I asked two questions, which I won't repeat.
DephNet[Paul] 03-08-2008, 01:45 PM Why not?See previous answer.
Also, what is "secure", exactly?Something that does not give the same checksum for two, maybe more, different files.
SHA-1 sums are more secure, still vulnerable tho.
Paul
mcrilly 03-08-2008, 01:48 PM I guess you've missed my point completely. Thanks for trying anyway.
DephNet[Paul] 03-08-2008, 01:49 PM How about trying to explain your point?
Paul
mcrilly 03-08-2008, 02:01 PM I'll simply ask the question again, if you don't understand it, then please simply refrain from answering: "What is secure exactly?" - i.e. is anything secure?
DephNet[Paul] 03-08-2008, 02:06 PM is anything secure?Yes. A computer that is turned off, unplugged from any network, and burried about 200 feet underground in a concrete block 100 feet square.
Anything can be secure, depends how much access you want people to have.
If you think that MD5 hashes are secure then you might want to detail how they are secure.
Paul
mcrilly 03-08-2008, 02:28 PM I never stated they are secure. Also, given the context of the conversation, your point on a secure system is invalid - the system has to remain useful and secure.
ZeroPing 03-08-2008, 05:10 PM Meaning that it will not be secure or?
The theory - skip below if you aren't interested
[1] Collisions - When you compute an MD5 hash, what you get is a low probability of collisions - i.e. there is a low probability for a given $a of your finding $b such that
$a != $b, but md5($a) == md5($b)
[2] 32 Chars - The 32 chars are basically hexadecimal digits - sixteen 2-digit hexadecimal numbers. So when you chop them down to 16 chars, you get eight 2-digit hexadecimal numbers
[3] Since you've lost eight of the original 2-digit hexadecimal numbers, it is far easier for md5chopped(a) == md5chopped(b) - only eight hex numbers have to match rather than sixteen. So you've -vastly- increased the probability of a collision.
[4] Just for info - the probability of a collision has increased by (this is a very rough figure) 256 to the power of eight (each hex number can be 00 to FF, thats 256 possibilities, and there are eight such) - that is 2 to the power of 64. That is roughly 4 billion x 4 billion - the number of bytes on 16 billion 1 GB ram sticks.
Thats the maths/explanation. Practically speaking -
[1] Collisions can be generated theoretically / practically - there are papers/demos out on this subject. However it is very doubtful those will be used to break passwords when I last checked[they are much more useful to forge digital signatures]
[2] Rainbow tables do a much better job of breaking MD5 passwords.
[3] If you make a cormpromise now and your site / systems remain small, it will not really matter. But if you grow big, then some time in the future, this will snowball into a disaster. And then, the person who works on the code will probably go 'Who the heck is the idiot who wrote this code?'
Good luck either way :)
ZeroPing 03-08-2008, 05:16 PM Why not? They're only bruteforcable.
It is also possible to generate collisions (see my reply above) to a given MD5 hash, under certain conditions. For example, digital signatures can be forged using this technique. Doesn't really apply to password hashes as far as I know, of course.
Also, what is "secure", exactly?
Nothing is 'Secure'. But the person you quoted was saying 'X is insecure' - meaning that it has been proven to be insecure.
To define lack of security is simple - if MD5 is unable to provide the security features it provides (in the above case, being used to digitally sign text in such a fashion that only the owner can sign the text, and anybody can verify the signature as belonging to the owner) - then it is insecure. While you do have a point, so does the other poster.
luke_a 03-10-2008, 10:48 AM Also look into generating a salted hash, using sha512, for your passwords.
hash('sha512', $password);
Also, never store a password, hashed or not, in a cookie. Use session_id's to identify users.
lexington 03-10-2008, 10:49 AM Thanks actually I already used a salt when I first created the password system. I checked it on md5 decrypt sites and they cannot break the password :)
GHDpro 03-10-2008, 11:34 AM Is it ok if I use substr to chop md5 down to about 16 characters for passwords? I think that having 32 chars for every db row would waste space.;
As mentioned elsewhere in this topic, md5 are 32 hexidecimal characters. So to save db space, store the md5 string as a 16-byte binary string.
(in PHP there is no hex2bin afaik, but for workarounds see the comments section of the bin2hex (http://nl.php.net/bin2hex) function)
cilina 03-11-2008, 04:45 AM I still can't decode password when I retrive it from mysql db
can anyone help :(
dollar 03-11-2008, 05:23 AM I still can't decode password when I retrive it from mysql db
can anyone help :(
It is impossible to "decode" an MD5 hashed password. Hashing a password with MD5 is a one way process, there's no going back. The only thing you can do is compare the hash to a hash of what a user inputs.
i.e. User signs up and uses the password: abc123
Password is stored in the database as: e99a18c428cb38d5f260853678922e03
When the user attempts to login, you take the text they submit on login, put that through MD5, and then compare it to the hash in your database to see if a proper password was entered.
mcrilly 03-11-2008, 10:56 AM Dollar is spot on. You basically take their input, hash it using the MD5 algo and your salt and then compare that hash to the stored, hashed password in your DB.
Don't try and decode the MD5 hash :)
sasha 03-11-2008, 02:39 PM Just a note, if you want to be able to revert password to it's original value you can try using real encryption (md5 is hashing not encryption). I find mysql's aes_encrypt and aes_decrypt functions simple and easy to use.
SELECT @db_secret := 'some_secret_string_you_use_to_encrypt_your_passwords'
UPDATE users SET password= AES_ENCRYPT('this_is_password',@db_secret) where id=1
SELECT AES_DECRYPT(password , @db_secret) from users WHERE id=1
# this will return 'this_is_password'
mcrilly 03-11-2008, 04:07 PM Just a note, if you want to be able to revert password to it's original value you can try using real encryption (md5 is hashing not encryption). I find mysql's aes_encrypt and aes_decrypt functions simple and easy to use.
SELECT @db_secret := 'some_secret_string_you_use_to_encrypt_your_passwords'
UPDATE users SET password= AES_ENCRYPT('this_is_password',@db_secret) where id=1
SELECT AES_DECRYPT(password , @db_secret) from users WHERE id=1
# this will return 'this_is_password'
Nice trick this, I'll have to remember this and give it a try :)
sasha 03-11-2008, 05:18 PM Nice trick this, I'll have to remember this and give it a try :)
The problem, and there is always one, is that your data in this case is as secure as your key (db_secret var). So if someone gets hold of that key, they can decrypt all of your passwords.
To work around that I create "mysql connection file". In that file there is data required to connect to the database (username and password) and the db_secret (key i use for encrypting the data in the database). I encrypt this file using variation of one-time pad algorithm. Yet again this algorithm relies on yet another "secret key" which must not be compromised. I come up with this by doing some hashing of the key which I do not keep secret.
It goes something like this
file private.php
<?php
$encryption_key = 'some_long_random_string' ;
$db_username = 'username';
$db_password = 'password' ;
$db_secret = 'secret_key';
my_encrypt ($db_username .'::' . $db_password . '::'. $db_secret) ;
function my_encrypt($string , $encryption_key) {
// here i change the key using some hashing and substr() and stuff like that and they use variation of one-time pad and that key to enctypt the $string;
return $encrypted_string;
}
?>
This file never gets uploaded to the server, it is just used to generate mysql connection file
php private.php > .ht_mysql_connection_file
on server, i upload ioncube encoded file which knows how to decrypt .ht_mysql_connection_file using "public" $encryption_key, connects to the database using data from that file and exports @db_secret variable to the current mysql connection which I can call at any time and use it as argument to AES_ENCRYPT and AES_DECRIPT functions (those calls too are within some classes in ioncube encoded files). It is still possible for someone who obtains full access to server to try to decode the files and data, so there is built in mechanism in the system that will notify me of bad calls to these functions and it will replace mysql connection file with something that is good enough to keep thief busy.
it's suppose to not to be decode, if you want to check a password for example..
you need to control the password by encrypt it and compare it to the stored version !
vpsville 03-13-2008, 10:19 AM Using MD5 or any other common hashing algorithm is very secure. You don't need to worry about salts or collisions.
A collision would break security in this case if someone guessed someone elses password wrong, and it produced an identical hash. Thats so unlikely its not worth your time coding salts or worrying about other algorithms.
The other instance would be if the database was stolen, and each password was brute forced to generate an identical hash. But do do that, you don't need a collision at all, just time.
Salting can theoretically increase the security of the hashed passwords (by making it take more time to brute force them), but only if that salt is kept secret. If they can steal your database why can't they steal your salt, which is probably in your PHP code anyway right? :o
Its always funny reading about people complaining that md5 is 'insecure'...they have no idea how hard it is to exploit that theoretical collision even with a variable length message.
A collision is concerning if you are signing your emails with md5 and you work for the CIA. But on the password field of a php web page login? No need to worry at all about collisions and salts will not increase security.
No one has shown a collision for sha1 yet, they just theorized its possible.
Form1 03-13-2008, 11:52 AM vpsville: That's not true. Salting each record with a different salt, as a well configured system does, means that for N users, you make a brute force attack N times harder. Otherwise, an attacker can run a dictionary attack against the entire userbase, and while this won't necessarily help an attack gain access to any particular account, it will quickly lead to insecure passwords being compromised.
Salting the entire system with a static salt is much poorer security, but still prevents dictionary attacks - if you simply MD5 your passwords with no salt at all, an attacker can use a precomputed dictionary of MD5 password hashes - often containing common words, phrases, and so forth - in order to quickly and easily compromise your database.
In short: salting is extremely important, and you should salt each record separately. Given how trivial salting is, you should do it.
Take it easy,
David Berube
vpsville 03-13-2008, 12:06 PM When implementing security you need to be aware of the threat. Just what attack scenario are you attempting to prevent with a salt? A hacked server resulting in a downloaded database?
Yes, salting each record with a different SECRET salt does increase the time taken to brute force the database.
Unfortunately in order to gain any significant benefit from the salt, the algorithm used to generate the salt must be kept secret. If the database and the php files are hacked/stolen, this is a moot point.
How do you recommend to create unique salts for each record, and keep the salts/algorithm safe from the root user on the server?
That is a challenging task and I'm curious to hear your take on this.
Form1 03-13-2008, 12:36 PM The salt does not have to be kept any more secret than the crypted hash for the password. The point of the salt is not that it's secret, the point is that instead of having to do the dictionary attack once, the attacker needs to do it once *for each user*.
With no salts at all, the attacker can even reuse a computed list of hashes from a previous attack - such lists can even be downloaded from the various sites on the Internet.
With a single static salt, the attacker can run a dictionary attack against your particular salt and hash combination, and then he will quickly discover all of the weak passwords in your database. With a per-user salt - even one generated via a weak random number generator - the attacker is forced to attack each user separately - this means that if you have 10,000 users, it's 10,000 times harder to search the entire userspace for weak passwords. (This is, incidentally, why Linux does per-user salts.)
Because the goal of salting your passwords is to split a simple password operation into a more complex one, it is not generally important that you must have a cryptographically secure salt - as far as I know, it's not generally useful to an attacker to be able to predict salts. Nonetheless, it's probably wise to use a cryptographically strong random number generator.
Take it easy,
David Berube
vpsville 03-13-2008, 01:06 PM You're correct when you say salting will create the need for more hashing to occur. But I don't think this makes weak passwords much harder to find.
With the salting you suggest an attack would consist of hashing every dictionary word and comparing it to one user. So the dictionary is run through for each user.
iterations = (words in dictionary * 1 user) * number of users.
without a salt, each word is hashed and compared to all users.
iterations = (words in dictionary * number of users).
As I understand it the number of iterations is identical with or without a salt. So it all comes down to the cost of creating a md5 hash.
Its true that more hashing will occur with salts, but given the low computational cost of md5, its a moot point. Any weak passwords will be discovered in a few of hours (or seconds) of cracking either way.
To give you an indication of the computational cost of running through a dictionary attack with md5, in 2003 a 1.6ghz pentium could do 460,000 sha1 hashes per second.
md5 is faster, and computers are much faster now. How long to go through websters dictionary on a p4 quad core?
Form1 03-13-2008, 01:21 PM Salting passwords is not a guaranteed protection against dictionary attacks; it simply slows down the attack. Generally, the slowest part of a dictionary attack is computing the hashes *by far*: it's much slower to compare two strings than to create a MD5 hash.
Given that the total effort required to institute a per-user salt is perhaps ten lines of code - and likely less - it's is nonetheless worth the effort.
Additionally, note that while it may be feasible to find dictionary passwords fairly quickly even with a salt, salting also slows down brute force approaches and expanded dictionary attacks: some dictionary attacks, for example, will find all words followed by a a number, all combinations of two words, and so forth. This approaches become less feasible when proper salting is used.
Essentially, salting is a low cost way to increase the computational expense of attacking a list of password hashes. It is not a silver bullet, but, given the simplicity of the technique and almost complete lack of cost, it is important.
Take it easy,
David Berube
vpsville 03-13-2008, 02:24 PM Your point is well taken. Random salting does add security with little or no cost. This is in the case of a stolen password database; and you're probably already screwed if that happens. But the cost is low so go for it.
Since I just researched rainbow tables and ophcrack, here are my suggestions of beefing up your password security:
1. Use a very strong hash. PHP supports SHA512. This one is great (512bit hash!) because its SLOW to generate and a good rainbow table would take hundreds of gigabytes.
2. Encourage use of strong(long) passwords.
3. Salt your passwords with another long hash, unique to the user.
4. Don't let your server get hacked and your data stolen! :)
Form1 03-13-2008, 02:30 PM An excellent set of suggestions. IIRC, SHA512 is pretty much where it's at for hashing functions at the moment.
Password strength is an excellent point; anyone have any good link for an AJAX password strength indicator? I've seen some, but most of them had one or more unfortunate flaws.
Take it easy,
David Berube
orbitz 03-13-2008, 02:39 PM I just googled it, the first one is here:
http://simplythebest.net/scripts/ajax/ajax_password_strength.html
Not so sure how good it is yet.
folsom 03-14-2008, 04:27 PM Wow, some of you guys take simple stuff way too far. md5 is fine for hashing tiny pieces of data like passwords. The method that I use is the typical md5(username@password) scheme that a lot of others use. Geez the real reason that I hash is because I don't want to see people's passwords.
orbitz 03-14-2008, 05:19 PM Wow, some of you guys take simple stuff way too far. md5 is fine for hashing tiny pieces of data like passwords. The method that I use is the typical md5(username@password) scheme that a lot of others use. Geez the real reason that I hash is because I don't want to see people's passwords.
md5 alone is fine only if your data is not so important that when you lose it, you don't care.
Tim Greer 03-14-2008, 10:47 PM Varying salts won't matter anyway, as if anyone's got a basic idea of how it works, it would just use the same brute force against the salts for that specific encrypted password (assuming they have the encrypted versions -- if they don't, then it's just a brute force attempt anyway and the same methods would have to be used). MD5 is probably fine for almost anyone. The differences, besides the potential for collisions (which is pretty unlikely), is that md5 hashes can be stored in a database and be compared to the MD5 hash in your encrypted password file(s), which just saves time from having to re-brute force each time. If they have that encrypted list, they can just brute force (or crack the passwords, is what I mean in this case) against the existing salt. But, if someone has access to your passwords to brute force them or effectively 'decrypt' them (i.e.; find out what they are), then you're probably screwed anyway.
So, don't worry about md5, sha1, or some other salt. Just stay away from base64 and two character salts, as there is a password character limit on one and the other just isn't a good encryption method. Sure, there are better ways to encrypt passwords than MD5, but I doubt it's a problem for most people.
If you're worried, use a custom method (you can create your own) and don't worry about it too much. If you're writing it to a cookie, I doubt it's a government secret and it's so unlikely it would matter unless someone already somehow accessed your encrypted data (which no one should have access to unless they've compromised your site, system or database anyway). I'm not trying to make light of password security, and I encourage people always use the best methods, but it's not as dire as a white paper can theorize or conclude based upon usually unrealistic scenarios.
If you use MD5, just keep the 32 char hash, there's no point in saving 16 characters due to space constraint worry (there's nothing to worry about there). Cutting it in half will defeat the purpose, because then you will more likely have collisions. Sha512 is fine, but it's still a static hash. I personally roll out my own routines that are unique per hash, it's faster, and just as secure in the way the Sha512 and other hashes work. However, by all means, use the most secure technique anyway (it never hurts).
Elliot A 03-16-2008, 07:26 AM Heres a few thoughts.
1. Vary the salts per user.
One brute force way of calculating a hash is to pre-generate a list of hash outcomes, and then use an index to lookup the value. This can make a 2 day brute force session turn into a 2 second lookup. Varying the salts per hash invalidates any rainbow table lookup, as they have to be regenerated for each new hash, which of course takes time.
2. Hash Multiple Times
Best way to slow down a brute force attack? Make the calculations expensive. You can MD5 a hash a couple of thousand times to make it take a second or two to compute killing any hopes of getting the result in this century. Bonus points for salting and multiplying the iterations by the string length (eg: md5 interations = 100,000 * strlen ($pass)).
3. Use SHA1 and MD5 together if they are all you have
Collisions are algorithm specific generally. Using multiple algorithms would detect an attempt to cause a collision.
Eg:
md5 ( sha1 ( $pass ) . md5 ( $pass ) );
4. Don't write your own hashing algorithm
While you could throw attackers off the trail by doing it your own way, unless you understand advanced cryptanalysis you are weakening your security. Build off the current, published and vetted algorithms.
5. Password Policies
Enforce minimum password lengths and add extra non a-z characters. No point in using fancy encryption if the password is 'a', the brute force algorithm would find it first up.
Finally a thought on database storage. You can store a MD5 as a binary string, but you would be better off with any fixed length field (ie: char(32)). It would be premature optimisation to try to compress the hash, as the lookup and transmission time would be negligible.
|