1

I am having some odd issues here....

I have the two following scripts:

First, a PHP script (which I am using http://writecodeonline.com/php/ to test)

$key = '[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[nJ7rO@T^PwgT!NVY*Hri@($p4luBM)ugVvbnAnWL@xGK*jBP3s$g#-XTH{e3@X*0StJ';
$string = 'Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ';

//
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key), $string, MCRYPT_MODE_ECB));

$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, md5($key), base64_decode($encrypted), MCRYPT_MODE_ECB), "\0");


echo $encrypted . "<br>";
echo $decrypted;

Second, a Java class,

import java.io.*;
import java.net.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.*;
import javax.crypto.spec.*;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;


public class Main {

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        String pw = "[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[nJ7rO@T^PwgT!NVY*Hri@($p4luBM)ugVvbnAnWL@xGK*jBP3s$g#-XTH{e3@X*0StJ";
        String str = encode("Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ", pw);
        System.out.println(str);
        System.out.println(decode(str, pw));
    }

    public static String encode(String s, String p) throws Exception
    {
        String cleartext = padRight(s, s.length()+(16-(s.length()%16)));
        String key = DigestUtils.md5Hex(p);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(cleartext.getBytes());
        return Base64.encodeBase64String(encrypted);
    }

    public static String decode(String encrypted, String p) throws Exception
    {
        byte[] bts = Base64.decodeBase64(encrypted);


        String key = DigestUtils.md5Hex(p);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);



        byte[] decrypted = cipher.doFinal(bts);

        return new String(decrypted).replaceAll("\0", "");
    }

    public static String padRight(String s, int n) {
        while (s.length() < n)
        {
            s+="\0";
        }
        return s;
    }

}

Something very strange happens. When I test the PHP script, I get:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWg==

as the encrypted code.

When I test the java code, however, I get:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWsdyQJ3DP2jBsJcLh2n2wv0=

If you look closely, you will see that (somehow) the java text is longer! But, oddly, both of the texts are exactly the same up until "+EAH" which is when they diverge. I find this completely strange -- why?

Because I have tested this code on numerous other strings, from lorum ipsum, to the word "Testing" with no errors. The only way I have found of causing this (so far) is to repeat a shortish word many times separated by spaces.

I am incredibly worried about this because I have no idea what other ways there are to trigger this strange behavior. So that leads me to my question... WHat in the name of davy jone's locker is casking this?

Georges Oates Larsen
  • 6,812
  • 12
  • 51
  • 67

2 Answers2

4

I'm not an expert of encryption, but it may be a padding issue. You may try with the following.

PHP
Set the padding as follows:

$blockSize = mcrypt_get_block_size(MCRYPT RIJNDAEIL_128, MCRYPT_MODE_ECB);
$padding = $blockSize - (strlen($string) % $blockSize);
$string .= str_repeat(chr($padding), $padding);

This will use PKCS#5 padding, instead of PHP's null padding.

Java
Change the following line:

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

to:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

Unfortunately I don't have an environment with Java where I can compare the results, but I hope it helps.

Diego
  • 7,312
  • 5
  • 31
  • 38
  • Thanks a ton! That works like a charm! I would like to note for future viewers that I had to change MCRYPT_RIJNDAEL_256 to MCRYPT RIJNDAEIL_128 – Georges Oates Larsen Aug 07 '12 at 02:39
  • Glad to have helped. I also corrected my answer, I meant to put 128 from the beginning. It was a bit early in the morning, I must have been sleepy. :) – Diego Aug 07 '12 at 13:56
  • Not a problem! I was rather tired myself -- I meant to write MCRYPT_RIJNDAEIL_128 in my comment not MCRYPT RIJNDAEIL_128 – Georges Oates Larsen Aug 07 '12 at 23:06
  • To decrypt on PHP: http://stackoverflow.com/questions/16895540/php-mcrypt-encrypt-decrypt-returns-invisible-strange-characters – Carlos González Jan 27 '16 at 23:21
1

The code have misspellings in constant's name, the correct code is:

$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$padding   = $blockSize - (strlen($tokenRaw) % $blockSize);
$tokenRaw .= str_repeat(chr($padding), $padding);

$encode    = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $tokenRaw, MCRYPT_MODE_ECB));
Skilla
  • 31
  • 2