Encryption with Checksum

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Encryption with Checksum

Post by cusimar9 »

Hi,

I'm using the following methods to encrypt/decrypt a string. They're modified versions of functions from the php.net website:

Code: Select all

 
function crc($str, $crc_len=2) {
    $result = base_convert(sha1($str),10,36);
    return substr($result,0,$crc_len);
}
 
function encrypt($text, $short=false){
    if (!$text) return false;
    $blocksize = ($short==false) ? MCRYPT_RIJNDAEL_256 : MCRYPT_RIJNDAEL_128;
    $crc_len = ($short==false) ? 6 : 2; 
    $checksum = crc($text, $crc_len);
    $text = $text . $checksum; // add the checksum to the end of the string so we can verify decryption
    $key = '8idf33jkf0Kjd'; // the cipher key
    $iv_size = mcrypt_get_iv_size($blocksize, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $crypttext = mcrypt_encrypt($blocksize, $key, $text, MCRYPT_MODE_ECB, $iv);
    return trim(base64_encode($crypttext));
}
 
// Decrypt a string. 
// Short parameter denotes whether 128 or 256 bit encryption was used as well as
// the size of the checksum
function decrypt($text, $short=false){
    if (!$text) return false;    
    $blocksize = ($short==false) ? MCRYPT_RIJNDAEL_256 : MCRYPT_RIJNDAEL_128;
    $crc_len = ($short==false) ? 6 : 2; 
    $key = '8idf33jkf0Kjd'; // the cipher key
    $crypttext = base64_decode($text); // decode encrypted string
    $iv_size = mcrypt_get_iv_size($blocksize, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);    
    $decrypttext = mcrypt_decrypt($blocksize, $key, $crypttext, MCRYPT_MODE_ECB, $iv);
    $result = trim($decrypttext); 
    
    $checksum = substr($result,strlen($result)-$crc_len); // split the decrypted string and the checksum
    $result = substr($result,0,strlen($result)-$crc_len);
    return ($checksum == crc($result, $crc_len)) ? $result : "error";  
}
 
I've been modifying it tonight to include a checksum at the end of the string, before encryption. Then the string is decrypted, and the checksum verified to ensure the string was fiddled before decryption.

What I've written above works very well, but being the fussy sod I am I'm trying to see how I can improve it.

Put simply, I'm toying with including an entire SHA1 hash of the original string, before encrypting it, which is absolutely insane. Surely the standard MCRYPT class can return a result of whether or not the decryption was successful, without me having to do all this? I don't particularly need high security but I only want to write this once and I could re-use it in the future.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Encryption with Checksum

Post by Benjamin »

I don't think there is a valid reason to do that. If the encrypted string was modified, I would think the decryption would fail.
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Re: Encryption with Checksum

Post by cusimar9 »

astions wrote:I don't think there is a valid reason to do that. If the encrypted string was modified, I would think the decryption would fail.
The above functions don't seem to fail though, if the string was modified they just return a garbled string
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Encryption with Checksum

Post by Benjamin »

cusimar9 wrote:The above functions don't seem to fail though, if the string was modified they just return a garbled string
That means the decryption failed.
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Re: Encryption with Checksum

Post by cusimar9 »

astions wrote:
cusimar9 wrote:The above functions don't seem to fail though, if the string was modified they just return a garbled string
That means the decryption failed.
Thanks :lol:

But how do you tell a garbled string from a real one was my question. I'm using a checksum at the moment which works well, but many decryption routines I've seen/used in the past return an actual error (either false, 'error', throw an exception etc), so I'm just surprised MCrypt doesn't seem to do that.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Encryption with Checksum

Post by Benjamin »

You could prepend or append the encrypted string with an MD5 of the unencrypted data.
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Re: Encryption with Checksum

Post by cusimar9 »

astions wrote:You could prepend or append the encrypted string with an MD5 of the unencrypted data.
If you look at the code above that's exactly what I'm doing. The function crc takes a specified number of characters from a sha1 hash of the string and this is appended to the string before encryption as the checksum.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Encryption with Checksum

Post by Benjamin »

I didn't look at the code. I based my comments on what you said:
cusimar9 wrote:I've been modifying it tonight to include a checksum at the end of the string, before encryption. Then the string is decrypted, and the checksum verified to ensure the string was fiddled before decryption.
I would put the checksum at the beginning of the string, after encryption. Not the opposite.
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Re: Encryption with Checksum

Post by cusimar9 »

astions wrote:I would put the checksum at the beginning of the string, after encryption. Not the opposite.
At the start of the string, and AFTER encryption. Why? It must be before encryption or the checksum itself could be fiddled as well as the encrypted string. If the encrypted string is taken and decrypted as a whole then its surely more secure.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Encryption with Checksum

Post by Benjamin »

cusimar9 wrote:
astions wrote:I would put the checksum at the beginning of the string, after encryption. Not the opposite.
At the start of the string, and AFTER encryption. Why? It must be before encryption or the checksum itself could be fiddled as well as the encrypted string. If the encrypted string is taken and decrypted as a whole then its surely more secure.
Well, like I said, I don't see a valid reason to do this. You cannot modify an encrypted string without knowing how to decrypt/encrypt it. If you md5 the data before you encrypt it, then attach this md5 to the encrypted data, you can then verify that the data is the same.

The ability for one to be able to modify the checksum is irrelevant because they would never be able to modify the encrypted data. The only way they could is if they knew the decryption key, in which case your checksums are useless.
cusimar9
Forum Newbie
Posts: 8
Joined: Tue Sep 01, 2009 3:41 pm

Re: Encryption with Checksum

Post by cusimar9 »

OK I'll leave it as it is. Totally overkill for what I'm using it for anyway, a rot13 would probably suffice!
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: Encryption with Checksum

Post by kaisellgren »

Modifying encrypted data is forbidden. However, you are just encoding it, so, it does not hurt.

Taking a checksum of data, encrypting it and then appending the checksum into the beginning of the encrypted data is a valid way to ensure integrity. However, a simple hash is not sufficient (at least not the case with the Merkle Damgård construction). Use HMAC, that's meant for it.

The encryption process is poor, but luckily it seems you do not need to worry about that. :P
Post Reply