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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576234
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576235
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576238
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576251
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576253
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576257
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576265
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576270
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576296
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576321
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
https://forums.phpfreaks.com/topic/112225-solved-mcrypt/page/2/#findComment-576341
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • 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.