TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
Forums are in read-only mode while we transition to new software.
Security Question: Encryption
  • Hi Folks, I have a question regarding security and encryption.

    I have to store customer bank account details in my database for payment reasons.

    I want to do this in an encrypted way via Encrypt, which is no problem, decrypting works fine as well.

    The data in the database seems quite safe this way, but what about the server being hacked? It's not a big deal to find out the encrypting key in the config, and with that decrypting the data again.

    Is there any way to encrypt the data with a key, which does not allow decrypting it again? So that I need another key (which is not stored on the server) to decrypt the data?

    Or how do you deal with sensible data? E.g. credit card details?

    Thanks for your help and ideas

    Thorsten

  • Don't use a 2 way encryption, use hashing with an individual salt. Check the bonafide module for a way to do this.

  • For credit cards (if you want the information back), you have to store it using 2-way encryption. The best way to do this is to use your payment or gateway account to keep the bank information for you -- all you get is a token back for what you need it to do (recurring billing, fulfillment billing). That way, the gateway/merchant is responsible for the PCI/DSS compliance

  • Don't use a 2 way encryption, use one way encryption with an individual salt.

    There's no such thing as one way encryption. That's called hashing.

  • If you are right you are right, sorry for my bad jargon.

  • @chrisgo Unfortunately I do not have any payment provider and have to store the bank details in my own database.

  • A better (relatively speaking by maybe about 5%) way would be to keep the key in the code on the web server and then do not store that key anywhere on the database server. When you start scaling, that would be the first split of server work: Server 1 = web+app and then Server 2 = database. So you may have to do that sooner rather than later. If one of your servers get hacked, they will have either the key or the encrypted data ... if they hack into both your servers ... you may have other problems :(

  • This scenario is what public key encryption was designed for. Store a permanently obscured (eg ****1234) version in plaintext if you need to display it back to the customer. Then, encrypt the real number with the public key and store the result.

    You then have options with the private key. Most secure, build your payment server on a separate machine behind your firewall and have it communicate with the database over SSL. Keep the private key securely on the backoffice machine and do the decryption there.

    Less secure, have the user upload/paste the private key on every request when they need to decrypt the details (if uploading, make sure you clean up the temp files).

    Or, keep the private key on the server but have the user re-enter their password to view the data and use their password as the paraphrase for the key. You could go double secure and also use their password to su to a different user with read permission on the key.

    There are also other options including using certificate based auth for the user's http connection and using their certificate to authorise access (by passphrase, or by a cli app running as a different user with read permission on the key) and open the private key.

    The main thing is coming up with a sensible way for your application to prevent an attacker from accessing the private key at all, or making it useless if they have it. That will require at least some piece of information that isn't stored on the server for highest security, or that isn't readable by Apache for an absolute minimum.

  • Thanks for that, andrewc.

    Is there any ready-to-use public/private key encryption module available for kohana?

  • @andrewc, excellent suggestion btw. I was ready to shout Private/Public Key Pair until I saw you had already done so :)

  • @Thorsten I don't know about "ready to use module for kohana" but you could check this as a starting point.

  • Thanks, I'll have a look at it :-)

  • @samsoir, thanks! @devi - didn't look in detail, but that looks complex. @Thorsten, not a ready made module, but I built a (slightly hacky) implementation as a model template (think behaviour/mixin) for my semi-stable KODoctrine module. Check out https://github.com/acoulton/kodoctrine/blob/master/classes/kodoctrine/template/listener/encryptable.php#L127 and https://github.com/acoulton/kodoctrine/blob/master/classes/kodoctrine/template/encryptable.php#L105 for a couple of rough examples.

    Private key management is out of scope for that code, but should get you started on implementing the crypt/decrypt.

  • Thanks for all your help.

    I have written a small module, based on Kohanas default encryption class, that allows you to select OpenSSL as a driver and use public / private keys for encryption.

    Unfortunately I do not have the time to include other OpenSSL encryption methods at the moment.

    You can get it from Github and give it a try:

    https://github.com/ThorstenS/Kohana-Encrypt

  • Hey @Thorsten, good start. Obviously the module as-is doesn't indicate the use case, so you may have covered this in another way (eg isolated servers), but it might be worth highlighting in the readme that if you put both the public and private key in that config file then using keypairs is pointless and you'd be as well to use mcrypt etc for performance.

    I'd also probably try to avoid having the private key load as a class property in the constructor even on an isolated server. Better to load it (preferably in method scope only) only specifically when required. You could either do that by loading on each call to decrypt, or if working in a batch by loading it in the batch script and passing it as a param to decrypt...

  • Thanks for your comment, @andrewc.

    You are right, having both keys on the server does not make a change, of course.

    What I was planning is to do is to encrypt the data using the public key, which is stored on the server, and decrypt it only on my local machine when creating the debit batch file for my local bank.

    I think this should be quite safe then :-)

  • Yep, that should be good. If there's any access to your local machine you might still want to consider implementing a paraphrase on the private key and requiring that you input it when you want to build the batch. Depends what else is on your machine and who has access to it...

  • Would you use public/private keys to protect a password field if you require a non-hashed version?

  • @DrPheltRight: It depends, I'd say.

    First of all, you should ask yourself if it is absolutely inevitable to not simply hash the password.

    The problem with public/private key encryption is, like mentioned above, that you can restore the password if both keys are stored on your server.

    If your server gets hacked all users passwords would be readable by the attacker, and with people usually using the same passwords and email-addresses for logins all over the web, your users might not be too happy about having to change every password everywhere ;-)

    Personally, I'd suggest hashing the password, for me there is no real need to be able to recover the plain-text password. And implement a "send me a new password via email" link for users that forgot their passwords.

  • I don't disagree when it comes to login passwords, in fact, I completely understand the reasoning and benefits of hashing passwords in an irreversible way. However for situations where your customers are going to be generating a lot of services each with their own passwords (created using a random string generator) then a password list is definitely useful for a user. The initial login password required to see this information would be hashed.

  • That the initial login password is hashed does not provide you any protection in the case of an attack on your server.

    What you could do is to have an input/upload field on login where the user has to enter his private key (not very comfortable to be honest).

    Alternatively, you could create a password-protected pair of keys for each user, with the users hashed password required to access his private key.

  • So are these more API type keys rather than login passwords? I guess yes, you could have two flows, one for authenticating the key where you encrypt with the public key and validate that the ciphertext matches the stored value (like a hash) and one where the user password is used as the private key paraphrase as thorsten suggests - bear in mind that you'll have to change the key passphrase any time the user changes their password.

    You wouldn't want to use the password hash as the passphrase as that is stored on the server. You need to use their cleartext or a differently salted hash so its only available in that request).

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion