Security tokens with unreadable private keys? - security

I'd like to uniquely identify users by issuing security tokens to them. In order to guarantee non-repudiation I'd like to ensure that no one has access to the user's private key, not even the person who issues the tokens.
What's the cheapest/most-secure way to implement this?

Use a 3rd party certificate authority: you don't know the private key and you don't have to care about how the client gets and secures the private key (but you can worry about it). Not the cheapest solution ever...
OR:
Share a secret with each client (printed on paper, through email, phone, whatever...).
Have the client generate the keys based on that secret, time (lets say 5 minute intervals) and whatever else you can get (computer hardware id - if you already know it, client IP, etc...). Make sure that you have the user input the secret and never store it in an app/browser.
Invalidate/expire the tokens often and negotiate new ones
This is only somewhat safe (just like any other solution)...if you want to be safe, make sure that the client computer is not compromised.
It depends on where/how you want to use those keys* but the bottom line is that in the case of asymmetric keys, the client will encrypt the data sent to you (the server) using their private key and you (the server) will decrypt that data using the client's public key (opposite of how HTTPS works).
Can you verify, at any point in time, the identity of your clients?
If the client computer is compromised, you can safely assume that the private key is compromised too. What's wrong with SSL/HTTPS. Do you really need to have one certificate per client?
Tokens are not the same thing as keys and they don't have to rely on public/private keys. Transport, however, might require encryption.
*my bank gave me a certificate (which only works in IE) used to access my online banking account. I had to go through several convoluted steps to generate and install that certificate and it only works on one computer - do you think that your clients/users would agree to go through this kind of setup?

It would be relatively easy for compromised computers to steal the user's private key if it were stored as a soft public key (e.g., on the hard drive). (APT (botnet) malware has been known to include functionality to do exactly this.)
But more fundamentally, nothing short of physically incapacitating the user will guarantee non-repudiation. Non-repudiation is something the user chooses to do, opposing evidence notwithstanding, and to prove that a user didn't do something is impossible. Ultimately, non-repudiation involves a legal (or at least a business) question: what level of confidence do you have that the user performed the action he is denying having performed and that his denial is dishonest? Cryptosystems can only provide reasonable confidence of a user's involvement in an action; they cannot provide absolute proof.
PIV cards (and PIV-I cards) use a number of safeguards for signing certificates. First, the private key is stored on the smart card, and there is no trivial way to extract it. The card requires a numeric PIN to use the private signing key, and effectively destroys the key after a certain number of incorrect attempts. The hardware cryptomodule must meet Level-2 standards and be tamper-resistant, and transport of the card requires Level-3 physical security (FIPS 201). The certificate is signed by a trusted CA. The PIN, if entered using a keyboard, must be sent directly to the card to avoid keylogger-type attacks.
These precautions are elaborate, intensive, and still do not guarantee non-repudiation. (What if malware convinces the user to sign a different document than the one he is intending to sign? Or the user is under duress? Or an intelligence agency obtains the card in transit and uses a secret vulnerability to extract the private key before replacing the card?)
Security is not generally a question of cheapest/most secure, but rather of risk assessment, mitigation, and ultimately acceptance. What are your significant risks? If you assess the types of non-repudiation risks you face and implement effective compensating controls, you will be more likely to find a cost-effective solution than if you seek to eliminate risk altogether.

The standard way to handle non-repudiation in a digital signature app is to use a trusted third party, a 3rd party cert authority.
Be careful trying to create your own system--since you're not an expert in the field, you'll most probably end up either losing the non-repudiation ability that you seek or some other flaw.
The reason the standards for digital signatures exist is that this stuff is very hard to get right in a provable way. See "Schneier's Law"
Also, eventually, non-repudiation comes down to someone being sued--you say that "B" did it (signed the agreement, pressed the button, etc), but "B" denies it. You say you can "prove" that B did it. But so what, you'll need to prove in court that B did it, to get the court to grant you relief (to order B to do something such as pay damages.)
But it will be very very expensive to sue someone and to prove their case due to a digital sig system. And if you went to all that trouble and then the digital sig system was some homebrew system, not a standard, then your odds of relief would drop down to about 0%.
Conclusion: if you care enough about the digital sig to sue people, then use a standard for digital sig. If you will ultimately negotiate rather than sue, then look at the different options.
For example, why not use a hardware security token They're now available as apps for people's phones, too.

Related

Can I calculate data integrity check for RSA keys using the key itself?

I'm developing a solution which stores in a DB, for each customer, an RSA key which will be used to sign payments.
Those keys are so called SIM keys created via an SKS HSM, long story short we don't store actually the key in our DB but only an encrypted blob that only the HSM can use. In this way no one, except the HSM, knows what the keys are.
In order to prevent an inside attacker, with access to the DB, to switch keys among users it was decided to calculate, for each key, an integrity check and store it together with the key.
The solution is to perform an HMAC of customerId + key, in this way it would be impossible to switch keys among users without breaking the integrity check.
The key used to calculate the HMAC is dedicated for this use case and is stored in the HSM. However this point is the one I would like to change and for which I'm making this question.
Technically speaking it would be possible to calculate the integrity check using the RSA key itself by encrypting customerID + key using the public part of the key.
However CTOs are blocking this solution because they said the same key should never be used for signing and encrypting.
In my opinion the guideline to have separate keys for signing and encrypting doesn't apply to this case, in fact the guideline is true but only if we would actually expose an API that perform encryption and signing using the same key, which is not the case. The encryption operation we perform is against data generated by the application itself, not an input, is always the same for the entire lifetime of the key and is used only for the integrity check of the key itself.
I'm looking for someone with security knowledge that can help me understanding if the principle "don't use the same key for signing and encryption" really applies to this case, which in my opinion doesn't.
Thanks a lot.
Your CTO is correct on blocking this. Because you didn't give the details on what kind of payment solution you're building, just the fact you're storing, process and/or transmitting cardholder and/or sensitive authentication data puts you in scope for a PCI-DSS or a PA-DSS audit.
But there are very strict rules for key rotation, strength (you didn't mention the SHA to use with HMAC) and storage when handling sensitive cardholder data.
If you aren't familiar with the PCI Security Council, get ready to learn fast. They publish the guidelines that you as a developer must abide by if you are either developing an in-house solution or one for resale. The first overview are the guidelines themselves:
https://www.pcisecuritystandards.org/pci_security/maintaining_payment_security
As stated above, this forum really is no place to begin to discuss the details of all of the required secure coding practices, network segmentation considerations, employee separation of duties, etc. that are included in complianc = and along with mountains of paperwork and possible quarterly scans. And, based on your size and payment volume, an outside auditor.
In a former position I managed the US, Europe and South America's PCI & PA-DSS software compliance programs and it was very costly. Talk to an expert because you do not want to be the next breach of the day. It sounds like your CTO understands the implications so I'd listen to him.

Safely Storing sensitive data client side

Back Story
I work at a small-mid size company and we are reworking our customer facing accounting portal and my manager wants to make single click payment option with the Credit Card info stored in cookies on the end users computer. I'm not in love this the idea.... at all (in fact I'm still trying to change his mind). That being said I am trying to make it as secure as I can, I think I've got a way to minimize the risk, here it is:
using SSL for all exchanges
encrypt the data in a number of cookies that are stored locally
having the cipher as a confirm password that must be entered each time. forcing the cipher to be strong, say 15+ mixed chars, and this is confirmed by checking a hash of it on the server.
I know that the major weak spot is the cookie info that is stored in a two way encryption, that said is this a reasonably safe way to store the info....
The Question
How can it be improved using this basic method.
Please I know that there is going to be a lot DON'T DO IT! answers (if I was not asking, I would be one of them) so please be specific, you are preaching to the choir on this so be constructive in the negatives.
Edit - If you have a specific point that you think I can use in reasoning with my manager please share. (I've already brought up that we maybe legally responsible if the CC info is stolen from a cookie, and he said he would have a lawyer look that over)
Thank you.
using SSL for all exchanges
Should be done no matter what solution you use, as long as credit cards/payment info is involved. As you probably know.
encrypt the data in a number of cookies that are stored locally having
the cipher as a confirm password that must be entered each time.
forcing the cipher to be strong, say 15+ mixed chars, and this is
confirmed by checking a hash of it on the server.
I usually remember my credit card number, and I'd rather put that in (as I'm already intent on not disclosing it to anyone) than a long and complicated key that most customers would write down somewhere anyway.
Even if we aren't allowed to say "don't do it!" - why don't you ask us for good ways to dissuade your manager from taking this decision? ;-)
What makes you unwilling to store this server-side? It's not like Amazon stores my credit card info in a cookie. The basic idea is to store all user info on the server, and access it when a user has authenticated successfully (i.e. logged in).
Cookies are in this case used to persist the logged in-state between browser sessions. The info this logged in-session has access to is stored on the server. With credit card info this usually entails a lot more security than other sensitive info, but it's the same basic idea.
Storing actual credit card numbers in cookies (encrypted or not) could be a potential PR nightmare when some tech-savvy customer realises what you are doing.
Thread for more reading: What information is OK to store in cookies?
Edit: The more I read through this question the more dumbfounded I get. Does your manager even know what a cookie is? How it works? What the point of it is? Saying that you want to store credit card info in cookies is like saying you want to use shoes as a means to transport shoe-laces. He is actively and purposefully shooting himself in the foot for no reason whatsoever. What he wants to achieve can be achieve a lot easier with other, much safer techniques - without any loss in functionality whatsoever.
From an article linked by Scott Hanselman:
Storing Credit Cards
If you absolutely must store credit card data it should be stored in encrypted form.
There are various compliance standards (specifically CSIP and PCI) that vendors are supposed to follow that describe specific rules of how networks need to be secured and data stored. These rules are fairly complex and require very expensive certification. However, these standards are so strict and expensive to get verified for that it's nearly impossible for smaller businesses to comply. While smaller vendors are not likely to be pushed to comply, not complying essentially releases the credit card company of any liability should there be fraud or a security breach. In other words you are fully responsible for the full extent of the damage (realistically you are anyway – I'm only echoing back the rough concepts of these certifications).
(my emphasis)
Point out that Cookies are transmitted across each request. If you store credit card information in them not only is it less safe, but you are not actually gaining any sort of realistic time benefit. Outside of being easier to implement, there is no reason to do it this way. Since you're the one implementing it he shouldn't care about the ease of implementation anyway...
Edit: You could also point out that if anything goes wrong, he will be the one getting fired for it. Threatening his job is a great way to get him to see it your way.
Don't use the user's password as the key, or at least, it shouldn't be the only thing that comprises the key. You should encrypt the credit card account information with a private key that is stored on the server (and not known to the user).
You can decrypt the credit card information on the server, even though it's stored on the client. This way, there is no way for the encrypted credit card information to be reversed on the client (without knowing the private key).
You might encrypt the credit card account information with both the private key and the user's entered password, that way, they can't be sent to the server to be decrypted without the proper password.

Ciphertext on server

Are there any protocols which would allow 2 visitors to communicate securely through my website, without the possibility of me reading their messages?
Ask Google for End-to-End encryption like PGP/GPG. For a client-side browser-based implementation you might want to check out GPG encryption in JavaScript.
I just googled it and cannot tell if its really secure (not sending your private key to anyone). I just want to give you a point to start with.
EDIT: Looks like it does send the clients private key to your server to perform a server-based encryption. This is not what you want. But I am sure that a JavaScript implementation of GPG is possible even though I don't know if somebody has done it yet.
Yes; for example, this is what would happen if your server was a link in a communication protected by SSL/TLS.
The participants use a public-key encryption scheme to agree upon a secret, symmetric key; that is then used to encrypt their communication.
It's also possible for the participants to simply encrypt their messages with the public key of the intended receiver. That way, only the intended receiver can decrypt the message. This is not a very advanced scheme and probably vulnerable. (Among others, if an eavesdropper can guess exactly what is sent, he can encrypt that message with the intended recipient's public key and see if the result matches with what is being sent).
There is a lot of literature available on cryptographic protocols; for starters, here's a Wikipedia article on Key Agreement Protocols.
If we're talking about not possible then the second part to S.L. Barth's answer will achieve this with the exception that the key exchange must be done by some other means. This can be the phone or email or even another website but if it's done via your website then it's open to a man-in-the-middle attack. You can tell your users to do this, you just can't actually help them do it.
There is probably a javascript library somewhere that will implement GPG encryption so that all you have to do is make sure that every message is encrypted in the browser before it's sent to your web server. You can store the messages as long as you like, they're encrypted. Only the user with the correct private key will be able to decrypt it.
SSL and TLS as they are used by websites everywhere are vulnerable to man-in-the-middle attacks. The reason we don't hear much about these sorts of attacks is that most of the people in the middle are trustworthy so the attacks simply don't happen. The recent revoking of the CA certificates of DigiNotar and others was precisely because the Iranian Government were caught acting as a man-in-the-middle and decrypting their own citizen's SSL traffic.
If you're happy with preventing casual snooping by curious sysadmins, the key exchange can be done through your website as well.
One more thing: Security is hard.
Even if you do this with well-known encryption techniques, the chances of there being a flaw in the implementation will be very close to 1. This doesn't mean that those curious sysadmins will be able to accidentally read messages but it does mean that a determined and skilled adversary will be able to find a way in. As soon as you can afford it you should hire an expert to redesign or at the very least examine your protocol and implementation.
In general, such a secure link between your users without you being able to read and/or modify their messages is only possible if they have some way of identifying each other (or at least in one direction).
This might be a shared secret (like a passphrase) or a public key known to one (or certified by a CA known to one), where the other one has the corresponding private key.
On this one can build a secure protocol (using a key exchange and then symmetric encryption with MACs in both directions), like TLS does. (Another way, used often for instant messaging, is OTR, the Off-the-Record messaging protocol.)
Without a way to identify the other end point, you end up with a way of allowing man-in-the-middle attacks. SSL/TLS without certificates, or with certificates where the man-in-the-middle knows the corresponding private key, is insecure, as is every other similar encryption scheme.
Another issue is that you said visitors of my website. This looks like you would implement client-side cryptography in JavaScript, delivered from your website. Don't do this ... if the visitors do not trust you not to read their data, they also should not trust you to feed them non-malicious JavaScript, which might implement something else than you are claiming it does, again allowing a MITM, or even directly sending a copy of the data to you.
More details about this are discussed in Javascript Cryptography Considered Harmful (from a slightly different perspective).

Threat Posed by Man-in-the-Middle Attacks

How frequent (and/or sophisticated) are man-in-the-middle attacks?
About
In cryptography, the man-in-the-middle attack (often abbreviated MITM), or bucket-brigade attack, or sometimes Janus attack, is a form of active eavesdropping in which the attacker makes independent connections with the victims and relays messages between them, making them believe that they are talking directly to each other over a private connection, when in fact the entire conversation is controlled by the attacker. The attacker must be able to intercept all messages going between the two victims and inject new ones, which is straightforward in many circumstances (for example, an attacker within reception range of an unencrypted Wi-Fi wireless access point, can insert himself as a man-in-the-middle).
http://en.wikipedia.org/wiki/Man-in-the-middle_attack
The reason I ask is to try and gauge whether it's worth the added overhead of encrypting important sections of the content I'm sending to the user or whether it's safe to just go ahead and send it unencrypted.
Note: I know this isn't strictly a "programming" question insofar as there is no code solution, however it influences coding decisions and is coding-based, so it still seems appropriate.
It doesn't take a MITM attack to read data that hasn't been encrypted at all. A MITM attack is used to allow an attacker to read data that has been encrypted.
Edit: The relevant question with respect to MITM attacks is not whether you should do encryption at all. It's whether you should do some sort of authentication (i.e., verifying the identity of the remote party) while you set up an encrypted connection.
With no encryption at all, a "snooper" just looks at your data as it goes through, and sees exactly what's there. A MITM attack applies when you do encryption, but don't verify who you're sending the encrypted data to. In this case, the attacker inserts himself in the middle of the conversation -- you connect to the attacker, and send him encrypted data. He connects to the person you intended to talk to, and creates an encrypted connection to both of you. Then, as you send your data, he receives it, decrypts it with your key, re-encrypts it with the target's key, and sends it to the target. Likewise, any returned data he decrypts with the target's key, and re-encrypts with yours.
This way, it looks to both you and the target as if the communication is going normally -- but the attacker can read everything you send. If you don't encrypt the data at all, though, none of this is necessary -- since you're sending plain text, the attacker can just look at it as it goes by.
The MITM attack is not necessarily thwarted by encryption. For example, if you encrypt using a so-called "self-signed certificate," then your communications will be encrypted, and yet a MITM attack could still occur. For example, with a self-signed cert, if you load "Fiddler" onto the client box, it will perform a MITM exercise so that it can watch all the traffic. The client and the server will not realize that the MITM is happening.
If you use real PKI (a true trusted 3rd party is involved), then MITM isn't possible.
In any case, MITM is fairly easy to achieve, if the value of your data is "worth it" to the attacker.
Depends on the application, but if the data being sent is at all sensitive, definitely guard against man in the middle! It is a very relevant danger especially with rise of Wi-Fi, and very easy to do; a friend and I were able to replicate the Gmail MIMA last year with little difficulty.
I would refer you to the Internet Storm Center (isc.sans.org) for any questions about frequency of attack types on the Internet.
Keep in mind that MITM is a very broad term, and you seem to be more worried specifically with just session sniffing (i.e., eavesdropping) attacks. Sniffing attacks are trivial to perform. A full MITM facilitates modification of the session, which can have different implications than simply viewing the information. This modification requires a bit more sophistication, but not custom tools.
Using TLS/SSL on your site will provide protection of the data from prying eyes and ensure that clients are indeed communicating with the correct server.
To address the note on coding - whether you decide to use cryptography or not, you should be engineering your web app such that it would not be onerous to add crypto later.
Any time you talk about security, it's always in context of sensitivity of your data. The more valuable your secret is to someone, the more determined they will be to obtain it, and the more resources they'll expand. Conversely, the more valuable it is to you to keep it secret, the more resources you should expand protecting it.
Man in the middle attacks are pretty accessible to anyone, especially on public networks. It's up to you to decide if you want anyone to be able to read your data or not...

Somebody is storing credit card data - how are they doing it?

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 the following:
My credit card info is being stored on a server some where in the world. This data is (hopefully) not being stored on a merchant's server, but at some point it needs to be stored to verify and charge the account identified by merchant submitted data.
My question is this: if you were tasked with storing credit card data what encryption strategy would you use to secure the data on-disk? From what I can tell submitted credit card info is being checked more or less in real time. I doubt that any encryption key used to secure the data is being entered manually, so decryption is being done on the fly, which implies that the keys themselves are being stored on-disk. How would you secure your data and your keys in an automated system like this?
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.
For vendors to process and store your credit card info, they generally have to get PCI certified. The requirements should be outlined here. Some of the requirements are very straightforward, and others are vague and open to interpretation. Going through the process is not fun, and a company having the certification doesn't mean your data is safe.
But it's better than nothing I suppose.
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.
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.
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.
In some situations, encryption keys are stored not on disk but on some hardware device. Either a special encryption server is used to do the encrypt/decrypt or the decrypt is done using a key stored on, say, a hardware dongle. This way, a hacker cannot steal the decrypt keys without stealing the physical device containing them (since the key never leaves the device).
Another method I have seen is to store encrypted data in a database/datacenter that has no direct connection to the outside world (you can't hack what you can't access). An interface server sits between the "secure" part of the network and the "Internet-facing"/"insecure" part of the network as a proxy. Forcing secure traffic to funnel through this security choke point can make it more difficult for an intruder to access the secured data.
Neither of these mean your data is perfectly secure, of course.
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 ...
First of all if you deal with credit card numbers, you will need to become PCI-DSS compliant, and once you store numbers all 12 sections of the PCI-DSS spec will apply to you. Thats a major cost to most organisations, and if you don't have the time, resources and financial means, you should not go down the path of storing credit card numbers.
We have gained PCI-DSS compliance on a Windows based e-commerce system that stores credit cards. It uses a 256 bit AES encryption. The key itself is encrypted using Windows DPAPI meaning it can only be decrypted by a process running under the same user account as the one that encrypted it. The encrypted key is stored in the registry.
The key is rotated every 12 months, and a backup key copy is stored broken into 3 parts A,B,C and spread over 3 USB drives, each held by a different person. Drive 1 has A+B, Drive 2 has B+C, Drive 3 has A+C. So any 2 drives are required to construct a full key (A+B+C). This scheme is tolerant to the loss of any 1 of the drives. Key parts themselves are encrypted with a password known only to the drive owner.
To answer your specific question, it is possible to store the credit card encryption key encrypted on disk. The key encrypting key can derived from a passphrase that must be entered when the server is started. Shamir's secret splitting scheme can be used so that k out of N shares are required to construct the secret that will be used as key encrypting key. The decrypted encryption key/secret is then stored in memory. If the server has to be restarted, then you need k shares. This is of course a big overhead and most merchants I know do not implement this. They do however usually store the key separately from the encrypted data for some intermediate security, so access to one does not automatically mean access to the other in entirety (still very bad though).
I deleted contents of my original post since that did not directly answer the question. Suffice it to say that key management and correct encryption are an important piece but still a small part of the story.
PCI auditors cannot possibly ensure that everything is done correctly.
If you want to eliminate any credit card stealing headaches, hash them using salt values not stored in the database (in addition to salt values stored in the database). Hashing them with any modern hashing algorithm will pretty much put to rest most issues with credit card theft but it does mean consumers must re-enter their credit card on each purchase. Having worked on a project that dealt with storage of credit card numbers, I found that hashing them cut security review costs by an order of magnitude (granted that project was before PII concerns).
If you are going to use symmetrical encryption, then you enter a new realm of complication that all comes down to management and control over the decryption keys. I will say that even if you hash the credit card numbers you will still need to deal with reversible encryption since all PII(Personally Identifiable Information) must be encrypted. SQL Server 2008 has a new Extensible Key Mangement plugin architecture which lets use third-party vendor programs to manage control over the decryption keys including split keys.
For more info:
Deploying SQL Server 2008 Based on Payment Card Industry Data Security Standards (PCI DSS) Version 1.2.
any automated system for decrypting encrypted information is going to be completly insecure. By automating the process you are defeating the encryption. Any encrypted data should only be decrypted by a user entered secret key.

Resources