On a credit card, you will typically find:
- the number, typically 16 digits;
- the expiration date (month and year, usually within the next two years);
- the card holder name;
- the security code (3 or 4 digits).
The trouble with publishing hashes of such information is vulnerability to exhaustive search: the attacker tries all possible combinations, until one matches the hash value. There are two ways to defeat such attacks: by keeping a large number of combinations, and by making the hashing process itself slow.
Slowing the hash requires using a salt (to prevent parallel attacks and precomputations), and making many nested iterations (as much as possible, provided that the overhead is tolerable for your system). There is an art to that; a careless handmade construction may be quite weaker. This part is very similar to what is done for passwords, so let's cut it down to the usual recommendation: use bcrypt. A good GPU can evaluate a 32-bit hash function like SHA-1 about one billion times per second; but by configuring the "cost factor" of bcrypt you can bring such a figure down to, say, 100 times per second, without overloading your own system too much.
Now let's see about the number of combinations. The card holder name can often be guessed, because in a merchant site database you will also record the user name and possibly a delivery address. The expiration date is within the next two years (or so), hence 24 possibilities. The card number usually begins with a 4-digit identifier for the bank, and ends with a checksum digit which is deterministically computed from the 15 others. Assuming the attacker will try, say, about ten distinct banks, you end up with about 1011 (aka "a hundred billions") possible card numbers. However, if the "truncated card number" contains, say, 8 digits (the first and last four digits), that number is reduced to 108 (one hundred millions).
If you use bcrypt and attack can go only at a rate of 100 tries per second, then the attacker will need an average of half a million seconds to find the card number (that's about 6 days). This may be viewed as "sufficient" because the resale value of a stolen credit card number is not high (I think it is around 10$ at most). For increased resilience, do not hash the lone number, add the expiration date (x24 on attack cost) and the security code (x1000).
So, to sum up:
- use bcrypt with a high iteration count (and don't fumble on the salt);
- put the expiration date and the security code in the hash input;
and you can resist the weakening induced by the storage of truncated card data.