br0ken Posted June 27, 2008 Share Posted June 27, 2008 Hello again! I'm trying to find a way to safely store credit card numbers in a database. I've recently installed mcrypt on PHP/IIS server and have been using several pre-written classes to try to encrypt, store and then decrypt the credit card information. The details were encrypted and saved fine but then when attempting to decrypt them, only about 60% of them could be decrypted to their initial value. After reading about this from various sources I realised that a VARCHAR field strips white space from a string and this could be causing the error. After changing the field type to a TEXT field, the same problem still occured. I read the thread on this problem already in this forum but unfortunately, the poster there solved his problem by simply resetting his server. This however, did not work for me. Any help would be much appreciated! Quote Link to comment Share on other sites More sharing options...
Jabop Posted June 27, 2008 Share Posted June 27, 2008 You should probably include code, result, error messages, etc. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 There are no error messages. The decrypt function returns a value however this value is not the value that was initially encrypted. As for code, I have used several different mcrypt classes, all of which have the same results. I think the problem is based on the fact that the encrypted string is binary information and the database doesn't know how to store this, however this is just speculation. Quote Link to comment Share on other sites More sharing options...
Jabop Posted June 27, 2008 Share Posted June 27, 2008 Well we're not going to be able to help without your code, so I don't know what to tell you. :-\ Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 It's not a code issues though so posting code would be no help what so ever. I know this because I've tried four different mcrypt implementations and had the same problem with each one. This error is due to more how binary information is stored in the database and I was hoping that someone on here would have had the same problem or some information on this subject. Quote Link to comment Share on other sites More sharing options...
PFMaBiSmAd Posted June 27, 2008 Share Posted June 27, 2008 You should be using a BLOB type so that the character encoding of the database cannot affect the data. You also need to be escaping the data, which is why posting your code is important so that we can see what exactly you are doing and what you are not. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 I use addslashes and strip_tags to escape my code. Is this sufficient or should I be using mysql_real_escape_string()? Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 You should be using mysql_real_escape_string() especially when it comes to storing sensitive information. You want everything as secure as possible. I always avoid adding slashes regardless anyway. But as the previous posts have stated, post your code. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 OK here's the class I'm using to encrypt and decrypt stuff. I hope this helps class xCrypt { function mykey(){ return md5(_token1._systemName._token2); } function linencrypt($pass) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); //get vector size on ECB mode $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); //Creating the vector $cryptedpass = mcrypt_encrypt (MCRYPT_RIJNDAEL_256, $this->mykey(), $pass, MCRYPT_MODE_ECB, $iv); //Encrypting using MCRYPT_RIJNDAEL_256 algorithm return $cryptedpass; } function lindecrypt($enpass) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $decryptedpass = mcrypt_decrypt (MCRYPT_RIJNDAEL_256, $this->mykey(), $enpass, MCRYPT_MODE_ECB, $iv); //Decrypting... return rtrim($decryptedpass); } } I've now converted the field storing the numbers to a BLOB but am still experiencing the same problems. About mysql_real_escape_string(), I currently have a function input(variable, maxlength) in which all input is filtered. Should I just add mysql_real_escape_string() to this in the place of addslashes? Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 Please in future use the code BB tags. And just out of curiosity, why not just create your own algorithm? Just use other encryption methods to create your own. That's what I do, then it's unlikely for someone to crack it unless they know exactly what method you use. I use this for passwords: function secure_password($password) { $password = $this->secure($password); $password = md5(sha1('!h6' . $password . substr($password, -1) . substr($password, 0, 2))); $password = sha1($password . '@^$' . md5($password)); $password = str_rot13(substr($password, 3) . 'zFq'); $password = sprintf('%s%x', $password, crc32($password)); return $password; } Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 Yeah but what if the person who had stolen your credit card numbers also had your algorithm? Couldn't they just perform the algorithm in reverse and then have the decrypted text? Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 No, it doesn't work like that. When a person registers, their password is encrypted and then written to the database. Then when they log in, the password is again encrypted using the same method and then compared to the one already in the database for validation. It will never appear in plain text again unless they had some kind of rainbow table (which people use to decrypt MD5 hashes). Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 Yeah but I'm encrypting credit card numbers that will again need to be decrypted so this wouldn't be a viable solution for me. Thanks anyway though. Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 Why would they need to be decrypted again? EDIT: Also bear in mind that when people submit forms, using POST or GET methods all data is sent in plain text any way unless the website has an SSL certificate and is SSL secured. Quote Link to comment Share on other sites More sharing options...
Jabop Posted June 27, 2008 Share Posted June 27, 2008 Wolphie, ... whoa. <?php define("ENCKEY", "PASSPHRASE"); function Encrypt($Str,$Key=ENCKEY) { $IVSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $IV = mcrypt_create_iv($IVSize, MCRYPT_RAND); $CryptStr = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $Key, $Str, MCRYPT_MODE_ECB, $IV); return trim($CryptStr); } function Decrypt($CryptStr,$Key=ENCKEY) { $CryptStr = SafeBase64Decode($CryptStr); $IVSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $IV = mcrypt_create_iv($IVSize, MCRYPT_RAND); $DecryptStr = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $Key, $CryptStr, MCRYPT_MODE_ECB, $IV); return trim($DecryptStr); } ?> Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 Because the company using the ecommerce system has a in house card processing machine (I forget the correct term). The card information needs to be encrypted and stored in the database untill they have time to process the order. When this time comes the information will be decrypted and then deleted. Sometimes it can take a while for them to process an order so if in that time the database records were somehow hacked, it would be much more secure if they were encrypted. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 Wolphie, ... whoa. <?php define("ENCKEY", "PASSPHRASE"); function Encrypt($Str,$Key=ENCKEY) { $IVSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $IV = mcrypt_create_iv($IVSize, MCRYPT_RAND); $CryptStr = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $Key, $Str, MCRYPT_MODE_ECB, $IV); return trim($CryptStr); } function Decrypt($CryptStr,$Key=ENCKEY) { $CryptStr = SafeBase64Decode($CryptStr); $IVSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $IV = mcrypt_create_iv($IVSize, MCRYPT_RAND); $DecryptStr = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $Key, $CryptStr, MCRYPT_MODE_ECB, $IV); return trim($DecryptStr); } ?> Thanks, I'll give this a try now! Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 Wolphie, ... whoa. Lol, huh, what? br0ken: That isn't a really failsafe method. As you said, it needs the ability to be decrypted and in which case, would make it a perfect target for hackers. Seeing as it is *supposed* to be decrypted. If they get hold of the method you use, you're f***ed. Things that are encrypted aren't supposed to be decrypted, especially sensitive information like that. Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 Wolphie, ... whoa. Lol, huh, what? br0ken: That isn't a really failsafe method. As you said, it needs the ability to be decrypted and in which case, would make it a perfect target for hackers. Seeing as it is *supposed* to be decrypted. If they get hold of the method you use, you're f***ed. Things that are encrypted aren't supposed to be decrypted, especially sensitive information like that. They should be sent to a secure e-mail address which makes use of SSL authentication. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 What would you do in this situation? The credit card details HAVE to be stored, it's really as simple as that. How would you make them as secure as can be? Quote Link to comment Share on other sites More sharing options...
Wolphie Posted June 27, 2008 Share Posted June 27, 2008 If you want my honest opinion, I'm not really sure. I don't work with eCommerce at all. I don't really like working with sensitive information, especially credit-cards. And if that is the case, I would use PayPal as a gateway. But one thing is for sure, USE SSL. Also, try doing some research on google about how PayPal, and other payment gateways do it. P.S. Could a moderator/administrator remove my second post above. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 We require all our clients to SSL if they are to have an ecommerce with us. Paypal is not really a viable solution. After performing some research we've found that some people are put off by having to sign up for another account (as well as the ecommerce account) and this can mean a loss of sales in some cases. Amazon handle credit cards really well. They have a seperate server that is not connected to the internet but is connected to their internal network via a serial cable. While this is extremely secure, it's not cost-effective for us to use. Quote Link to comment Share on other sites More sharing options...
discomatt Posted June 27, 2008 Share Posted June 27, 2008 Wolfie, you don't know what you're talking about.... SSL is 128-bit... and uses weaker methods of encryption than what MCrypt offers. If you can break Rijndael 256 without the key, I would love to see you do it The idea of 2-way encryption is that it's going to take an attacker time to decrypt. In this time, assuming you know you've been attacked you can alert users, who can then change credit card numbers. This makes the data the attackers are now cracking absolutely worthless. MCrypt uses VERY, VERY strong methods of 2-way encryption. The data is at greater risk on its way to the server ( even with SSL ) than it is once it's stored using a good MCrypt class. As long as they don't get the key, the data will be pretty much useless. function secure_password($password) { $password = $this->secure($password); $password = md5(sha1('!h6' . $password . substr($password, -1) . substr($password, 0, 2))); $password = sha1($password . '@^$' . md5($password)); $password = str_rot13(substr($password, 3) . 'zFq'); $password = sprintf('%s%x', $password, crc32($password)); return $password; } This is just plain ugly, and quite redundant. Simply using a random salt, and randomly mixing it in with a hash is more than enough to make it unfeasible to brute-force, and also protects it from any existing table-based attacks. Quote Link to comment Share on other sites More sharing options...
br0ken Posted June 27, 2008 Author Share Posted June 27, 2008 discomatt, can you recommend any good Mcrypt classes to me? Also, how would I store the encrypted information in a MySQL table. I've been told to use a BLOB field but am having difficulty in decrypting encrypted values. For 70% of the time, the values are decrypted but the rest of the time they are not! Quote Link to comment Share on other sites More sharing options...
discomatt Posted June 27, 2008 Share Posted June 27, 2008 Amazon handle credit cards really well. They have a seperate server that is not connected to the internet but is connected to their internal network via a serial cable. While this is extremely secure, it's not cost-effective for us to use. That is something I would suggest.. keeping the database offline, connecting it a few times a day (or as needed) for just enough time to move the data from the online to the offline machine. If this is unfeasible, you had better make sure your online machine is locked down tight, and that you have insurance in case the worst happens. A server capable of doing this shouldn't run you more than $2,000, plus another $1,000 or so if you have to hire outside help to design a secure way to talk between the machines. Seems worth it, in my opinion. discomatt, can you recommend any good Mcrypt classes to me? Also, how would I store the encrypted information in a MySQL table. I've been told to use a BLOB field but am having difficulty in decrypting encrypted values. For 70% of the time, the values are decrypted but the rest of the time they are not! Most MCrypt classes work the same... I've always just designed my own ( as most are designed to be flexible, and that creates a slight inefficiency as I don't need mine to be ). I'll make up a class and test it on me local machine and see if I can get consistent results. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.