views:

451

answers:

1

I have a class that takes a string in this format:

000067000000000012620060324b38e2cab3353

, encrypts the string then appends it as a get variable in a URL.

The class that does the encryption has a function that looks like this:

private function _code_encryption($enc_type,$a_string){
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);                          

    if($enc_type == self::ENCRYPT_STRING){
       //encrypt then return base64 encoded
       $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $a_string, MCRYPT_MODE_CBC, $iv);
       return base64_encode($encrypted);
    }elseif($enc_type == self::DECRYPT_STRING){
       $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, base64_decode($a_string), MCRYPT_MODE_CBC, $iv);
        return trim($decrypted);
    }
}

When the string is encrypted I urlencode the value and add it to the url like the url looks like "https://secure.mysite.com/index.php?action=someaction&transfer_code=XXXXX where XXXX is the urlencoded encrypted string.

Now, when the url is parsed and processed the value of $_GET['transfer_code'] is getting passed into the above _code_encryption function but is not returning the correctly decrypted value and instead returns garbled characters my browser doesn't render. Is there a requirement for the length of the key I use for encryption/decryption? I tried something like

$key = hash('sha256',self::AUTH_ENCRYPTION_KEY,true);

but that didn't work either...

Also, I am not urldecoding the $_GET['transfer_code'] variable because the php man pages state that get vars are already urlencoded...

Should I be UTF-8 encoding the alphanumeric string BEFORE encryption/base64_encoding, or will that even make any difference?

+3  A: 

You use a random IV to encrypt, and the a different random IV to decrypt. The decrypted string will never ever match the original. To properly decrypt the original string you must use the same IV that was used during encryption. Usually this is achieved by prepending the IV used to the encrypted string. At decryption time you must first extract the IV from the value, initialize the key with this value, then decrypt the rest usign the properly initialized key.

I don't have a parser to validate this but it should be something like:

private function _code_encryption($enc_type,$a_string){
 $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
 if($enc_type == self::ENCRYPT_STRING){
  //encrypt then return base64 encoded
  $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $a_string, MCRYPT_MODE_CBC, $iv);
  return base64_encode($iv.$encrypted);
 } elseif ($enc_type == self::DECRYPT_STRING){
  $decoded = base64_decode($a_string);
  $iv = substr($decoded,0,$iv_size);
  $cipher = substr($decoded,$iv_size);
  $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $cipher, MCRYPT_MODE_CBC, $iv);
  return trim($decrypted);
 }
}
Remus Rusanu
Are you intentially skipping the 1st char of the iv ( substr($decoded,1,$iv_size) )?I thought everything was working correctly (extracting the IV from char 0, not 1) but I'm getting mixed results. For example encrypting/encoding this string "67:1262031751:4b38e2cab2353" works great but this one "24:1262031777:4b38e2cab2353" never works at all and returns a 64 char string of bogus characters.
eCaroth
No, id did not skip 1st char intentionally. I just didn't rember if is 0 based or 1 based.
Remus Rusanu
If some strings work some don't make sure your base64 encode/decode is correct. base64 pads the output with '=' and if the urlencode/decode strips the '=' then the base64 encode/decode is corrupted and the result is the cipher is corrupted. you're going to take this one by one and verify at each step that the reverse operation works (decrypt the output after encrypting and verify, decode after encoding, and verify etc).
Remus Rusanu
Turns out the urlencoding was preserving the "=" signs fine but spaces were being converted to %2B, rather than "+". Problem solved.
eCaroth