tags:

views:

72

answers:

3

I'm working on my first secure shopping site. We're not storing credit card data, so that's not a problem. However, we do have a transaction key and API login key for our payment gateway (authorize.net) that I'd prefer to keep in a database, rather than hard-coding into my php. I don't know that we need tremendous security, but I would rather not store it in plain text. I know about sha, but that's one-way. I need a way to store the value in the database in a semi-secure format, but then be able to "decrypt" it programmatically for use in my function.

An additional caveat to this is that my site is hosted, which means there's a very tight limit to what kind of stuff I can install, so ideally any solution would rely on something that's included with a standard php install.

Can anyone point me in the right direction? I'm very new to securing data.

EDITED TO ADD: I checked with my host and mcrypt is installed. Is this the right direction to look in?

A: 

From a security perspective, there's no difference by storing it in the php files or in the database, if someone has access to your php files he has access to the database as well.

working with mcrypt doesn't mean you will have MORE security, (if they can read your php files they can read the key as well) so...

If I were you i'd store the API key in plain text on a file outside the web server directory.

just write good code you should be fine.

sathia
We're not storing it in the database to make it secure; we're doing it so we can write a front-end to allow a non-coder to change the value if necessary. That said, we'd prefer it to not be stored in plain-text. And again - this site is cloud-hosted; we don't have access to directories outside the web server space we're given.
EmmyS
Actually, you should ALWAYS assume that different components of a remote server are individual security risks. It's possible through SQL injections or simple malformed queries to return rows of a database without compromising the PHP code. This is why you always hash passwords- just in case someone got your database. Salts were invented to prevent rainbow table attacks, and just like an mcrypt key- if someone got the salt they could circumvent that and still use a rainbow table.
steven_desu
I don't get why people is downvoting what I've said, if you believe that you'll be MORE secure by hashing it do it, it won't change a thing. To deal with this kind of security you should have a very different infrastructure, you are storing an API KEY, you'll have the same "security" with an hash as with a plain txt code. where are you storing your db connection files :p ? You should check very well what that API KEY is allowed to do instead. I mean, that API KEY must be able to do only certain things from a defined IP etc...
sathia
@sathia Suppose you store the API key in the database and someone uses the following theoretical SQL injection: `'-- GET * FROM API_KEY`. Now they have your API key. Suppose you store the API key in a PHP config file. Now what if someone brute-forced your FTP password and downloaded the script? They have your API key. Suppose you encrypt the API key, store the encryption key in a PHP config file, and store the encrypted API key in the database. You're safe either way.
steven_desu
I love how you say "safe either way" while either they got your database or your FTP. I see your point but if someone can crack open your FTP you are toast (secure server shouldn't have FTP at all), no matter what. anyway I see your point but it's very weak in terms of security. after all the OP just wanted to hide an API key, of course i wouldn't be happy to share an API key with some cracker, but an API key shouldn't be allowed to make anything nasty. usually those API key are used to create a token for GET/POST HTTP calls
sathia
A: 

Hmm, you can try AES encryption. The problem is that you have to save the salt hash(98sdfx9c6v5c) somewhere in your PHP.

Insert config:

INSERT INTO config (secret_key) VALUES (AES_ENCRYPT('secret api key','98sdfx9c6v5c'));

select config:

SELECT AES_DECRYPT(secret_key,'98sdfx9c6v5c') AS secret_url FROM config
Bas van Dorst
+2  A: 

MCrypt can be your friend here. What you do need to take into account, though, is that every publicly available (and useful) encryption method requires a key. If AES encryption or 3DES encryption didn't require a key during the encryption process then breaking the encryption would just be a matter of trying every standard decryption method until you got a meaningful result. Thus, storing the key for your payment gateway incurs the exact same risks as storing the key for your encryption. No matter how many layers of encryption you want to add, at some level there will have to be a key stored in plain text, usually hard-coded into the PHP and often in an included config.php file to make it easy to change in the future.

The only option for securely storing information without the need for a key would be to invent your own encryption method. The security of this method lies solely in the fact that no one knows the means by which you are encrypting the string, so they don't have a step-by-step pattern to just walk backwards through. If you ever told someone how your encryption worked, though, then the security would be forfeit. Also, there are many algorithmic ways to break simple encryptions (letter replacement, for example). This is why mathematicians get a lot of money for developing things like AES.

Your best best is to look into MCrypt Encrypt and MCrypt Decrypt. This way if just your PHP is compromised then they know the key you used to encrypt, but they don't have the data. If just the database is compromised then they have the data but not the key you used to encrypt it. If both are compromised, you're screwed. But if both are compromised you're screwed no matter what you do, so that's a fairly safe route.

steven_desu
Thanks, Steven. I'm aware that if both the code and the database are hacked, we're up a creek. But that's pretty much the case everywhere, right? There's only so much you can do.
EmmyS
There is one way I know around that problem, actually, but it involves a LOT of code and a LOT of overhead. I made a system one time which used three computers. One was the "PHP master", one was the "database master", and one was the "key master". The PHP master had the key to the database master, the database master had the key to the key master, and the key master had a database of keys (one for every row of data) for the data within the database master. I also had all PHP on the hard drive encrypted and it was decrypted to a RAM drive when the computer booted.
steven_desu
Yeah, I'm not sure our client would be willing to pay for the amount of work that would take. Plus, again - the site is cloud hosted, so we need to keep things in pretty much a single location. (And I can't help giggling and thinking, "there is only zul" every time you mention key master...)
EmmyS