Jump to content

[SOLVED] Mcrypt


br0ken

Recommended Posts

First of all, two-way encryption/decryption is not the same as a one-way hash.

 

Getting this to work is not a matter of finding the right class or right code it is a matter of finding why your code and data is not working.

 

I created a database with a blob column and tested your class code and it works. So, something that php is doing (such as the magic_quotes_runtime setting adding escape characters to the data when it comes out of the database) or something your code is doing is causing the problem. For all we know, your code is doing an md5 on the data (since some of this seems to be left over from a password function.) We really need to see your code to be able to help.

 

Have you echoed out the various values to make sure of what they contain and have you compared these with what is in the database? Does the string you get out of the database have \ in it before several of the characters? The string you insert into the database, the string in the database, and the string you select out of the database should all be identical.

 

The class code you posted has a rtrim() in the decrypt function left over from when it was a password function. I recommend removing that (it would have no effect on a true CC number unless there were trailing trim-able characters, which your validation code should have dealt with long before they were encrypted.)

 

The code Jabop posted has an additional trim() function added to the encoding. This can break the process because there could be leading and trailing trim-able characters.

Link to comment
Share on other sites

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.

 

That will be really hard to return the CC numbers at all when you do that - and I think he needs to store the numbers for records. It'd be easier to just encrypt the numbers and decrypt them when needed

Link to comment
Share on other sites

The code Jabop posted as an additional trim() function added to the encoding. This can break the process because there could be leading and trailing trim-able characters.

 

Why would you use whitespace in a credit card number?

Link to comment
Share on other sites

You are trimming the encrypted output where it is being returned to the calling function.

 

Edit: The encrypted output can contain any 0-255 value. Trim removes several of these values -

 

" " (ASCII 32 (0x20)), an ordinary space.

"\t" (ASCII 9 (0x09)), a tab.

"\n" (ASCII 10 (0x0A)), a new line (line feed).

"\r" (ASCII 13 (0x0D)), a carriage return.

"\0" (ASCII 0 (0x00)), the NUL-byte.

"\x0B" (ASCII 11 (0x0B)), a vertical tab.

Link to comment
Share on other sites

Here is the code I've been using to test the encryption functions.

 

First I select the credit card number (cnumber) and then encrypt it and then decrypt it. These values are stored in cnumbenc and cnumbdec.

 

After this has been done for all of the numbers I display the resulting table.

 

The commented out line loads the encrypted value from the database, decrypts it then stores it in cnumbenc.

 

$db		= openDB();
$rs		= queryDB("SELECT id, cnumber FROM tblCard LIMIT 100");
$row	= 0;

while(getrowRS($rs))
{
	$id		= getvalueRS($rs, $row, "id");
	$card	= getvalueRS($rs, $row, "cnumber");

	$enc	= xEncrypt($card, mykey());
	$dec	= xDecrypt($enc, mykey());

	queryDB("UPDATE tblCard SET cnumbenc = '".mysql_real_escape_string($enc)."', cnumbdec = '".mysql_real_escape_string($dec)."' WHERE id = $id");

#	$dec	= xDecrypt(queryDBval("SELECT cnumbenc FROM tblCard WHERE id = $id"), mykey());
#	queryDB("UPDATE tblCard SET cnumbdec = '".input($dec, 60)."' WHERE id = $id");

	++$row;
}


printRS(queryDB("SELECT id, cnumber, cnumbenc, cnumbdec FROM tblCard LIMIT 100"));

Link to comment
Share on other sites

Right, that is what trim does. In a credit card number, only numbers are allowed (obv), so I put trim in there for his sake.

 

Yes but you're trimming the ENCRYPTED STRING! Which you should not do, as it can strip important leading and trailing bits. It's a binary value, not ASCII. Trimming is BAD

 

That will be really hard to return the CC numbers at all when you do that - and I think he needs to store the numbers for records. It'd be easier to just encrypt the numbers and decrypt them when needed

 

I realize this, i was simply telling him a better way to hash. And it's not really hard - it's impossible without brute forcing. Why you'd do that to your own data, I'm not entirely sure.

Link to comment
Share on other sites

@Jabop, I think you need to read the code you posted. In the encrypt function is this line - return trim($CryptStr); That will remove any leading or trailing trim-able characters from the encrypted function, destroying the encrypted cypher.

Link to comment
Share on other sites

@ broken

 

So the value is first stored in the DB in plain text, then encrypted and re-stored? This seems inefficient. Anyways, here's code that's worked for me on my test system.

 

<?php
define("ENCKEY", "SomeRandomKey");

function enc($str) {
   $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
   $iv = mcrypt_create_iv($size, MCRYPT_RAND);
   return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, ENCKEY, $str, MCRYPT_MODE_ECB, $iv);
}

function dec ($str) {
   $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
   $iv = mcrypt_create_iv($size, MCRYPT_RAND);
   return trim( mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCKEY, $str, MCRYPT_MODE_ECB, $iv) );
}

/* table data

CREATE TABLE `test_crypt` (
`data` BLOB NOT NULL
) ENGINE = innodb;

*/

echo <<<HEREDOC
<form method="post" action="">
<input type="text" name="str"><br />
<input type="submit" value="Submit"><br />
<br />
HEREDOC;

mysql_connect('localhost', 'root', '');
mysql_select_db('test');

if ( $_POST['str'] )
if ( !mysql_query("INSERT INTO `test_crypt` SET `data` = '" . mysql_real_escape_string( enc($_POST['str']) ) . "'" ) )
	echo 'Your query sucks!<br />' . mysql_error() . '<br />';

$r = mysql_query( 'SELECT `data` FROM `test_crypt`' );
if ( !$r )
echo 'Your second query sucks!<br />' . mysql_error() . '<br />';
else
while ( $d = mysql_fetch_assoc($r) ) {
	echo '<br />Encrypted string: ' . $d['data'];
	echo '<br />Decrypted string: ' . dec( $d['data'] );
	echo '<br />';
}


?>

 

Returns something like this (linebreaks added for readability):

 

<form method="post" action="">
<input type="text" name="str"><br />
<input type="submit" value="Submit"><br />
<br /><br />
Encrypted string: F
„³¾å0õé9òæ|:K¸™AÿH/M=7/š
<br />
Decrypted string: testing
<br /><br />
Encrypted string: M1ŠP!®ÄÆ;ß"ˆÞúüyóð±î¸+zÃx‡ 
<br />
Decrypted string: zomgS!
<br />

Link to comment
Share on other sites

@ broken

 

So the value is first stored in the DB in plain text, then encrypted and re-stored? This seems inefficient. Anyways, here's code that's worked for me on my test system.

 

No, the credit card numbers are in the database currently as samples. I'm extracting that number and entering the decrypted version into the database and then extracting it and attempting to decrypt it. Once I've got it working I'll integrate it into my actual system.

 

Thanks for the sample code, I shall give it a try now!

Link to comment
Share on other sites

This worked perfectly! Thank you so much everybody for helping me out.

 

One more question I have...

 

With the decrypted string being binary information, if it's saved in a ascii file backup, could it still be restored or would this corrupt the data?

 

 

Link to comment
Share on other sites

The decrypted string is ASCII, the encrypted string is binary.

 

Storing encrypted strings in a text file may be an issue, as there's no 'safe' way to separate the values... as you can see in my example, the encrypted string for 'testing' created a linebreak when displayed in ascii...

 

A way to do it might be to store it 'line-by-line', starting the line with the length of the encrypted string in bits, then a known character, say a hyphen, then the encrypted string...

 

That way, when you parse it, you can create a function that will read the first line, grab the numeric length, skip the known character, then read until the length is up, then look for a linebreak, and repeat.

Link to comment
Share on other sites

Define: "saved in a ascii file backup"

 

A standard .sql dump saves binary fields in hex. The following is from the test db I made for this thread -

 

INSERT INTO `cc` (`id`,`cc`) VALUES 
(0,0x1D7B95F18CED5D336B75EB4864529C8C14C7279EDC68203D90F73026ED6C193DEBE66608CEC557E868D68E83265E528F1CA8B4B414620762069E9B1BB3AF6BD9);

 

Link to comment
Share on other sites

Unfortunately our server wont allow us to run a sql dump so I've written my own script to perform the same task.

 

I've got the encrypted credit card number to store in a TEXT field and it works ok. Because it's in a text field, would it be ok in an ascii file?

 

Also, bin2hex is good but is there a function to reverse this? I know hex2bin doesn't exist but is there an equivilant?

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.