Эквивалент PHP для Java Triple DES шифрование / дешифрование - PullRequest
6 голосов
/ 16 декабря 2011

Я пытаюсь расшифровать ключ, зашифрованный функцией Java Triple DES, используя функцию PHP mcrypt, но безуспешно.Найдите ниже код Java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class Encrypt3DES {

     private byte[] key;
     private byte[] initializationVector;

    public Encrypt3DES(){

    }

    public String encryptText(String plainText, String key) throws Exception{

         //----  Use specified 3DES key and IV from other source --------------
        byte[] plaintext = plainText.getBytes();
        byte[] myIV = key.getBytes();
        byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62,
        (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF,
        (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67,
        (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95};

        Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        SecretKeySpec    myKey = new SecretKeySpec(tdesKeyData, "DESede");
        IvParameterSpec ivspec = new IvParameterSpec(myIV);
           c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
        byte[] cipherText = c3des.doFinal(plaintext);
        sun.misc.BASE64Encoder obj64=new sun.misc.BASE64Encoder();
        return obj64.encode(cipherText);

    }

    public String decryptText(String encryptText, String key) throws Exception{


        byte[] initializationVector = key.getBytes();
        byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62,
        (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF,
        (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67,
        (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95};


          byte[] encData = new sun.misc.BASE64Decoder().decodeBuffer(encryptText);
          Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
          SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede");
          IvParameterSpec ivspec = new IvParameterSpec(initializationVector);
          decipher.init(Cipher.DECRYPT_MODE, myKey, ivspec);
          byte[] plainText = decipher.doFinal(encData);
          return new String(plainText);

    }
}

Я хочу написать PHP-функцию, эквивалентную Java-функции decryptText выше.Я испытываю трудности при создании точного значения IV, сгенерированного кодом Java для шифрования, которое требуется для расшифровки.

Ответы [ 2 ]

9 голосов
/ 16 декабря 2011

Это PHP-эквивалент вашего Java-кода (я скопировал отступ PKCS # 5 из комментария 20-Sep-2006 07:56 из mcrypt ссылка )

function encryptText($plainText, $key) {
    $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2"
        . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06"
        . "\x67\x7A\x82\x94\x16\x32\x95";

    $padded = pkcs5_pad($plainText,
        mcrypt_get_block_size("tripledes", "cbc"));

    $encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key);

    return base64_encode($encText);
}

function decryptText($encryptText, $key) {
    $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2"
        . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06"
        . "\x67\x7A\x82\x94\x16\x32\x95";

    $cipherText = base64_decode($encryptText);

    $res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key);

    $resUnpadded = pkcs5_unpad($res);

    return $resUnpadded;
}


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

function pkcs5_unpad($text)
{
    $pad = ord($text{strlen($text)-1});
    if ($pad > strlen($text)) return false;
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
    return substr($text, 0, -1 * $pad);
}

Но есть некоторые проблемы, о которых вы должны знать:

  • В вашем коде Java вы звоните String.getBytes() без указания кодировки. Это делает ваш код непереносимым, если ваш открытый текст содержит не ASCII-символы, такие как umlauts, потому что Java использует набор символов по умолчанию системы. Если вы можете изменить это, я бы так и сделал. Я рекомендую вам использовать utf-8 с обеих сторон (Java и PHP).
  • Вы жестко закодировали ключ шифрования и используете IV как «ключ». Я ни в коем случае не криптоэксперт, но для меня это просто неправильно и может открыть огромную утечку безопасности.
  • Создайте случайный IV и просто объедините его в начале или в конце вашего сообщения. Поскольку размер IV равен AFAIK и равен размеру блока вашего шифра, вы просто удаляете столько байтов из начала или конца и легко отделяете IV от сообщения.
  • Что касается ключа, то для генерации ключа правильного размера из "сгенерированного человеком" пароля лучше всего использовать какой-нибудь метод получения ключа .

Конечно, если вам нужно выполнить некоторые данные требования, вы не можете изменить свой метод.

0 голосов
/ 08 октября 2013

Ответ почти хороший! Просто поменяйте местами $keyData и $key в

$encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key);

и

$res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key);

в противном случае вы всегда будете использовать один и тот же ключ 3DES. И лучше переименовать $keyData в $iv.

В любом случае, большое спасибо за пример Java и перевод Php-Java.

...