【问题标题】:Porting Rijndael decryption from PHP to Java with salt使用 salt 将 Rijndael 解密从 PHP 移植到 Java
【发布时间】:2015-08-19 01:22:39
【问题描述】:

我在将带有解密示例的 php 代码转换为 java 时遇到问题。 这是php代码:

function decrypt($encrypted, $password, $salt='2#g+XK^Sc3"4ABXbvwF8CPD%en%;9,c(') {
    // Build a 256-bit $key which is a SHA256 hash of $salt and $password.
    $key = hash('SHA256', $salt . $password, true);
    // Retrieve $iv which is the first 22 characters plus ==, base64_decoded.
    $iv = base64_decode(substr($encrypted, 0, 22) . '==');
    // Remove $iv from $encrypted.
    $encrypted = substr($encrypted, 22);
    // Decrypt the data.  rtrim won't corrupt the data because the last 32 characters are the md5 hash; thus any \0 character has to be padding.
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv), "\0\4");
    // Retrieve $hash which is the last 32 characters of $decrypted.
    $hash = substr($decrypted, -32);
    // Remove the last 32 characters from $decrypted.
    $decrypted = substr($decrypted, 0, -32);
    // Integrity check.  If this fails, either the data is corrupted, or the password/salt was incorrect.
    if (md5($decrypted) != $hash) return false;
    // Yay!
    return $decrypted;
}

这是我所做的 java 代码。但这不起作用。

private static String password = "AxkbK2jZ5PMaeNZWfn8XRLUWF2waGwH2EkAXxBDU6aZ";
private static String salt = "2#g+XK^Sc3\"4ABXbvwF8CPD%en%;9,c(";
private static String text = "Fm+Zfufqe3DjRQtWcYdw9g9oXriDjrAkRrBLhEfu7fCtT4BzD0gw7D+8KxrcbbgJm26peTUWHU2k4YJ4KqCSRQN3NPzuXwlJ4mC4444Edg3Q==";

public String decrypt(String pass, String encr) {

    try {
        int i = 0;

        String key = hash();
        byte[] iv = Base64.decodeBase64(text.substring(0, 22) + "==");

        Cipher cipher = Cipher.getInstance("DES");
        SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "DES");
        IvParameterSpec ivSpec = new IvParameterSpec(salt.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        ByteArrayInputStream fis = new ByteArrayInputStream(iv);
        CipherInputStream cis = new CipherInputStream(fis, cipher);
        ByteArrayOutputStream fos = new ByteArrayOutputStream();
        // decrypting
        byte[] b = new byte[8];
        while ((i = cis.read(b)) != -1) {
            fos.write(b, 0, i);
        }
        fos.flush();
        fos.close();
        cis.close();
        fis.close();

        return fos.toString();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

private String hash() {
    StringBuffer sb = new StringBuffer();

    try {
        MessageDigest md = null;
        md = MessageDigest.getInstance("SHA-256");
        md.update((password + salt).getBytes());
        byte byteData[] = md.digest();

        for (int i = 0; i < byteData.length; i++) {
            sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } finally {
        return sb.toString();
    }

}

【问题讨论】:

    标签: java php encryption aes porting


    【解决方案1】:

    您的代码存在一些问题。

    • MCRYPT_RIJNDAEL_128 是 AES 而不是 DES。这是两种完全不同的算法。
    • Cipher.getInstance("DES"); 可能默认为 Cipher.getInstance("DES/ECB/PKCS5Padding");,具体取决于您的默认 JCE 提供程序
    • 您没有使用您生成的key,而是直接使用不是密钥的密码。此外,您的密钥不应采用十六进制编码,因为您在 PHP 中也使用原始密钥。
    • 盐不是静脉输液。
    • 您没有从恢复的明文末尾切掉哈希来验证它。

    在您的原始 PHP 代码中有些令人畏惧的地方:

    • 如今,单遍 SHA-256 还不够好。您的密码必须非常长(50 多个随机字符)才能保证安全。使用高成本或迭代的 PBKDF2、bcrypt、scrypt,以便能够使用更短的密码。
    • 似乎 IV 实际上作为 Base64 编码的字符串附加到 Base64 编码的密文中,没有填充字节。这是非常不寻常的,可能会导致误解。
    • 使用 MCrypt 的零填充而不是使用 PKCS#7 padding
    • 检查明文的完整性很好,但您应该检查密文的完整性,因为encrypt-then-MAC 通常更好。 MD5也不够好。您应该至少使用 HMAC-SHA256。

    【讨论】:

    • 另外,md5($decrypted) != $hash 这里有很多问题。
    • @Scott md5($decrypted) != $hash 有点好,因为它至少是某种类似于 MAC-then-encrypt 的完整性检查。加密然后(实际)MAC 会更好。问题当然是它根本没有在 Java 代码中复制。
    • 我不反对,我只是想将其添加为附录。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 2011-10-26
    相关资源
    最近更新 更多