PHP等效于Java Triple DES加密/解密 [英] PHP Equivalent for Java Triple DES encryption/decryption

查看:193
本文介绍了PHP等效于Java Triple DES加密/解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用PHP mcrypt函数解密由Java Triple DES函数加密的密钥,但没有运气。在下面找到java代码

Am trying to decrypt a key encrypted by Java Triple DES function using PHP mcrypt function but with no luck. Find below the java code

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函数相当于上面的decryptText Java函数。我发现难以生成由加密的Java代码生成的确切IV值,这是解密所必需的。

I want to write a PHP function equivalent to the decryptText Java function above. am finding difficulty in generating the exact IV value generated by the Java code for encryption, which is required for the decryption.

推荐答案

这是你的Java代码的PHP等价物(我已经从 2006年9月20日07:56 复制了PKCS#5-padding: //php.net/manual/en/ref.mcrypt.php\"rel =noreferrer> mcrypt 参考

This is the PHP equivalent of your Java code (I have copied the PKCS#5-padding from the comment 20-Sep-2006 07:56 of The mcrypt reference)

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);
}

但是你应该注意一些问题:

But there are some problems you should be aware of:


  • 在Java代码中,您调用 String.getBytes()而不指示编码。如果明文包含非ASCII字符(如变音符号),则会使您的代码不可移植,因为Java使用系统默认字符集。如果你可以改变,我当然会这样做。我建议你双方都使用utf-8(Java和PHP)。

  • 你已经对密码进行了硬编码,并将IV用作密钥。我绝不是一个加密专家,但对我来说它只是感觉不对,可能会造成巨大的安全漏洞。

  • 创建一个随机的IV并在开始时或在消息结束。由于IV的大小是AFAIK等于你的密码的块大小,你只需从开头或结尾删除那么多字节,并且很容易将IV与消息分开。

  • As对于密钥,最好使用某种密钥派生方法生成一个正确的密钥来自人工生成密码的大小。

  • In your Java code you call String.getBytes() without indicating an encoding. This makes your code non portable if your clear text contains non ASCII-characters such as umlauts, because Java uses the system-default character set. If you can change that I certainly would do so. I recommend you to use utf-8 on both sides (Java and PHP).
  • You have hard coded the cipher-key and use the IV as "key". I'm by no means a crypto-expert but to me it just feels wrong and may open a huge security leak.
  • Create a random IV and just concatenate it at the start or at the end of your message. Since the size of the IV is AFAIK equal to the block-size of your cipher you just remove that much bytes from the start or end and have easily separated the IV from the message.
  • As for the key, it's best to use some kind of key derivation method to generate a key with the right size from a "human generated" password.

当然,如果您必须满足某些要求,则无法更改方法。

Of course, if you have to fulfil some given requirements you can't change your method.

这篇关于PHP等效于Java Triple DES加密/解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆