简体   繁体   English

PHP AES-256-CBC 加密数据不同于 JAVA AES/CBC/PKCS5PADDING

[英]PHP AES-256-CBC encrypted data is different from JAVA AES/CBC/PKCS5PADDING

I have a java code working perfectly我有一个完美运行的java代码

public static String encrypt(String message, String sercretKey)
    {
        String base64EncryptedString = "";
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] digestOfPassword = md.digest(sercretKey.getBytes("utf-8"));
            byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            byte[] iv = Arrays.copyOf(digestOfPassword, 16);
            SecretKey key = new SecretKeySpec(keyBytes, "AES");
            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, ivParameterSpec);
            byte[] plainTextBytes = message.getBytes("utf-8");
            byte[] buf = cipher.doFinal(plainTextBytes);
            byte[] base64Bytes = Base64.getEncoder().encode(buf);
            base64EncryptedString = new String(base64Bytes);
        return base64EncryptedString;
    }

I have tried using below code to recreate this above code in PHP我尝试使用下面的代码在 PHP 中重新创建上面的代码

function encryptTest($sSecretKey,$sValue)
        {
            $key = hash('sha256', $sSecretKey,false);
            $key = utf8_encode($key);
            $key = substr($key, 0, 24);
            $iv = substr($key, 0, 16);
            $data = $sValue;
            $outEnc = openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
            
            return base64_encode($outEnc);
        }

But showing different results.但显示出不同的结果。 What I have missed.我错过了什么。

(Same types of questions are available in StackOverflow, but pointing my issues) (StackOverflow 中提供了相同类型的问题,但指出了我的问题)

There are the following issues:有以下问题:

  • In the PHP code, the key is currently returned hex encoded.在 PHP 代码中,密钥当前以十六进制编码返回。 Instead, it must be returned as bytes string.相反,它必须作为字节字符串返回。 To do this, the third parameter in hash() must be switched from false to true .为此,必须将hash()中的第三个参数从false切换为true
  • In the Java code a 192 bits key is used, ie AES-192.在 Java 代码中使用了 192 位密钥,即 AES-192。 Accordingly, in the PHP code "AES-192-CBC" must be applied (and not "AES-256-CBC" ).因此,必须在 PHP 代码中应用"AES-192-CBC" (而不是"AES-256-CBC" )。
  • The utf8_encode() call in the PHP code is to be removed, as this corrupts the key. PHP 代码中的utf8_encode()调用将被删除,因为这会损坏密钥。

With these changes, both codes provide the same ciphertext.通过这些更改,两种代码都提供了相同的密文。

Security:安全:
Using SHA256 as key derivation is insecure.使用 SHA256 作为密钥派生是不安全的。 Instead apply a dedicated algorithm like Argon2 or PBKDF2.而是应用 Argon2 或 PBKDF2 等专用算法。 Also, using the key (or a part of it) as IV is insecure as it results in the reuse of key/IV pairs.此外,将密钥(或其中的一部分)用作 IV 是不安全的,因为它会导致密钥/IV 对的重复使用。 Instead, a randomly generated IV should be applied for each encryption.相反,应该为每个加密应用随机生成的 IV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM