A "secure" hash is a hash that is believed to be difficult to "spoof" in a formulaic, reproducible way without prior knowledge of the message used to create the hash. As that information is generally secret, hence the need for a hash, this is a good property of a hashing function intended for use in authentication.
A hash is generally considered "secure" if, given a message M, a hash function hash(), and a hash value H produced by hash(M) with a length in bits L, none of the following can be performed in less than O(2L) time:
- Given hash() and H, produce M. (preimage resistance)
- Given hash() and M, produce a different M2 such that hash(M2) == H. (weak collision resistance)
- Given hash(), produce any M1 and M2 such that hash(M1) == hash(M2). (strong collision resistance)
Additionally, a "secure" hash must have a hash length L such that 2L is not a feasible number of steps for a computer to perform given current hardware. A 32-bit integer hash can only have 2.1 billion values; while a preimage attack (finding a message that produces a specific hash H) would take a while, it's not infeasible for many computers, especially those in the hands of government agencies chartered with code-breaking. In addition, an algorithm that creates and stores random messages and their hashes would, according to probability, have a 50% shot at finding a duplicate hash with each new message after trying only 77,000 messages, and would have a 75% chance to hit a duplicate after only 110,000. Even 64-bit hashes still have a 50% chance to collide after trying only about 5 billion values. Such is the power of the birthday attack on small hashes. By contrast, a computer looking for collisions in a 256-bit hash (SHA-256) wouldn't even have a one-in-a-billion chance for the next message it tried to collide until it had tried 15 decillion numbers (1.5*1034).
Most demonstrated attacks on cryptographic hashes have been collision attacks, and have demonstrated the ability to generate colliding messages in less than 2L time (most have still been exponential-time, but reducing the exponent by half is a significant reduction in complexity as it makes a 256-bit hash as easy to solve as a 128-bit, a 128-bit as easy to solve as a 64-bit, etc).
In addition to small hash size, other factors that can make a hash demonstrably insecure are:
Low work - a hash designed for use by a hashtable or for other "checksum"-type purposes are usually designed to be computationally inexpensive. That makes a brute-force attack that much easier.
"Sticky State" - The hashing function is prone to patterns of input where the current hashed value of all inputs so far does not change when given a particular additional byte of input. Having "sticky state" makes collisions easy to find, because once you identify a message that produces a "sticky state" hash it is trivial to generate other messages that have the same hash by appending input bytes that keep the hash in its "sticky state".
Diffusion - Each input byte of the message should be distributed among the bytes of the hash value in an equally-complex way. Certain hash functions create predictable changes to certain bits in the hash. This again makes collision creation trivial; given a message that produces a hash, collisions can be easily created by introducing new values to the message that only affect the bits that change predictably.