1

I'm trying to create a package in perl that is equivalent to our pre-existing class in php for handling data encryption.

The encryption type seems to be TripleDES in ECB mode however I cannot replicated the resulting cypher text using Crypt::CBC or Crypt::TripleDES.

I think the issue is to do with either padding or the key format (binary vs hex etc) yet searching though the documentation isn't helping me find an answer.

The current PHP class is as follows (trimmed down but with the same core functionality):

<?php
class Encryption {
    private $encryption_key;
    private $encryption_td;
    private $encryption_iv;

    private function __construct() {
        $this->encryption_key = 'abc123';
        $this->encryption_td = mcrypt_module_open( 'tripledes', '', 'ecb', '' );
        $this->encryption_iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size( $this->encryption_td ), MCRYPT_RAND );

        mcrypt_generic_init( $this->encryption_td, $this->encryption_key, $this->encryption_iv );
    }

    public function __destruct() {
        mcrypt_generic_deinit( $this->encryption_td );
        mcrypt_module_close( $this->encryption_td );
    }   

    public static function instance($key = null, $iv = null, $algorithm = null, $mode = null) {
        static $instance;

        if (! $instance) {
            $instance = new Encryption( $key, $iv, $algorithm, $mode );
        }

        return $instance;
    }

    public function encrypt( $password ) {
        return base64_encode( mcrypt_generic( $this->encryption_td, $password ) );
    }

    public function decrypt( $password ) {
        return trim(mdecrypt_generic( $this->encryption_td, base64_decode( $password ) ) );
    }
}

function decrypt_password( $password ) {
    return Encryption::instance()->decrypt( $password );
}

function encrypt_password( $password ) {
    return Encryption::instance()->encrypt( $password );
}

print encrypt_password( 'wibblewobble123' ) . "\n";
print decrypt_password( encrypt_password( 'wibblewobble123' ) ) . "\n";
?>

My current perl package is as follows:

package Encryption;
use warnings;
use strict;
use MIME::Base64;
use Crypt::TripleDES;

sub new {
    my $class = shift;
    my $self = {};
    $self->{'encryption_key'} = 'abc123';
    $self->{'td'} = Crypt::TripleDES->new();
    bless( $self, $class );
    return $self;
}

sub decrypt {
    my( $self, $encrypted_password ) = @_;
    $encrypted_password = decode_base64( $encrypted_password );
    my $password = $self->{'td'}->decrypt3( $encrypted_password, $self->{'encryption_key'} );
    chomp( $password );
    return $password;
}

sub encrypt {
    my( $self, $password ) = @_;
    my $encrypted_password = $self->{'td'}->encrypt3( $password, $self->{'encryption_key'} );
    $encrypted_password = encode_base64( $encrypted_password );
    chomp( $encrypted_password );
    undef( $password );
    return $encrypted_password;
}

1;

And the test code:

use warnings;
use strict;

use Encryption;

sub decrypt {
    my $password = shift;
    my $eh = Encryption->new();
    return $eh->decrypt( $password );
}

sub encrypt {
    my $password = shift;
    my $eh = Encryption->new();
    return $eh->encrypt( $password );
}

print encrypt( 'wibblewobble123' ) . "\n";
print decrypt( encrypt( 'wibblewobble123' ) ) . "\n";

The output from each is as follows:

php:

xuRt3xxjPO1GUz+DccTVKw==
wibblewobble123

perl:

mmWuKkpvveHvnUsQ2NC6DA==
wibblewobble123

The expected result is perl's encryption subroutine returns the same output as php's encryption function with decrypt doing the same but in reverse.

If Crypt::TripleDES is the wrong way to be attacking this problem then I'm happy to use something else - This code is going to get re-written into something neater anyway.

As a side note this will need to work with multiple key lengths, so if it is a padding issue please explain how to calculate the correct padding based upon key length.

Damian
  • 11
  • 3
  • 1
    After running your (unmodified) Perl program I get "xuRt3xxjPO1GUz+DccTVKw==". Also you can find this bug report useful: https://rt.cpan.org/Ticket/Display.html?id=34237 – Alexandr Ciornii Oct 29 '11 at 23:13
  • 1
    I suspected part of the problem is that you're not using an initialization vector for perl. But replacing it with null in the PHP code has no impact on the encrypted string. :( (BTW neither EBC nor triple DES are considered very secure these days). I do hope you're not using reversible encryption for passwords. – symcbean Oct 29 '11 at 23:32
  • TrippleDES? If you're being forced to do so by some company, then by all means go ahead with it. If not, I'd avoide it at all costs. AES would be a lot better. I just cannot stand seeing DES being talked about in any serious manner anymore. Sorry if it's a job thing, but if not, I'd just avoid it. The algorithm is so broken it's not funny. – 133794m3r Nov 05 '11 at 04:16
  • I'll have a look over the cpan ticket, it's looking more like a IV issues. – Damian Nov 09 '11 at 14:31
  • For damian: ECB mode does not use an IV @Leetgamer: TripleDES is not broken at all, take a look at http://www.keylength.com/en/3/ if you don't believe, DES is only "broken" because of the short key length. Of course, for new applications everybody should use AES and *at least* CBC mode (and that's just taking care of confidentiality). – Maarten Bodewes Dec 01 '11 at 21:24
  • Don't know if this can help you, but CBC encrypt of a single block (8 bytes) without padding and IV vector of zero's is the same as an ECB block encrypt. – Maarten Bodewes Dec 08 '11 at 00:34

0 Answers0