【问题标题】:Simple decrypt/encrypt for java and PHPjava和PHP的简单解密/加密
【发布时间】:2017-12-20 00:22:10
【问题描述】:

以前,我有一个工作系统来加密 PHP 中的数据并使用 JAVA 解密它。这是PHP代码:

function encrypt($message, $initialVector, $secretKey) {

return base64_encode(
  mcrypt_encrypt(
    MCRYPT_RIJNDAEL_128,
    md5($secretKey),
    $message,
    MCRYPT_MODE_CFB,
    $initialVector
    )
  );
}

function decrypt($message, $initialVector, $secretKey) {
  $decoded = base64_decode($message);
  return mcrypt_decrypt(
    MCRYPT_RIJNDAEL_128,
    md5($secretKey),
    $decoded,
    MCRYPT_MODE_CFB,
    $initialVector
  );
}

还有java代码

 public String decrypt(String encryptedData, String initialVectorString, String secretKey) {
    String decryptedData = null;
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).getBytes(), "AES");
        IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
        byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode(encryptedData.getBytes());
        byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
        decryptedData = new String(decryptedByteArray, "UTF8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return decryptedData;

}

但是,我最近从 PHP 5.x 切换到 7.1,现在收到以下消息:

“函数 mcrypt_encrypt() 已弃用”

所以看起来 mcrypt 不再是一个好的选择了。我用谷歌搜索了很多,但大多数例子仍然使用 mcrypt。唯一的其他好的选择是指像 RNCryptor 或 defuse 这样的工具,但没有任何工作示例。是否有一些适用于 PHP 和 JAVA 的简单工作示例?我需要能够将数据解密为其原始形式,因为我需要使用它执行某些任务。

提前致谢

【问题讨论】:

  • 所以你有两个解密函数?干什么用的?
  • @Oliver 正如 OP 解释的那样,一个是 PHP,一个是 Java
  • MD5 不是安全密钥派生函数,NIST 建议是 PBKDF2,有时也称为 Rfc2898DeriveBytes。推导函数应该使用大约 100 毫秒的 CPU 时间以确保安全。

标签: java php encryption cryptography


【解决方案1】:

这看起来像此链接中的代码:http://php.net/manual/de/function.mcrypt-encrypt.php#119395。不过不管怎样,我觉得应该换成 openssl_encrypt()。

这是你的功能的一个端口(当然没有 md5)。

<?php

function encrypt_new($data, $iv, $key, $method)
{
    return base64_encode(openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
}

function decrypt_new($data, $iv, $key, $method)
{
    return openssl_decrypt(base64_decode($data), $method, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
}

$data = "plain text";
$method = 'AES-128-CFB8'; // AES/CFB8/NoPadding
$ivSize = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($ivSize);
$password = 'default-secret-salt';
$key = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);

$encrypted = encrypt_new($data, $iv, $key, $method);
echo $encrypted. "\n";
$decrypted = decrypt_new($encrypted, $iv, $key, $method);
echo $decrypted. "\n"; // plain text

【讨论】:

  • 另一个问题是IV,每个加密都是随机的,这很好,但是如何在加密和解密函数之间共享它。一种好方法是在加密代码中生成随机IV,并在加密数据前加上is,这样解密函数就会有IV可用。
  • @zaph 密码哈希也可以用 1 生成。 $key = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);或 2. $key = hash_pbkdf2("sha256", $password, $iv, $iterations = 1000, 20);什么会更好,更安全? IV 可以连接为前缀,true。
  • 是的,password_hash 很好。关键是尽可能使用约 100 毫秒的 CPU 时间。所以任何一种方法都很好。
  • @zaph 好的,谢谢!我刚刚修复了答案中的代码。
  • 感谢您的代码,它适用于我的 PHP 项目。我现在正试图找到一些能够解密数据的 Java 代码。
【解决方案2】:

您是否考虑过从mcrypt_encrypt 迁移到openssl_encrypt。请记住,openssl 不会在给定相同的明文和密钥的情况下输出相同的密文。

另外,删除md5 是个好主意,因为它非常快速且易于暴力破解。

【讨论】:

  • 请详细说明“给定相同的明文和密钥,openssl 不会输出相同的密文”。
  • 对不起,这不是解释,这只是一个虚构的陈述。问题是,如果两者都使用相同的加密算法、模式和适用的 IV,为什么它们会有所不同?提示,答案在我前面省略的内容中。还同意 MD5 不应用于密钥派生,但这引出了应该使用什么的问题。
  • @踢球当然是mcrypt只支持非标准的空填充,这就是我对冲问的原因。
  • 你是对的。评论已被删除以避免误导信息。
猜你喜欢
  • 2014-06-28
  • 1970-01-01
  • 2018-01-20
  • 2013-03-16
  • 2011-04-29
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
相关资源
最近更新 更多