As many commenters have pointed out, there are theoretical problems with what you're asking for (if you can decrypt the data, then your attacker can too). But, there are some practical things you can do to make the attacker's life harder:
- Don't write your own cryptographic code or design your own crypto systems; use existing libraries as much as possible.
- Separate your reads from your writes. Using a public/private key pair, you can give one set of systems the ability to write encrypted data but not read it, and a different set of systems the ability to read the data. The systems that can decrypt / read data should be isolated as much as possible - don't expose them to public networks, limit which operators have access to them, etc. The separation also forces you to encapsulate your secure data and define an API over it; rather than arbitrary reads, hosts that don't have the decryption keys will have to ask the hosts that do to perform specific operations. If you're writing a Rails app, the Strongbox gem [1] enforces this pattern for you.
- Rotate your encryption keys.
- Don't store keys in code. Follow the Heroku pattern [2] of storing any sensitive data (i.e. private keys) in the environment, where it is bound at runtime to your code and encrypted data.
- Store as little sensitive data as possible. Make sure data you don't need any more is periodically purged.
- Human processes are just as important as code; keep track of who has access to sensitive data, make that access opt-in, and remove it when those people change jobs or are terminated. Do everything in your power to keep those operators from being phished (user education, two-factor auth, etc).
- Don't store credit cards if at all possible. Find a payment processor [3] to do it for you. It's not worth the headache, it makes you a more attractive target, and it may come with additional legal overhead (depending on your jurisdiction).
- Don't write your own cryptographic code or design your own crypto systems; use existing libraries as much as possible.
- Separate your reads from your writes. Using a public/private key pair, you can give one set of systems the ability to write encrypted data but not read it, and a different set of systems the ability to read the data. The systems that can decrypt / read data should be isolated as much as possible - don't expose them to public networks, limit which operators have access to them, etc. The separation also forces you to encapsulate your secure data and define an API over it; rather than arbitrary reads, hosts that don't have the decryption keys will have to ask the hosts that do to perform specific operations. If you're writing a Rails app, the Strongbox gem [1] enforces this pattern for you.
- Rotate your encryption keys.
- Don't store keys in code. Follow the Heroku pattern [2] of storing any sensitive data (i.e. private keys) in the environment, where it is bound at runtime to your code and encrypted data.
- Store as little sensitive data as possible. Make sure data you don't need any more is periodically purged.
- Human processes are just as important as code; keep track of who has access to sensitive data, make that access opt-in, and remove it when those people change jobs or are terminated. Do everything in your power to keep those operators from being phished (user education, two-factor auth, etc).
- Don't store credit cards if at all possible. Find a payment processor [3] to do it for you. It's not worth the headache, it makes you a more attractive target, and it may come with additional legal overhead (depending on your jurisdiction).
[1] https://github.com/spikex/strongbox
[2] http://12factor.net/config
[3] https://stripe.com/