【问题标题】:PHP Equivalent for Java Triple DES encryption/decryption用于 Java 三重 DES 加密/解密的 PHP 等效项
【发布时间】:2012-01-21 18:03:19
【问题描述】:

我正在尝试使用 PHP mcrypt 函数解密由 Java Triple DES 函数加密的密钥,但没有运气。在下面找到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);

    }
}

我想写一个与上面decryptText Java 函数等效的PHP 函数。我发现难以生成由 Java 代码生成的用于加密的确切 IV 值,这是解密所必需的。

【问题讨论】:

标签: java php 3des tripledes


【解决方案1】:

这是您的 Java 代码的 PHP 等价物(我从 The mcrypt reference 的评论 20-Sep-2006 07:56 复制了 PKCS#5 填充)

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 字符(例如变音符号),这会使您的代码不可移植,因为 Java 使用系统默认字符集。如果你能改变这一点,我当然会这样做。我建议你在两边(Java 和 PHP)都使用 utf-8。
  • 您已对密码密钥进行硬编码并使用 IV 作为“密钥”。我绝不是加密专家,但对我来说感觉不对,可能会造成巨大的安全漏洞。
  • 创建一个随机 IV 并将其连接在消息的开头或结尾。由于 IV 的大小 AFAIK 等于密码的块大小,因此您只需从开头或结尾删除那么多字节,就可以轻松地将 IV 与消息分开。
  • 至于密钥,最好使用某种key derivation 方法从“人工生成”密码生成大小合适的密钥。

当然,如果你必须满足某些给定的要求,你就不能改变你的方法。

【讨论】:

  • 非常感谢 vstm。我会检查并恢复。
  • 我可以改变变量 $keyData 的值吗?
  • 您的代码有效,对我帮助很大!不介意就去借吧:)
【解决方案2】:

答案几乎是好的!只需将$keyData$key 倒转

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

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

否则您将始终使用相同的 3DES 密钥。并且最好将$keyData重命名为$iv

无论如何,非常感谢 Java 示例和 Php-Java 翻译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2015-06-22
    • 1970-01-01
    • 2014-02-26
    相关资源
    最近更新 更多