0

I have a DES Algorithm use java ,now I need convert this java program for php, I don't know java cipher.init method's third parameters SecureRandom ,So I use my php Des program to encrypt a string ,but I got a different result with java Des.

Here is my Java DES:

public static String encode(String srcStr) {
    if (srcStr == null)
        return null;
    String dst = null;
    byte[] result = encrypt2(srcStr.getBytes(), "h43au76U");
    if (result == null)
        return null;
    System.out.println(result);
    dst = byte2HexStr(result, result.length);
    return dst;
    }

 private static final char[] mChars = "0123456789ABCDEF".toCharArray();


 public static String byte2HexStr(byte[] b, int iLen) {
        if (b == null)
            return null;
        StringBuilder sb = new StringBuilder();
        for (int n = 0; n < iLen; n++) {
            sb.append(mChars[(b[n] & 0xff) >> 4]);
            sb.append(mChars[b[n] & 0xf]);
        }
        return sb.toString().trim().toUpperCase(Locale.US);
        }



 private static byte[] encrypt2(byte[] datasource, String password) {
        byte[] is;
        try {
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8"));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            javax.crypto.SecretKey securekey
            = keyFactory.generateSecret(desKey);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(1, securekey, random);
            is = cipher.doFinal(datasource);
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
        return is;
        }

And this is my php des:

function encrypt($input,$key,$iv=0){
    $size = mcrypt_get_block_size(MCRYPT_DES,MCRYPT_MODE_CBC); //3DES加密将MCRYPT_DES改为MCRYPT_3DES
    $input =pkcs5_pad($input, $size); //如果采用PaddingPKCS7,请更换成PaddingPKCS7方法。
    $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
    @mcrypt_generic_init($td, $key,$iv);
    $data = mcrypt_generic($td, $input);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
//    return $data;
   return strtoupper(bin2hex($data));
}

I got a different result, why? And I don't know if SecureRandom is a iv ?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Ice Wilder
  • 941
  • 1
  • 7
  • 7
  • DES is no longer considered secure and should not be used, use AES instead–if you are interested in security. It is best not to use mcrypt, it is abandonware, has not been updated in years and does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding that can't even be used with binary data. mcrypt had many outstanding [bugs](https://sourceforge.net/p/mcrypt/bugs/) dating back to 2003. Instead consider using [defuse](https://github.com/defuse/php-encryption), it is being maintained and is correct. – zaph Jun 20 '16 at 12:53

2 Answers2

2

Always use a fully qualified Cipher string. Cipher.getInstance("DES"); may result in different ciphers depending on the default security provider. It most likely results in "DES/ECB/PKCS5Padding", but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs.

What you need to do in PHP to achieve compatibility with Java is to use ECB mode instead of CBC mode and apply PKCS#5 padding (same as PKCS#7 padding). This answer shows an implementation of that padding. You just have to use the correct block size which is 8 for DES.


Never use ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme.

The IV must be unpredictable (read: random). Don't use a static IV, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. The IV is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption.

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
0
public static function encryptDes($data, $key)
{
     $paddedData = static::pad($data);
     $opts = OPENSSL_ZERO_PADDING | OPENSSL_RAW_DATA;
     return strtoupper(bin2hex(openssl_encrypt($paddedData, 'DES-ECB', $key, $opts)));
}

public static function decryptDes($data, $key)
{
    $data = hex2bin($data);
    $opts = OPENSSL_ZERO_PADDING | OPENSSL_RAW_DATA;
    return static::unpad(openssl_decrypt($data, 'DES-ECB', $key, $opts));
}

private static function pad($text)
{
    $blockSize = 8;
    $length = strlen($text);
    $pad = $blockSize - ($length % $blockSize);
    return str_pad($text, $length + $pad, chr($pad));
}

private static function unpad($text)
{
    $length = ord($text[strlen($text) - 1]);
    return substr($text, 0, -$length);
}
Xavier-Lam
  • 404
  • 4
  • 6