0

I have a Java program that can encrypt using AES/ECB/PKCS5Padding cipher with 256bit key, and I want to write a PHP script that produce the same result.

However, my script failed to do so. I kind of get a feel that how they process the key before encryption is the problem, but I cannot tell.

Could someone point out what's wrong in the PHP script ?

Thanks.

Here are the example codes, you can simply run it after copy & paste:

Java

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;

public class JavaCipher {

    private SecretKeySpec secretKey;

    private JavaCipher(String secret) throws Exception {
        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        byte[] digest = sha.digest(secret.getBytes("UTF-8"));
        secretKey = new SecretKeySpec(digest, "AES");
    }

    private String encrypt(String sSrc) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes());
        return DatatypeConverter.printHexBinary(encrypted).toLowerCase();
    }

    public static void main(String[] args) throws Exception {  
        JavaCipher cipher = new JavaCipher("some random key");

        // print d013acccb5d191a00898ac87057383ff
        System.out.println(cipher.encrypt("abcdefg"));
    }
}

PHP

<?php

class PHPCipher {

    private $key;

    public function __construct($key)
    {
        $this->key = substr(hash('sha256', $key), 0, 32);
    }

    public function encrypt($data)
    {
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $this->key, $iv);
        $result = mcrypt_generic($td, $this->pad($data, $size));
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return bin2hex($result);
    }

    private function pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }
}

$cipher = new PHPCipher('some random key');
// print 9a4df66d67a3e8d4a1dda7cda6e94d07
echo $cipher->encrypt('abcdefg');
Rangi Lin
  • 8,822
  • 4
  • 41
  • 69
  • 4
    **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Jul 29 '16 at 16:37
  • And don't use mcrypt_* functions in PHP. – Luke Joshua Park Jul 30 '16 at 00:08
  • 3
    Always interesting to see people going through all these steps generating an IV for ECB mode. – Maarten Bodewes Jul 30 '16 at 14:09
  • 2
    I don't know why my comment is missing, so let me said it again This is required in order to integrate with 3rd party cooperation – Rangi Lin Aug 06 '16 at 06:25

1 Answers1

0

Since AES with key size 256 bit is what I need, all I need to do is provide a 32 bytes key.

Instead of cutting the string into 32 characters (which changes the key) :

$this->key = substr(hash('sha256', $key), 0, 32);

I should do pack it into binary string

$this->key = pack('H*', hash('sha256', $key));
Rangi Lin
  • 8,822
  • 4
  • 41
  • 69
  • BTW, you do have the choice to refuse to use ECB mode, just say no and don't do it, otherwise you are contributing to poor security. If we software developers want to be professionals we must do the right thing. Consider a civil engineer when asked to use a beam of insufficient strength he would not do it because he is a professional. Your choice. – zaph Jul 29 '16 at 14:30
  • 1
    Instead of using `pack`, you could simply pass `true` as the third argument to `hash` and you don't need to use `substr` at all – Artjom B. Jul 29 '16 at 16:39