java - 将gzencoded数据传递给mcrypt_encrypt,解密后无法解压

标签 java php encryption gzip block-cipher

简单来说,将 gzencode(或其他非文本数据)的结果传递给 mcrypt_encrypt 函数时是否存在已知问题?

详细信息:

基本上,我遇到的问题是加密/解密适用于纯文本,但如果我将压缩数据传递给加密函数,然后解密并解压缩,则解压缩时会出现错误。

因此,在 PHP 中,我将 gzencode() 的结果传递给加密函数。然后我进行 Base64 编码以在 Web 服务网页上显示结果。然后在 Java 应用程序中,我使用 GZIPInputStream 解码 base64、解密和解压缩。我在最后一步中遇到错误。

但是如果我跳过压缩步骤(只需将纯文本传递给加密函数),一切都会正常。如果我跳过加密而只进行压缩,一切也都可以正常工作。因此,如果我不将它们结合起来,这些函数似乎在 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(加密(gzencode($plain_text)));

Java 中的这个

unzipPrint(解密(decodeBase64(数据)));

在解压缩阶段,我收到了可怕的消息:“java.util.zip.ZipException:超额订阅的动态位长度树”。

同样,如果我跳过两端的压缩/解压缩步骤,一切都很好。如果我在两端跳过加密,那么压缩/解压缩就可以正常工作。

编辑: 好吧,很奇怪,但是在逐字节检查压缩数据的结果字节数组(在解码 Base64 和解密之后)后,我发现一个关闭的单个字节(与原始数据相比) PHP 字节数组)的值是 1。它是字节号 14(Java 中的索引 13),它的值是 110,而不是 111。我完全不知道怎么会出现这种情况。

因此,如果我将该单个字节从 110 更改为 111,那么我可以成功使用 GZIPOutputStream 来解压缩数据。

所以我知道出了什么问题,但不知道为什么。

编辑2:已解决 ->感谢 Owlstead 的评论,我仔细检查了 IV 值,发现 php 和 java 代码之间存在细微差异。我不知道这如何导致解密数据结果只有一个字节的差异。

那一天浪费在我的 IV 中的一个 0x13 而不是 0x12 上。

最佳答案

您应该检查 IV,因为它可能只会更改包含 ZIP header 的第一个密文 block 。

(结束问题,很高兴您解决了问题,在我看来,解决问题的任何一天都不是浪费:))

关于java - 将gzencoded数据传递给mcrypt_encrypt,解密后无法解压,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10268832/

相关文章:

java - 为什么接口(interface)中的所有字段都是隐式静态和最终的?

java - Swing 中的输入验证

java - 在HashMap中设置键类型,如何?

php - 在 Laravel 5.2 中将表单发送的参数传递给 Controller

java - CTR 模式下的 AES 解密 (Java)

security - 如何从多个密码生成公共(public)哈希?

java - 在哪里可以找到 Java API 代码

php - 我的本地计算机上的 MYsql 错误。但它在现场工作正常

php - php中的空查询结果

python - 填充不正确。 AES Python 加密