I am developing a service that will involve the direct debit of customers' accounts on a routine (weekly, monthly, etc.) basis, and so I'll need to store their information (BSB/routing number and account number) in my database. I am very concerned about security, and so my first thought was to not store this information, but after reading through many other questions about this topic, I have come up with a solution that I think will work - but I would like to run it past you guys to make sure I haven't left open any security holes.
When a user registers to the service, it will create a public/private key pair with the private key having a passphrase that the user provides (their account password). The password is hashed with bcrypt, and the public and private keys are stored alongside the password hash in the user table.
I will also establish a single admin public/private key pair which will be used when we need to process a direct debit. The public key will be known to the application and database, but the private key will be kept off of the server, so that the data can only be downloaded when encrypted, and then processed elsewhere. An alternative to downloading when encrypted would be to instead upload the private key to the application, decrypt the data for that request only, and then delete the uploaded private key - is this a security hole?
When a user registers for direct debit, the service will take the user's public key, and the admin's public key, and encrypt them using GPG's multiple recipients feature.
To the best of my knowledge this covers the following situations:
- If the user wants to view the data, they will need to provide their password to decrypt the information.
- If the user wants to add more data, they won't need to provide their password as I just use their public key.
- If the admin wants to view the data, they will need to download the information and decrypt it, or else upload their private key (see above).
- If the user changes their password, I will just need to update their private key. If they have forgotten their password, the only way I could decrypt their data would be through the admin private key, but as this is kept off-site the data should be deleted.
Will there be any concerns if the admin key pair ever becomes compromised (apart from the obvious) and I needed to generate a new admin key pair and then re-encrypt all of the stored data?
Are there any security holes in this design? I am admittedly no expert but I've tried to do my best with researching this, and would now love to get some input.
I have also looked in to services like Authorize.net's Customer Information Manager (CIM) but as far as I can see you need to be using their service to collect payments, when instead we have already established our own merchant to do this at a cheaper rate, and so we just need a secure information storage service.
The service will be using HTTPS, and running on Ubuntu 12.04, with PHP and MySQL, if that helps.
Any advice you can give will be greatly appreciated!