Java端的AES加密 - 在PHP端解密并选择单个密钥 [英] AES encryption on Java side - decryption on PHP side and selecting a single key

查看:152
本文介绍了Java端的AES加密 - 在PHP端解密并选择单个密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AES,我想找到一个可以在Java端加密字符串的密钥,我在php端硬编码相同的密钥并解密字符串如果字符串匹配我已经过身份验证。

I am using AES and I want to settle for a key which I can use on the Java side to encrypt a string, I hardcode the same key on php side and decrypt the string if the strings match I am authenticated to step inside.

以下是我在Java中的代码:

Following is my code in 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:

Here is the function I use in 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端获得不同的解密文本,我感觉问题是关键,虽然我很难编码,这种行为不应该发生,任何提示?

However it seems, that I always get different decrypted text on php side, I feel the issue is with the key, while as I am hard coding it, this behavior should not occur, any hints?

推荐答案

似乎有些事情你做错了,我会按顺序翻看这些:

There seem to be a few things you are doing wrong, I'll go over these in order:

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

因此初始化 ALGO

Always specify "Algorithm/Mode/Padding" when creating an instance of Cipher in Java. Otherwise you never know which mode and padding will be used, which is especially problematic if you want to pass encrypted data between different platforms and programming languages, since they will probably have different defaults. (for example Java's default padding is PKCS1Padding where as PHP's mcrypt_decrypt() requires ZeroBytePadding)
So initialize ALGO with:

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

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

As Roland Jansen has already mentioned, is the Java AES the 128-bit version. So use in PHP:

MCRYPT_RIJNDAEL_128

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

Third, you must always specify a different random IV for every encryption (must not be secret). You then must use the same IV for decryption. So you will also have to generate an IV in java that you then pass to PHP and use for decryption there.

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中进行以下解密:

As of now you also generate a random IV in PHP, which will obviously not lead to the desired plaintext. So do the following in php for decryption:

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

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

如果在这些修复后仍然无效,问题可能是编码密文 - 或密钥/ IV-Strings。尝试确保将完全相同的数据传递给PHP,然后用Java中的 cipher.doFinal 传递给它。

我希望,我可以帮助你。

I hope, I could help you.

这篇关于Java端的AES加密 - 在PHP端解密并选择单个密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆