【问题标题】:PHP AES-256-CBC encrypted data is different from JAVA AES/CBC/PKCS5PADDINGPHP AES-256-CBC加密数据不同于JAVA AES/CBC/PKCS5PADDING
【发布时间】:2022-11-16 23:06:45
【问题描述】:

我有一个完美运行的 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;
    }

我尝试使用下面的代码在 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);
        }

但显示不同的结果。我错过了什么。

(StackOverflow 中提供了相同类型的问题,但指出了我的问题)

【问题讨论】:

  • $key = substr($key, 0, 32) 这应该是 $key = substr($key, 0, 24) 吗?
  • 也试过..但加密值不同

标签: java php encryption aes


【解决方案1】:

存在以下问题:

  • 在 PHP 代码中,密钥当前以十六进制编码返回。相反,它必须作为字节字符串返回。为此,必须将hash() 中的第三个参数从false 切换为true
  • 在 Java 代码中使用了 192 位密钥,即 AES-192。因此,在 PHP 代码中必须应用 "AES-192-CBC"(而不是 "AES-256-CBC")。
  • PHP 代码中的 utf8_encode() 调用将被删除,因为这会损坏密钥。

通过这些更改,两个代码提供相同的密文。

安全:
使用 SHA256 作为密钥派生是不安全的。而是应用专用算法,如 Argon2 或 PBKDF2。此外,使用密钥(或其一部分)作为 IV 是不安全的,因为它会导致密钥/IV 对的重用。相反,应为每次加密应用随机生成的 IV。

【讨论】:

  • 其实我已经结束了这个解决方案,它是有效的。
【解决方案2】:
我正在尝试在 PHP 中实现相同的解密逻辑,但我做不到,你能指导我吗?
public static String decryptUsingAESGCM256(byte[] cipherText, byte[] aesKey256) throws Exception
{
    private static final int AES_KEY_SIZE = 256;
    private static final int GCM_TAG_LENGTH = 16;
private static final String IV="886643115275";
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(AES_KEY_SIZE);
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    SecretKeySpec keySpec = new SecretKeySpec(aesKey256, "AES");
    GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV.getBytes());
    cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
    byte[] decryptedText = cipher.doFinal(java.util.Base64.getDecoder().decode(cipherText));
    System.out.println("decryptUsingAESGCM256= "+new String(decryptedText));
    return new String(decryptedText);
}

【讨论】:

    猜你喜欢
    • 2014-01-13
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    相关资源
    最近更新 更多