为了简短起见,将 gzencode(或其他非文本数据)的结果传递给 mcrypt_encrypt 函数时是否存在已知问题?
细节:
基本上我有一个问题,加密/解密适用于纯文本,但如果我将压缩数据传递给加密函数,然后解密和解压缩,我会得到错误解压缩。
所以在 PHP 中,我将 gzencode() 的结果传递给 encrypt 函数。然后我进行 base64 编码以在 Web 服务网页上显示结果。然后在一个 Java 应用程序中,我使用 GZIPInputStream 对 base64 进行解码、解密和解压缩。我在最后一步出现错误。
但是,如果我跳过压缩步骤(只需将纯文本传递给 encrypt 函数),一切正常。如果我跳过加密并只进行压缩,一切也都很好。因此,如果我不将它们结合起来,这些函数似乎在 PHP 和 Java 方面都可以正常工作。
public static function encrypt($str,$key,$iv) {
$str=Crypto2::pkcs5Pad($str,mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
$encrypted=mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,$str,MCRYPT_MODE_CBC,$iv);
return $encrypted;
}
public static function pkcs5Pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
$padded=$text . str_repeat(chr($pad), $pad);
return $padded;
}
Java函数:
public static byte[] decrypt(byte[] inputbuffer) throws Exception {
Key key = new SecretKeySpec(keybyte, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key, ivSpec);
c.getBlockSize();
System.out.println("Block size="+c.getBlockSize());
int outlen = c.getOutputSize(inputbuffer.length);
System.out.println("Output length will be:"+outlen);
byte[] result=c.doFinal(inputbuffer);
return result;
}
public static byte[] decodeBase64(String data) throws IOException{
BASE64Decoder decoder = new BASE64Decoder();
byte[] decodedBytes = decoder.decodeBuffer(data);
return decodedBytes;
}
public static void unzipPrint(byte[] data) throws Exception{
InputStream is=new GZIPInputStream(new ByteArrayInputStream(data));
int ch2;
while((ch2=is.read())!=-1) {
System.out.print((char)ch2);
}
}
因此,如果我在 PHP 中执行此操作: base64_encode(encrypt(gzencode($plain_text)));
这在Java中
解压缩打印(解密(decodeBase64(数据)));
在解压缩阶段,我得到了可怕的:“java.util.zip.ZipException:超额订阅动态位长度树”。
同样,如果我跳过两端的压缩/解压缩步骤,一切都很好。如果我在两端跳过加密,那么压缩/解压缩工作正常。
编辑:好吧,很奇怪,但是在逐字节检查压缩数据的结果字节数组之后(在解码 base64 和解密之后),我发现一个单字节(与原始 PHP 字节数组相比)的值为 1。它是字节数 14(Java 中的索引 13),它的值是 110 而不是 111。我完全不知道这是怎么回事。
因此,如果我将该单字节从 110 更改为 111,那么我可以成功地使用 GZIPOutputStream 来解压缩数据。
所以我知道出了什么问题,但不知道为什么。
编辑 2:这已解决->感谢 Owlstead 的评论,我仔细检查了 IV 值,发现 php 和 java 代码之间存在细微差异。我不知道这如何导致结果解密数据中只有一个字节的差异。
那是在我的 IV 中的单个 0x13 而不是 0x12 浪费了一天。