【问题标题】:AES encryption on Java side - decryption on PHP side and selecting a single keyJava 端的 AES 加密 - PHP 端的解密并选择单个密钥
【发布时间】:2014-07-30 22:08:06
【问题描述】:

我正在使用 AES,我想选择一个密钥,我可以在 Java 端使用它来加密字符串,我在 php 端对相同的密钥进行硬编码,如果字符串匹配,我会解密字符串我通过身份验证进入.

以下是我的 Java 代码:

public class AESencrp {

     private static final String ALGO = "AES";
    private static final byte[] keyValue = 
        new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };

public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
}

}

这是我在 PHP 中使用的函数:

function fnDecrypt()
{
 // echo $_POST['key'];
 $sValue = $_POST['key']; 
 $sSecretKey = "TheBestSecretKey";
    return rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256, 
            $sSecretKey, 
            base64_decode($sValue), 
            MCRYPT_MODE_CBC,
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256,
                    MCRYPT_MODE_CBC
                ), 
                MCRYPT_RAND
            )
        ), "\0"
    );
}

但是,我似乎总是在 php 端得到不同的解密文本,我觉得问题出在密钥上,而由于我正在对其进行硬编码,所以这种行为不应该发生,有什么提示吗?

【问题讨论】:

  • MCRYPT_RIJNDAEL_256 不是 AES。试试MCRYPT_RIJNDAEL_128
  • 好的,让我试试。这是否意味着我也必须考虑 128 位密钥?或者我可以使用 256 键?

标签: java php android aes


【解决方案1】:

您似乎做错了几件事,我将按顺序进行检查:

在 Java 中创建 Cipher 的实例时始终指定 "Algorithm/Mode/Padding"。否则,您永远不知道将使用哪种模式和填充,如果您想在不同平台和编程语言之间传递加密数据,这尤其成问题,因为它们可能具有不同的默认值。 (例如,Java 的默认填充是 PKCS1Padding,而 PHP 的 mcrypt_decrypt() 需要 ZeroBytePadding
所以初始化ALGO

/* ZeroBytePadding should better not be used in practice */
private static final String ALGO = "AES/CBC/ZeroBytePadding";

正如Roland Jansen 已经提到的,是Java AES 的128 位版本。所以在 PHP 中使用:

MCRYPT_RIJNDAEL_128

第三,您必须始终为每次加密指定不同的随机IV(不得保密)。然后您必须使用相同的 IV 进行解密。因此,您还必须在 java 中生成一个 IV,然后将其传递给 PHP 并在那里进行解密。

byte[] iv = new byte[16]; // must be 16 bytes for AES-128
new SecureRandom().nextBytes(iv); // generate random bytes
IvParameterSpec ivSpec = new IvParameterSpec(iv);

/* create instance of Cipher and keys */

cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

到目前为止,您还在 PHP 中生成了一个随机的 IV,这显然不会导致所需的明文。所以在php中做如下解密:

 $key = "{insert Java encryption key here}";
 $iv; = "{insert Java encryption IV here}";

 mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC, $iv);

如果在这些修复后仍然无法正常工作,则问题可能是密文或密钥/IV 字符串的编码。尝试确保您向 PHP 传递的数据与您从 Java 中的 cipher.doFinal 收到的数据完全相同。

希望能帮到你。

【讨论】:

    【解决方案2】:

    此链接http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php 有一个教程可以帮助您。 如果您想更改 SecretKey。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-20
      相关资源
      最近更新 更多