PHP中的简单AES加密,用Java解密

时间:2017-01-10 06:25:53

标签: java php encryption base64 aes

我想实现一种简单但安全的方法,将一些信息从PHP脚本发送到Java客户端。我已经在这里看了几个实现,但到目前为止都没有工作,我现在感到沮丧。我用了一点编辑的最后一个就是这个:

PHP:

function enc3($plaintext) {

$length = 16;
$key = openssl_random_pseudo_bytes($length);

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
                             $plaintext, MCRYPT_MODE_CBC, $iv);

echo base64_encode($ciphertext);
echo "\n".base64_encode($iv);
echo "\n".base64_encode($key);
}
enc3("test");

爪哇:

public static byte[] decrypt(byte[] key, byte[] initVector, byte[] encryptedValue) {

    try {

        IvParameterSpec iv = new IvParameterSpec(initVector);
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

        byte[] original = cipher.doFinal(encryptedValue);

        return original;
    } catch (Exception ex) {
        Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
}
...
byte[] encpryted = Base64.getDecoder().decode(rd.readLine());
byte[] iv = Base64.getDecoder().decode(rd.readLine());
byte[] key = Base64.getDecoder().decode(rd.readLine());

byte[] output = decrypt(key, iv, encpryted);

我得到了一个:

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes

关键只是用于调试,当然,我会在它工作时将其删除,并将其存储在客户端中。不知道最好的方法是什么,不知何故,我想通过隐藏方式将它隐藏起来,服务器也知道如何生成它。但我想它会在内存中可读,不是吗?

1 个答案:

答案 0 :(得分:3)

AES是一种分组密码,只能在16字节的块上正常工作。当你的密文长度不能被16整除时,它会导致IllegalBlockSizeException。

您可以在PHP中轻松实现AES / CBC密码的PKCS5填充,这基本上是一种标准化的方法,如何将明文输入填充为块大小的精确倍数:

function pkcs5_pad($text) {
    $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $pad = $size - (strlen($text) % $size);
    return $text . str_repeat(chr($pad), $pad);
}

然后更新加密函数以使用填充:

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
pkcs5_pad($plaintext), MCRYPT_MODE_CBC, $iv);

Java已经实现了对PKCS5的支持,只需更新AES密码初始化:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");