在 PHP 上删除长键,在 Java 上不删除

DESede long key on PHP, not in Java

我正在尝试将 Java 的 DESede 解密转换为 PHP 的版本。但是,对于相同的输入,PHP 无法提供相同的输出。

Java:

public class ThreeDES {

    private KeySpec             keySpec;
    private SecretKeyFactory    keyFactory;
    private Cipher              cipher;
    public ThreeDES( String encryptionScheme, String encryptionKey )
                throws EncryptionException {
        try {
            byte[] keyAsBytes = encryptionKey.getBytes("UTF-8");
            keySpec = new DESedeKeySpec(keyAsBytes);
            keyFactory = SecretKeyFactory.getInstance(encryptionScheme);
            cipher = Cipher.getInstance(encryptionScheme);
        } catch (InvalidKeyException e)
        {
            throw new EncryptionException( e );
        }
        catch (UnsupportedEncodingException e)
        {
            throw new EncryptionException( e );
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new EncryptionException( e );
        }
        catch (NoSuchPaddingException e)
        {
            throw new EncryptionException( e );
        }
    }

    public String decrypt( String encryptedString ) throws EncryptionException {
        try {
            SecretKey key = keyFactory.generateSecret( keySpec );
            cipher.init( Cipher.DECRYPT_MODE, key );
            BASE64Decoder base64decoder = new BASE64Decoder();
            byte[] cleartext = base64decoder.decodeBuffer(encryptedString);
            byte[] ciphertext = cipher.doFinal(cleartext);
            return bytes2String( ciphertext );
        } 
        catch (Exception e)
        {
            throw new EncryptionException( e );
        }
    }

    private static String bytes2String( byte[] bytes )
    {
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < bytes.length; i++)
        {
            stringBuffer.append( (char) bytes[i] );
        }
        return stringBuffer.toString();
    }
}

PHP:

function decrypt($key, $data) {
    $mcrypt_module = mcrypt_module_open(MCRYPT_TRIPLEDES, '', MCRYPT_MODE_ECB, '');
    $mcrypt_iv     = mcrypt_create_iv(mcrypt_enc_get_iv_size($mcrypt_module), MCRYPT_RAND);
    $decrypted     = mcrypt_decrypt(MCRYPT_TRIPLEDES, $key, base64_encode($data), MCRYPT_MODE_ECB, $mcrypt_iv);
    mcrypt_module_close($mcrypt_module);
    return pkcs5_unpad($decrypted);
}

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

给定以下输入参数,PHP 无法提供相同的输出:

$key = 'ASDFasdf12348983jklasdfJ2Jaf8';
$encrypted_data = 'cPap7+JIPS4=';

应解密为:

coRef=3

Java的测试代码如下:

try {
    String encryptedStr = encrypted_data; // same value as PHP's $encrypted_data
    String decryptedString = "";
    ThreeDES desedeEncrypter = new ThreeDES("DSEede", key); // same value as PHP's $key
    decryptedString = desedeEncrypter.decrypt(encryptedStr);
    System.out.println(decryptedString);
} catch (ThreeDES.EncryptionException e) {
    e.printStackTrace();
}

输出:coRef=3。但是,以下 PHP 代码会引发有关密钥长度的警告。

echo decrypt($key, $encrypted_data);

Key of size 29 not supported by this algorithm. Only keys of size 24 supported in...

如何修改我的代码以使用超过 24 个字符的密钥?

嗯,这很奇怪,

Triple Des 只接受 24 个字节作为键

Each DES key is nominally stored or transmitted as 8 bytes, each of odd parity,[12] so a key bundle requires 24 bytes for option 1, 16 for option 2, or 8 for option 3.

所以我认为问题出在here

DESedeKeySpec 对象:

/**
     * Uses the first 24 bytes in <code>key</code> as the DES-EDE key.
     * <p>
     * The bytes that constitute the DES-EDE key are those between
     * <code>key[0]</code> and <code>key[23]</code> inclusive
     *
     * @param key the buffer with the DES-EDE key material.
     * @exception InvalidKeyException if the given key material is shorter
     * than 24 bytes.
*/

所以我认为 DESedeKeySpec 是将长度为 29 的密钥修剪为 24 以符合 tribledes 要求。

编辑 另一个重要说明 mcrypt_* 扩展已被弃用。

This function has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.