Welcome Guest, Not a member yet? Register   Sign In
Encode with Encrypt class, Decrypt with Encryption class
#1

(This post was last modified: 06-18-2017, 04:54 PM by skunkbad.)

I'd like to be able to use the CI3 Encryption class to decrypt values that were "encoded" with the CI2 (deprecated) Encrypt class. So I set up a test controller and have been playing around, but no success. Method:

PHP Code:
/**
 * Attempt to encode via Encrypt class
 * and decrypt via Encryption class.
 */
public function encryption_test()
{
    
$this->load->library('encrypt');
    
$this->load->library('encryption');

    
// Old encryption_key from CI2
    
$key 'o23tngn2o2o3ngngnno22gon2oFdEzX2';

    
// Encrypt with CI2's Encrypt library (blowfish/cbc)
    
$this->encrypt->set_cipher(MCRYPT_BLOWFISH);
    
$this->encrypt->set_mode(MCRYPT_MODE_CBC);
    
$this->encrypt->set_key($key);

    
/**
     * CI3 Encryption class will need to use mycrypt, I think.
     * I'm just guessing that it does because the encoding
     * will be done through mcrypt. It would be great if I
     * was wrong.
     */
    
$this->encryption->initialize(['driver' => 'mcrypt']);

    
$string 'ABC123';
    
$encrypted_string $this->encrypt->encode($string);

    
//echo $encrypted_string . '<br />';

    // Decrypt using CI3's Encryption library
    
$decrypted_string $this->encryption->decrypt
        
$encrypted_string
        [
            
'cipher'   => 'blowfish',
            
'mode'     => 'cbc',
            
'key'      => $key,
            
'hmac'     => FALSE,
            
'raw_data' => FALSE
        
]);

    if( 
$string === $decrypted_string ){
        echo 
'Encrypt encode/Encrpytion decrypt success';
    }else{
        echo 
'Encrypt encode/Encrpytion decrypt failure';
    }
}

// ----------------------------------------------------------------------- 


I need help though, because no matter what I try for the custom parameters, I can never get it right.

I even tried to extend the Encryption class:

PHP Code:
public function legacy_decrypt$base64_encoded$key )
{

    
$pre_noise_removal  base64_decode$base64_encoded );

    
$dec $this->_remove_cipher_noise$pre_noise_removal$key );

    
$init_size 8;

    
$iv substr($dec0$init_size);
    
$data substr($dec$init_size);

    
/*$CI =& get_instance();
    $CI->console->log($base64_encoded);
    $CI->console->log($pre_noise_removal);
    $CI->console->log($dec);
    $CI->console->log($iv);
    $CI->console->log($data);*/

    
$str openssl_decrypt($data'BF-CBC'$key0$iv);

    return 
rtrim($str"\0");
}

function 
_remove_cipher_noise($data$key)
{
    
$keyhash sha1($key);
    
$keylen strlen($keyhash);
    
$str '';

    for (
$i 0$j 0$len strlen($data); $i $len; ++$i, ++$j)
    {
        if (
$j >= $keylen)
        {
            
$j 0;
        }

        
$temp ord($data[$i]) - ord($keyhash[$j]);

        if (
$temp 0)
        {
            
$temp $temp 256;
        }

        
$str .= chr($temp);
    }

    return 
$str;


If I try to use the legacy_decrypt method, my debugging shows that the string is exactly what it should be compared to what it was before encoding with the Encrypt class. The data is the same, the key, the IV, and everything I can see is the same.


The problem for me is that we have a lot of stored records that have been "encoded" using the Encrypt class, and it may be impossible (due to physical access issues) for me to get those records and work on them, yet there may be a time when we need to "decode" them and mcrypt is no longer on the server.

If anyone can help I'd appreciate it.
Reply
#2

Can't happen, but that's why the old Encrypt library wasn't immediately dropped - old data needs to be decrypted.

To make your life easier in the future, just re-encrypt all of your data (decrypt via CI_Encrypt; encrypt via CI_Encryption) right now. And use AES this time, it's the default for a reason. Smile
Reply
#3

(06-18-2017, 10:12 PM)Narf Wrote: Can't happen, but that's why the old Encrypt library wasn't immediately dropped - old data needs to be decrypted.

To make your life easier in the future, just re-encrypt all of your data (decrypt via CI_Encrypt; encrypt via CI_Encryption) right now. And use AES this time, it's the default for a reason. Smile

I see your comments all over Stack Overflow, and see you are definitely an expert in this field. While your advice is what I will end up doing, I did see that by setting the options on openssl_decrypt to:

OPENSSL_RAW_DATA | OPENSSL_NO_PADDING

It does decrypt properly. Which is awesome!


I got the solution here: https://3v4l.org/kYAXn

This would only be for emergency purposes in the future. Like if my boss comes to me and says they have some decrypting to do on stored data that is currently inaccessible to me.

I realize this is only for blowfish, but here are the revised methods extending Encryption class for legacy decrypt:

PHP Code:
public function legacy_decrypt$base64_encoded$key )
{

 
   $pre_noise_removal  base64_decode$base64_encoded );

 
   $dec $this->_remove_cipher_noise$pre_noise_removal$key );

 
   $init_size 8;

 
   $iv substr($dec0$init_size);
 
   $data substr($dec$init_size);

 
   $str openssl_decrypt($data'BF-CBC'$keyOPENSSL_RAW_DATA OPENSSL_NO_PADDING $iv);

 
   //try to detect null padding
    
if (mb_strlen($iv'8bit') % mb_strlen($str'8bit') == 0) {
     
       preg_match_all('#([\0]+)$#'$str$matches);
     
       if (mb_strlen($matches[1][0], '8bit') > 1) {
     
               $str rtrim($str"\0");
     
               //trigger_error('Detected and stripped null padding. Please double-check results!');
     
       }
    }

 
   return rtrim($str"\0");
}

private function 
_remove_cipher_noise($data$key)
{
 
   $keyhash sha1($key);
 
   $keylen strlen($keyhash);
 
   $str '';

 
   for ($i 0$j 0$len strlen($data); $i $len; ++$i, ++$j)
 
   {
 
       if ($j >= $keylen)
 
       {
 
           $j 0;
 
       }

 
       $temp ord($data[$i]) - ord($keyhash[$j]);

 
       if ($temp 0)
 
       {
 
           $temp $temp 256;
 
       }

 
       $str .= chr($temp);
 
   }

 
   return $str;

Reply
#4

Yes, you can do it using raw primitives ... that's not the same thing as using CI_Encryption to do it.
Reply
#5

Would you consider a legacy_decrypt method in the Encryption class?
Reply
#6

No ... why would I want to duplicate what CI_Encrypt already does?
Reply
#7

(06-19-2017, 08:45 AM)Narf Wrote: No ... why would I want to duplicate what CI_Encrypt already does?

If mcrypt is no longer available for whatever reason. I see it is or will be in PECL, but thinking that some won't have the ability to install it. It could be problematic, with lots of forum posts and people freaking out. I figured it out, so I guess anybody can ...
Reply
#8

You figured out how to use Blowfish via OpenSSL, but for a lot of the ciphers supported by mcrypt, there's no OpenSSL support.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB