<snip - palm-face image a bit large...>
Let me give you a better reply
(Though I'm just going to be repeating myself a bit and I'm not sure you're actually after one...)
You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!
Yes, we know that an md5 hash is exactly 32 characters long and made up of hexadecimal digits only (case in-sensitive), i.e. it's 128-bits long. Knowing this does not help us at all though in doing a reverse iterative lookup with lookup/rainbow tables to get to the first hash, as I've already pointed out. There are 2^128 (3.40282366920938463463374607431768211456 × 10^38) possible permutations (unique md5 hashes). In order to *guarantee* being able to do such an iterative reverse lookup, for absolutely any password string imaginable, you would need every single one of these hashes in a lookup table and beside each the corresponding output hash of hashing them. Never mind the time required to compile it and later search it, without any overhead (or compression), you would need 128bits * 2 * (2^128) = 8.7112285931760246646623899502532662132736 × 10^40 bits = 9.903520314283042199192993792 × 10^27 TERABYTES of storage. You can reduce this requirement significantly if you instead have a much smaller set of passwords that you're wanting to be able to crack, in which case you only need all of the intermediate and final hashes of chain-hashing those for as many iterations as the algorithm used. But then this trade off makes it much less certain that you're going to be successful.
What I meant by "defeating" rainbow tables, was that you'd have to re-generate the table for each user (and only that user), so you're spending a lot of time pre-generating a single use dataset, when you could just compare the hashes as you're generating them against the hash you have instead (So if you hit a match, you don't waste time by generating the rest of the table)
Although with my earlier comment about GPU based hash computation, maybe that isn't such a big deal.
Sure, it may very well be more efficient to compare as you go along in such a case, therefore turning it into a brute-force type attack. So now I'm just being pedantic about lookup/rainbow tables being "defeated" when they're still perfectly viable, just not necessarily the best option.
Question though, what makes a random per user salt stronger than salting with the username? Is it just that the username would contain "less randomness" compared to a random salt? You're storing them both in the database so I don't see that as the weakness.
I don't think there is any significant difference. They accomplish the same goal of having a unique salt per user account.
does length or entropy matter for a salt given that it's known anyway?
One of the desirable traits of hash algorithms is that small changes to the input will result in seemingly unpredictable changes to the output. The two hashes for "abc" and "abc1" will look just as different from each other as the hashes for "abc" and "abc2". So the 'randomness', length, or any other quality of the salt shouldn't make a difference, so long as the same salt isn't repeatedly used. Obviously, though, in other cryptographic scenarios, entropy and length of keys does play a big part in security.
If usernames were acceptable salts here then surely the output of any random number generator would also suffice. So why then is it that articles such as this one
recommend that a CSPRNG must be used? (Admittedly I don't believe that article to have been written by an "expert" cryptographer, and it itself doesn't give an explanation). The only logical explanation that comes to my mind is that the use of a decently unpredictable method of salt generation makes it much more difficult for an attacker, *PRIOR* to breaching your system and obtaining the actual salts, to create pre-computed lookup/rainbow tables incorporating salts actually in use in your system. An attacker is at an advantage if he can generate such tables in advance of breaching your security.