-1

I am trying to create the encrypt PHP algorithm from this thread:

how to sync encryption between delphi and php using dcpcrypt (see shunty's reply)

Here is what I have so far:

function encrypt($str, $key)
{
    $keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);

    $ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
    $iv = implode(array_map("chr", $ivbytes));

    $pad = ord($str[strlen($str) - 1]);
    $enc = substr($str, 0, strlen($str) - $pad);

    $enc = base64_encode($str);
    $k = mhash(MHASH_SHA1, $key);

    //return substr($dec, 0, strlen($dec) - $pad);
    $dec = mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);

    return $dec;
}

I'm not sure what I'm doing wrong but testing it with this:

echo encrypt("this is a test", "test");

Gives the output: =ž«RCdrç­b˜hý’¯á·OÊ when it should give: WRaG/8xlxqqcTAJ5UAk4DA==

Can anyone help me out in explaining where I am going wrong, would really appreciate the help I can get.

EDIT:

function encrypt_SO($str, $key)
    {
        $keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);

        $ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
        $iv = implode(array_map("chr", $ivbytes));

        $pad = ord($str[strlen($str) - 1]);
        $enc = substr($str, 0, strlen($str) - $pad);
        $k = mhash(MHASH_SHA1, $key);

        //return substr($dec, 0, strlen($dec) - $pad);
        $dec = mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);

        return base64_encode($dec);
    }

Moved the encoding to the end.

EDIT 2: Solution thanks to everyone's helpful posts:

function encrypt_SO($str, $key)
{
    $keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);

    $ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
    $iv = implode(array_map("chr", $ivbytes));

    $k = mhash(MHASH_SHA1, $key);

    $blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $padsize = $blocksize - (strlen($str) % $blocksize);
    $str .= str_repeat(chr($padsize), $padsize);

    return base64_encode(mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $str, MCRYPT_MODE_CBC, $iv));
}
Community
  • 1
  • 1
KillerKode
  • 957
  • 1
  • 12
  • 31
  • `WRaG/8xlxqqcTAJ5UAk4DA==` has been base64 encoded, and `ž«RCdrç­b˜hý’¯á·OÊ` has not. – David Heffernan May 17 '13 at 11:32
  • Ah but I did use this: $enc = base64_encode($str); - is that not correct? I was trying to understanding the padding but I think I've made a mistake somewhere there. – KillerKode May 17 '13 at 11:36
  • Nothing you say there changes the thrust of my comment. – David Heffernan May 17 '13 at 11:46
  • 1
    Encrypt *before* you base64 encode. – shunty May 17 '13 at 14:15
  • Thanks, so I've been trying to understand the decrypt algorithm better and this is what I think it's doing: First finding the keysize which I guess would be the same in the encrypt method. Then calculating the IV which I also guess will be the same in the encrypt method as it's specific to the way the Delphi one is done. Then calculate the padding, which I'm not sure if it's done right, then change the key into a SHA1 hash, then encrypting and finally base 64 encoding. I will edit the op, I still can't get it to work right but is my understanding correct? – KillerKode May 17 '13 at 14:34

1 Answers1

1

To answer your comment above:

Encrypt:

  • Get keysize and blocksize
  • Get IV - this should really be something random and properly generated but to work with DCPcrypt without specifying an IV manually you need to use the one provided.
  • Hash the key
  • Add the padding - you've got this bit wrong. For this example you need something like:

    $blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $padsize = $blocksize - (strlen($str) % $blocksize);
    $str .= str_repeat(chr($padsize), $padsize);
    
  • Encrypt

  • Base64 encode

Decrypt:

  • Get keysize
  • Get IV - as above (must be the same as the one used to encrypt but, again, should really be properly cryptographically generated).
  • Hash the key
  • Base64 decode
  • Decrypt
  • Remove the padding
shunty
  • 3,699
  • 1
  • 22
  • 27
  • Oh my god thank you so much!!! Been trying to figure this out for two days now and I finally got it working thanks to you. I'll edit the OP with what the solution is, but I used your padding technique and also realized that the encrypt method was in MCRYPT_MODE_ECB instead of MCRYPT_MODE_CBC which was also a reason why I was getting different results too. I am working with DCPcrypt on Delphi so is there any way I can change the IV from DCPcrypt or is it too complicated? I don't really understand IV's too well though. – KillerKode May 17 '13 at 14:58
  • Another happy customer :-) Sure there's a better way. If you check the source in DCPcrypt2.pas and look for TDCP_cipher.InitStr you'll see how it derives the key then calls TDCP_cipher.Init with a nil IV. All you have to do in your code is call .Init instead of .InitStr - but then you'll have to research proper ways of generating the IV *and* research how to pass or transmit the IV to the recipient. I leave that as an exercise! – shunty May 17 '13 at 15:10
  • Alright thanks! I'll start finding some info about generating IV's and give it a go later today, really appreciate your help. :) – KillerKode May 17 '13 at 15:13