Storing credit card information securely and legally is very difficult and should not be attempted. I have no intention of storing credit card data but I\'m dying to figure out
If I was storing the number, I would be a giant service provider with a massive database. That database is spread across a highly-redundant storage array consisting of multiple cabinets, in separate rooms or ideally in separate geographical locations, connected by a SAN. My biggest insider threat is the distributed physical plant, the constant stream of worn-out drives, and several daily shifts of technicians, administrators, and engineers. It's a huge threat.
Therefore I would encrypt the data on a physically-isolated computer that connects to the mass storage over a network. The software would be as simple as possible: encryption and number verification. The public interfaces and business logic goes elsewhere. Accesses would be logged to a separate SAN.
Encrypt with something like AES. The raw AES key is only ever stored in RAM. The key is wrapped in a PGP file for each administrator, who has their own passphrase to enable the server. Less-trusted personnel can be given partial passphrases to use in disaster recovery, or passphrases can be stored in a vault somewhere. For encryption, pick a unique initialization vector (IV) for each card number, AES-encrypt the number using that IV, and store the IV and encrypted number to the SAN. Decryption only occurs using a privileged client interface; normal client connections used for purchases can never get a decryption.
It's quite easy to store a salted hash of a credit card number rather than the number itself for secure lookups. For 99% of the scenarios out there, this would be sufficient credit card for storage -- fast and very secure.
If you really need reversible encryption of a credit card for some scenario (continued billing, for example), I would go with a symmetric key stored in a secure location other than the database. It's been a while since I looked at PCI specs, but I'm fairly certain that's PCI compliant.
If you need fast lookups along with reversible encryption, use both options: a hash and an encryption.
Edit: There seems to be some controversy over my answer. I would like to point out the following very interesting essay from Integrity.com (PDF):
Hashing Credit Card Numbers: Unsafe Application Practices
It details many of the issues involved in storing a hash of credit card data, but its conclusion confirms my suggestion.
Yes, a raw hash of the card is not secure; that's why we salt our hashes! But a static salt is also not secure, they allow the creation of rainbow tables for known static salts. So it's best to make our salts vary in some way that is unpredictable. In the case of passwords, it's sufficient to use a separate, random hash for each password being checked; it can even reside in the same table/row as the hashed password. For the case of credit cards, this should be the same -- a random salt for each instance of the credit card being hashed. If the credit card number is stored per transaction, a separate salt for each transaction.
There are pros and cons to this approach, but it's sufficiently secure. The pros are the lack of key management; the salt and hash are right there, and don't need to change while still allowing for audit checks of the hash; e.g. does that credit card hash match this known credit card number?
The cons are in search; it's not possible to effectively search for a particular credit card number across many transactions.
Of course, you'll have this issue with external encryption anyway; unless the database is itself encrypted (something only some databases support), you won't be able to search very well. Even then, encrypting at the database or even the table level reduces search effectiveness significantly.
As an merchant you can choose to store the CC data in your own database or outsource it to third party providers.
Third party providers like IPPayments or major banks like Westpac in Australia are level 1 PCI compliant. For web applications you can choose to use a payment acceptance web page (presented somewhere in your customer's workflow) from them branded for your company. For windows apps (e.g. you company's CRM app) and recurrent payments they generally have a gateway usable using their API that provide a tokenisation service, that is they accept a CC number, registers it and return an unique token that just looks like a CC number. The token can be safely be stored in your DB and used for any further transactions, batch payments, reconciliation etc with the bank. Of course they big issue is operational cost per transaction. For a utility that takes monthly credit card payment from a million customer the transaction cost can be substantial.
If you choose to store the CC number in your own DB triple DES encryption is sufficient. A better option is to you transparent encryption in DB as offered by Oracle advanced security or SQLServer where even the DBA cannot decrypt the CC number. Then there are onerous responsibility for key management, backup, physical security, network security, SSL transmission, changing default settings of all server equipments and firewall, anti virus, auditing, security cameras and on and on ...
Your assumption that the merchant must store the card somehow is incorrect. Most likely, the merchant is storing a token that it received from the payment processing gateway the first time you used the card. The token uniquely identifies the combination of merchant and card. Subsequently, you can make purchases from that merchant without supplying your card number again. If the merchant's database is compromised, the tokens are of little value to the attacker. They're only valid for that merchant, and they can all be canceled at once when the breach is detected.
The last few times I worked with creditcard payments, you never really stored the actual CC info on your own servers. You let the Payment gateway handle that. What you ended up with was a transactionID that you could use to verify that the creditcard was still both valid and had the requested amount of cash available. Then once you actually packed the stuff they bought, you'd issue a capture-command to the Payment Gateway.
This approach greatly simplified the process of integrating CC payments on a site, since all you ever needed to know was the transactionID for a particular customer. This ofcourse didn't allow you do to the amazon-"trick" of keeping your CC info for 1-click shopping. If the transactionID got compromised, all it could be used for was collecting payment early, or cancelling the transaction altogether (in which case you'd find out about it when you verified that the authorization was still valid before shipping). The transaction couldn't be used to collect a bigger sum than what the customer had approved already, nor would it allow someone to collect to a different account than what the "shop" was configured for.
Maybe not the exact answer you were looking for, but perhaps it could solve your overall issue without having to spend a fortune on security vendors.