将PHP加密代码转换为Java显示错误?

时间:2019-01-04 08:15:45

标签: java encryption

我正在创建一个调用第三方API的应用程序,他们提供了PHP代码,而我们需要的是Java代码。

PHP代码如下:

4

现在我将上述代码更改为java:

function encryptIt( $string ) {
$key = 'qJB0rGtIn5UB1xG03efyCp';
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($string, 'aes-256-cbc', $key, 0, $iv);
return base64_encode($encrypted . '::' . $iv);
}

实际上,我在加密技术上并不擅长,因此PHP代码创建了IV代码,但是在互联网上搜索后,我试图如上所述创建IV代码,

但是我得到的错误是:

private static String openssl_encrypt(String data, String strKey, String strIv) throws Exception {
        SecureRandom randomSecureRandom = new SecureRandom();
        Base64 base64 = new Base64();
        Cipher ciper = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] ivv = new byte[ciper.getBlockSize()];
        randomSecureRandom.nextBytes(ivv);
        SecretKeySpec key = new SecretKeySpec(strKey.getBytes(), "AES");
        IvParameterSpec iv = new IvParameterSpec(ivv, 0, ciper.getBlockSize());

        // Encrypt
        ciper.init(Cipher.ENCRYPT_MODE, key, iv);
        byte[] encryptedCiperBytes = ciper.doFinal(data.getBytes());

        String s = new String(base64.encode(encryptedCiperBytes));
        System.out.println("Ciper : " + s);
        return s;
    }

请帮助我解决这个问题

已更新:

我将代码更新为:

java.security.InvalidKeyException: Invalid AES key length: 22 bytes
    at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:509)
    at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1067)
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1038)
    at javax.crypto.Cipher.init(Cipher.java:1393)
    at javax.crypto.Cipher.init(Cipher.java:1327)

还是我得到的错误是:

  

java.security.InvalidKeyException:密钥大小非法

我的API提供程序说那就是关​​键!

1 个答案:

答案 0 :(得分:3)

就像命运多{的mcrypt一样,openssl_encrypt允许使用大小错误的密钥。它不会拒绝此类密钥,而只是用零值字节(PHP中的"\0")填充密钥的其余部分。几乎所有高级语言的库都完全违反了任何良好的加密惯例。

这很可能是由于两个原因:

  • C,通常期望键的指针,其大小是预先确定的(因此-256命令中的openssl)。
  • PHP具有动态变量类型,使用户期望函数接受任何类型的 crap 变量类型或状态。

因此,要复制有缺陷的PHP代码,您必须将密钥填充为零字节(直到数组长度为32个字节)。在Java中,如今通常使用可怕的Arrays.copyOf执行此操作(因为它也右填充了零字节)。

请注意,IV当然仍将确保您的加密结果永远不匹配。相反,请尝试使用Java解密并使用相同的方案进行加密,以确保IV在最终代码中保持随机。


键绝不是字符串。密钥由位或(最好是)对存储在安全存储器中某处的密钥的引用组成。但是,密码是字符串,因此确实应该首选使用PKBDF2。

当然,要使用PBKDF2,需要:

  1. 需要在您的PHP代码中执行相同的操作,并且
  2. 确保您使用最新的Java环境(对于安全环境特别推荐),或者在Java运行时环境中安装无限管辖权策略文件。