md5() is usually for passwords, short strings
but this time I wanted to encrypt (w/o needing to decrypt) a large string, like a whole article ... (not to mention i'd be needing to do this every few seconds)
Would this be a problem? or would it take processor more work/longer to md5 a big string vs a short password?
I read md5 is really really fast..
For those curious, I'm trying to generate a "signature" of the string in question
Oh dear.
Well, MD5 is not encryption.
(Encryption is, by definition, designed to be reversible.)
Do not use MD5 or SHA for password hashes - they are too fast!(And MD5 is plain broken for such a task.)
Hash algorithms (including MD5) take time proportional to the size of the input, or O(n). That means, it will take about "twice as long" to hash 100MB as it does to hash 50MB. For in-memory PHP strings this will be "in the blink of an eye" (as the I/O will most likely be the bottleneck) - you'll need to run performance benchmarks on real data in a real environment to quantify it.
MD5 is indeed "really really fast"; the algorithm is relatively simple and, like many hash algorithms, was designed to be fast. Don't worry about performance until there is a real performance issue - modern CPUs are very fast. Also, while MD5 (and SHA) is fast, running MD5 back-to-back-to-back as in an infinite loop will of course "eat" all the CPU; an idle CPU is a wasted CPU if there is work to be done.
However, consider SHA (preferable SHA-2) for a "general" signature hashing - it is only marginally slower (by a constant factor) but it is a better algorithm, even when trimmed to the same output space, and just might prevent issues in the future.
Related
So I know that MD5's are technically a no-no in new applications, but I randomly had a thought of this:
Since
md5($password);
is insecure, wouldn't
md5(md5($password))
be a better alternative?
would it keep getting more secure the more I use it? Say if I made a function like this
function ExtremeEncrypt($password)
{
$encryptedpass = md5(sha1(md5(md5($pass))));
return $encryptedpass;
}
Would this function be a good alternative to say using a random salt for every account like vbulletin does.
Double hashing a string does nothing except limit your key space and make collisions more likely. Please don't do this. Double md5 hashing is actually less secure than a single hash with some attack vectors.
A better option would be to use the password_hash function in php 5.5 or ircmaxell's password_compat library for earlier php versions.
First of: hash and encryption are not the same. Hash is a one-way function while encryption expects data could be decrypted.
You should not try to invent your own solution when it comes to security. In PHP, since 5.5 version, there is native solution called Password Hashing. md5() is insecure and you should be aware of that.
If you have PHP below 5.5 version, you should use salt to hash & store your passwords.
You have lots of answers here and they are accurate but they don't really explain why.
MD5 is a hashing algorithm. What a Hashing algorithm does, is take a long piece of data and analyse it cryptographically in a way that creates a smaller piece of data. So from ABCDEFGHIJKLMNOPQRSTUVWXYZ with my custom hash algorithm I might create a single digit hash 5.
When that is done, you lose information - ABCDEFGHIJKLMNOPQRSTUVWXYZ contains far more information than 5 and there is no way to make the translation the other way.
The problem with hashing in a way that only allows an outcome of 0-9 ( this is effectively a Checksum ) is that if you take two pieces of text, the chances are quite high that they will have the same hash. So maybe with my algorithm ZZZZZZZZZ will also produce a hash of 5. This is what is termed a Hash Collision.
Now what happens if I take the hash of my hash? Well, my starting point is already very low information - the most it can possibly be is one of ten digits, so the chance of a collision is now exceedingly high. Supposing when my hash algorithm runs on numbers it returns 1 if it is odd and 0 if it is even- so if I have a hash of ABCDEFGHIJKLMNOPQRSTUVWXYZ which comes to 5 then I have a 10% chance of a collision. But if I make a hash of that hash, I will now have a 50% chance of a collision.
The trick of cryptography is hiding information in such an enormous possible space that it is unbelievably hard to find. The more you shrink that possible space, the less well hidden your information is.
Short answer: No.
md5 is easy to break using brute-force. Adding additional layers of hashing only slows down a brute-force attack linearly.
First of all md5 isn't really encryption, because there isn't a decryption method to it. It's called hashing.
The standard practice is to salt your passwords:
$salt = [some random/unique number, people usually use user_id or timestamp]
$hashed_password = sha1($salt . $password)
Remember that you need to know the salt, hence usually it means storing it along with the hashed password.
You can have multiple salts, and arrange them however you like.
This question already has answers here:
Secure hash and salt for PHP passwords
(14 answers)
Closed 9 years ago.
I'm using PHP. I want a safe and fast password encryption system. Hashing a password a million times may be safer, but also slower. How to achieve a good balance between speed and safety?
I want to know the best encryption method in php and how to apply it.
I recommend using the new PHP 5.5 password API. It provides a secure means of hashing a password, while being fast enough.
If you don't have PHP 5.5 available there is a polyfill that works with PHP 5.3.7+: https://github.com/ircmaxell/password_compat
Use PHPass, it is an excellent hashing framework and very easy to use!
Use SHA512 http://php.net/manual/en/function.hash.php.
SHA512 is not cracked. I suggest to use a salt: Some random string that you append to the password before hashing. This can protect against precomputed rainbow tables but not against dictionary attacks if the attacker gains access to the database containing passwords and salts.
SHA512(password + salt) --> hash
Store hash and salt in the DB
When checking password, retrieve salt corresponding to user, concatenate it with password, hash it and compare it with stored hash.
Read here: How long to brute force a salted SHA-512 hash? (salt provided)
Thinking back about your question and particularly about your statement "Hashing a password a million times may be safer, but also slower. How to achieve a good balance between speed and safety". Indeed, repeatedly hashing will protect you against dictionary attacks by making it computationally prohibitively expensive to compute all hashes in a dictionary. I am not teaching you anything here. From the first link I gave you, it took around 46 milliseconds to calculate a SHA512 hash, which is relatively long. Out of hand I can think of the following factors that could influence your decision as you are in an arms race setting:
- Increasing computing power (more CPU cores and GPU computations)
- Improved Algorithms over time
- Amount of money available to the attacker
- The value to get out of your site if cracked (if low, it would not be worth the effort)
against
- Amount of CPU power you have at your disposal
As a rule of thumb, I would hash as many times as possible so as to not impact my web site performance. Taking into account the number of logins per seconds, you can roughly calculate the amount of CPU power you can afford to spend without impacting your site performance.
One last comment: Assuming hackers already have access to the table containing the user names and hashed passwords, you might at that point be more worried about all the bad things they can do on your site.
your not looking for encryption - your looking for hashing.
I suggest openwalls phpass http://www.openwall.com/phpass/
If you are using PHP5.5 they have a password hasing API
http://uk3.php.net/password
for more info.
MD5 (salt-less) has been used for a while a large number of lookup lists are around, Combined with modern hardware getting 700K + passwords per second it wont take long at all to "reverse" the password.
With a salt they are more secure, But still can be cracked quickly
In light of how many major websites have been hacked and their databases of password decrypted what is the best way to secure authentication?
Basically I am interested in a way to secure access to a part of a site to members in a way that if hacked would under no circumstances let hackers get a hold of the user's passwords.
Nothing is invulnerable but at least make it very difficult to crack.
http://codahale.com/how-to-safely-store-a-password/
Use bcrypt
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Why Not {MD5, SHA1, SHA256, SHA512, SHA-3, etc}?
These are all general purpose hash functions, designed to calculate a digest
of huge amounts of data in as short a time as possible. This means that they are
fantastic for ensuring the integrity of data and utterly rubbish for storing
passwords.
A modern server can calculate the MD5 hash of about
330MB every second. If your
users have passwords which are lowercase, alphanumeric, and 6 characters long,
you can try every single possible password of that size in around
40 seconds.
And that’s without investing anything.
If you’re willing to spend about 2,000 USD and a week or two picking up
CUDA, you can put together your
own little supercomputer cluster which will let you
try around 700,000,000 passwords a second.
And that rate you’ll be cracking those passwords at the rate of more than one
per second.
Salts Will Not Help You
It’s important to note that salts are useless for preventing dictionary
attacks or brute force attacks. You can use huge salts or many salts or
hand-harvested, shade-grown, organic Himalayan pink salt.
It doesn’t affect how fast an attacker can try a candidate password, given the
hash and the salt from your database.
Salt or no, if you’re using a general-purpose hash function designed for speed
you’re well and truly effed.
bcrypt Solves These Problems
How? Basically, it’s slow as hell. It uses a variant of the Blowfish
encryption algorithm’s keying schedule, and introduces a work factor, which
allows you to determine how expensive the hash function will be. Because of
this, bcrypt can keep up with Moore’s law. As computers get faster you can
increase the work factor and the hash will get slower.
How much slower is bcrypt than, say, MD5? Depends on the work factor. Using
a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on
my laptop. MD5, on the other hand, takes less than a microsecond.
So we’re talking about 5 or so orders of magnitude. Instead of cracking a
password every 40 seconds, I’d be cracking them every 12 years or so. Your
passwords might not need that kind of security and you might need a faster
comparison algorithm, but bcrypt allows you to choose your balance of speed
and security. Use it.
Besides proper password handling (like bcrypt, as already mentioned), you need to do the password hashing on a dedicated device/machine.
This "device" for password hashing is a separate system which contains so called "local parameter", which is an extra input to the hash function (say, 128-bit strong random number). This local parameter must be unreadable by the host system (your app, which does the user authentication).
Using such a dedicated machine for password hashing buys you an extra layer of security if your password database/app gets compromised.
Background:
I want to add a login to my small site, which is an online php application, which I'd like to build to be able to bear much user activity in the future.
Before I look further into implementing LightOpenID I want to add a normal login. The book I was learning from is called Head First PHP & MySQL (2008) and the final code of the chapter uses SHA('$user_password') as part of the mysql query.
As I take interest in Jeff Atwood's writing I'm well aware of bcrypt as of scrypt. But seen as there's no php implementation of scrypt and having no dedicated server to run it, I decided to at least look into implementing bcrypt for now.
However I'm not completely naive, I know I should watch out not to overextend my very humble hosting resources. The php app itself should always come first before anything else concerning resources.
Andrew Moore's method seems nice (though I'll have to see how to implement it on php 5.2.17 which my host uses) and it comes with a tip for hardware speed:
You should select a number of rounds that results in 200-250 ms of
work. Part of the reason why bcrypt is secure is that it is slow. You
must ensure to have a number of rounds that keeps that characteristic.
– Andrew Moore
Another user states that for him running microtime() gives 0.314 for Bcrypt(9), which thus would be near optimal.
The question:
Seen as I only have very humble resources at my disposal and I'd like to make the best of them, leaving most for the php app itself, am I still better off using Bcrypt(4) instead of something else?
Bcrypt(4) returns true almost instantly, but does it still keep that characteristic Moore talks about?(Would that be the part concerning RAM that makes it harder for GPU bruteforcing?) Or would SHA512 or something else actually be as fast but more secure at this point?
I'd expect Bcrypt(4) to win in this situation, but the hell do I know right? :p
Security is always about what you are trying to secure.
If you are more concerned about your resources than about your security, bcrypt(2) is already overkill. No hacker will ever try to break that for a normal application, having easier target sites like LinkedIn and many others, which just use functions from the sha family, with a single iteration, and unsalted. They will go for the 'low hanging fruit'. Or they could keep trying to hack your application, just not in the password encryption part.
SHA-512 is not much more secure than SHA-1 as password hashing algorithm [1], it has not been designed for that purpose. They can still be used as primitives for creating secure cryptographic algorithms though, but that's something no single person should do. To be considered secure, crypto algorithms must be public to be peer reviewed, and must pass the test of time. And obviously, must be designed for what you are going to use them. MD5, SHA-X, etc. are cryptographic algorithms, but weren't designed for storing passwords.
Just add or remove rounds to your bcrypt. In this case I would use 1 or 2. Also keep in mind that 1 round != 1 iteration. They are increased exponentially. If you read about how bcrypt works, you will see that there is much more to it than just iterations. For example, you mentioned 'unique salt per password'. Bcrypt already has that.
[1] For other things it's obviously more secure
You should look at security of the system, not just of bcrypt.
Certainly, if you want to store passwords, bcrypt or PBKDF2 is the way to proceed. Make sure you use a sufficiently large, random salt per user or password. Then try to maximize the number of iterations. If that's small, then it is small, but any iteration more is better than nothing.
Note that this does little against eavesdropping or man in the middle attempts (MitM). You should use SSL for that; the password or the hash (if you do the hashing client side) can be replayed otherwise.
Furthermore, if you want to protect against brute force attacks (attackers trying the most common passwords) you should create (or copy) a good password management scheme. Limit the amount of incorrect logins and try to let the users create strong passwords. Also limit the amount of information you return to your user regarding incorrect logins, that user may be the attacker.
Or would SHA512 or something else actually be as fast but more secure at this point?
Slowness is a major feature of password hashing algorithms (of which, bcrypt is one, but SHA-512 by itself is not) - the slower your algorithm is (relative to other algorithms), the harder it is for an attacker to brute force passwords based on the hashes. From this perspective, a single round of SHA-512 is less suitable than bcrypt for the purpose of securely storing passwords, because it is considerably faster.
In my opinion, the best approach to take is to pick a password hashing algorithm (bcrypt, PBKDF2, scrypt) and then tune the work factor to give you the best tradeoff between speed and security, given the computing resources available to you and the characteristics of your system. A higher work factor = more secure, but also more resource-intensive.
The good news is that users typically use your login function infrequently compared to other functions, so the impact of a slower/resource intensive login function is generally not a big problem.
we use md5 as a hashing algorithm in many parts of our code.
security in this context is NOT an issue. we just use md5 as a method of generating a unique identifier to store various items in apc etc.
collisions are an issue. although unlikely, it would cause some major issues.
anyone want to suggest something lighter on the cpu?
thanks.
we have just done some testing with md5 vs crc32.
using the following snippet:
<?
$start=microtime(true);
for($i=1;$i<=1000000;$i++){
md5(rand(10000000,99999999)); <--- crc32 tested here too.
}
$end=microtime(true);
echo $end-$start."\n";
?>
there results are as follow:
md5:
1.4991459846497
1.7893800735474
1.4672470092773
crc32:
0.97880411148071
0.94331979751587
0.93316197395325
so it would appear crc32 is about 1/3 faster then using md5.
It would be very hard (almost impossible, really) to beat CRC32 or a variant as it is so trivial (a rolling XOR across a single 32-bit word). Furthermore, since crc32 cheats and jumps to native code, unless the other solution does that as well, chances are the native CRC32 implementation won't be beaten.
However, it also has a much smaller space than MD5. Is the trade-off okay? CRC32's are usually only for basic error detection/framing... (It really is a "checksum" and not a "hashing" function for practical conversation purposes.)
Happy coding.
Also your numbers only show a 2/3 reduction ;-) In any case, I suspect this is not the main bottleneck and would highly recommend using an algorithm that will work -- be it MD5 or SHA1 or other. MD5 is only slightly computationally less expensive than SHA1 (it's within an order of magnitude), but it is possible that the implementation plays a factor. Run benchmarks on this as well if desired...
One of the comments in the php online userguide shows that md4 is the fastest. Then md5 followed by crc32, followed by sha1.
My own tests verify this. Very strange that your test should show otherwise. I tried your snippet as well and got the opposite results. Perhaps it's machine or PHP version dependent.
http://php.net/manual/en/function.hash-algos.php
Well, you can just use the variable name as a hash if you want to go light on the CPU. IF you want to convert a string to an int, just treat it as base 256 and convert it to an int.
Maybe you can try sha which produces a 40 char long string for any input.