【问题标题】:PHP vs JAVA AES encryption, what is the difference?PHP vs JAVA AES 加密,有什么区别?
【发布时间】:2014-10-31 16:59:54
【问题描述】:

我在这里遇到了一些奇怪的问题......

我有以下两个脚本:

首先,一个 PHP 脚本(我正在使用 http://writecodeonline.com/php/ 进行测试)

$key = '[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[nJ7rO@T^PwgT!NVY*Hri@($p4luBM)ugVvbnAnWL@xGK*jBP3s$g#-XTH{e3@X*0StJ';
$string = 'Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ';

//
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key), $string, MCRYPT_MODE_ECB));

$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, md5($key), base64_decode($encrypted), MCRYPT_MODE_ECB), "\0");


echo $encrypted . "<br>";
echo $decrypted;

第二,一个Java类,

import java.io.*;
import java.net.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.*;
import javax.crypto.spec.*;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;


public class Main {

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        String pw = "[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[nJ7rO@T^PwgT!NVY*Hri@($p4luBM)ugVvbnAnWL@xGK*jBP3s$g#-XTH{e3@X*0StJ";
        String str = encode("Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ", pw);
        System.out.println(str);
        System.out.println(decode(str, pw));
    }

    public static String encode(String s, String p) throws Exception
    {
        String cleartext = padRight(s, s.length()+(16-(s.length()%16)));
        String key = DigestUtils.md5Hex(p);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(cleartext.getBytes());
        return Base64.encodeBase64String(encrypted);
    }

    public static String decode(String encrypted, String p) throws Exception
    {
        byte[] bts = Base64.decodeBase64(encrypted);


        String key = DigestUtils.md5Hex(p);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);



        byte[] decrypted = cipher.doFinal(bts);

        return new String(decrypted).replaceAll("\0", "");
    }

    public static String padRight(String s, int n) {
        while (s.length() < n)
        {
            s+="\0";
        }
        return s;
    }

}

发生了一些非常奇怪的事情。当我测试 PHP 脚本时,我得到:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWg==

作为加密代码。

然而,当我测试 java 代码时,我得到:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWsdyQJ3DP2jBsJcLh2n2wv0=

如果您仔细观察,您会发现(不知何故)java 文本更长!但是,奇怪的是,这两个文本在“+EAH”之前是完全相同的,这是它们分歧的时候。我觉得这很奇怪——为什么?

因为我已经在许多其他字符串上测试了这段代码,从 lorum ipsum 到单词“Testing”,没有任何错误。 (到目前为止)我发现导致这种情况的唯一方法是多次重复一个简短的单词,用空格分隔。

我对此非常担心,因为我不知道还有什么其他方法可以触发这种奇怪的行为。所以这引出了我的问题……以 davy jone 的储物柜的名义,这是什么?

【问题讨论】:

    标签: java php cryptography aes


    【解决方案1】:

    我不是加密专家,但这可能是填充问题。您可以尝试以下方法。

    PHP
    如下设置内边距:

    $blockSize = mcrypt_get_block_size(MCRYPT RIJNDAEIL_128, MCRYPT_MODE_ECB);
    $padding = $blockSize - (strlen($string) % $blockSize);
    $string .= str_repeat(chr($padding), $padding);
    

    这将使用 PKCS#5 填充,而不是 PHP 的空填充。

    Java
    更改以下行:

    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    

    到:

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    

    很遗憾,我没有可以比较结果的 Java 环境,但我希望它会有所帮助。

    【讨论】:

    • 非常感谢!这就像一个魅力!我想提醒未来的观众,我必须将 MCRYPT_RIJNDAEL_256 更改为 MCRYPT RIJNDAEIL_128
    • 很高兴能帮上忙。我也更正了我的答案,我的意思是从一开始就放 128。早上有点早,应该是困了。 :)
    • 没问题!我自己很累——我打算在我的评论中写 MCRYPT_RIJNDAEIL_128 而不是 MCRYPT RIJNDAEIL_128
    【解决方案2】:

    代码中有常量名称拼写错误,正确的代码是:

    $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $padding   = $blockSize - (strlen($tokenRaw) % $blockSize);
    $tokenRaw .= str_repeat(chr($padding), $padding);
    
    $encode    = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $tokenRaw, MCRYPT_MODE_ECB));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-02
      • 2014-12-10
      • 2016-02-21
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      • 2011-05-23
      相关资源
      最近更新 更多