1

これを短くするために、gzencode(または他の非テキストデータ)の結果をmcrypt_encrypt関数に渡すときに既知の問題がありますか?

詳細:

基本的に、プレーンテキストに対して暗号化/復号化が機能するという問題がありますが、圧縮データを暗号化関数に渡してから復号化して解凍すると、解凍中にエラーが発生します。

したがって、PHPでは、gzencode()の結果を暗号化関数に渡します。次に、WebサービスのWebページに結果を表示するためにbase64エンコードします。次に、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(encrypt(gzencode($ plain_text)));

そしてこれはJavaで

unzipPrint(decrypt(decodeBase64(data)));

解凍フェーズ中に、「java.util.zip.ZipException:オーバーサブスクライブされた動的ビット長ツリー」という恐ろしいものが表示されます。

繰り返しますが、両端で圧縮/解凍の手順をスキップすると、すべて問題ありません。そして、両端で暗号化をスキップすると、圧縮/解凍は正常に機能します。

編集:奇妙なことに、圧縮されたデータの結果のバイト配列をバイトごとにチェックした後(base64のデコードと復号化の後)、値が1だけずれている(元のPHPバイト配列と比較して)SINGLEバイトが見つかりました。これはバイト番号14(Javaではインデックス13)で、値は111ではなく110でした。これがどのように当てはまるのかまったくわかりません。

したがって、その1バイトを110から111に変更すると、GZIPOutputStreamを使用してデータを正常に解凍できます。

だから私は何が悪いのかは知っていますが、理由はわかりません。

編集2:これは解決されました-> Owlsteadによるコメントのおかげで、私はIV値を再確認し、phpとjavaコードの間にわずかな不一致があることを発見しました。これがどのようにして結果の復号化されたデータにわずか1バイトの違いをもたらすことができるのか私にはわかりません。

それは私のIVの0x12の代わりに単一の0x13で1日無駄になりました。

4

1 に答える 1

2

IVをチェックする必要があります。これは、ZIPヘッダーを保持する暗号文の最初のブロックのみを変更する可能性があるためです。

(質問を閉じるために、あなたがそれを解決してくれてうれしいです、あなたが問題を解決する日はいつでも私の意見では無駄ではありません:))

于 2012-04-23T00:18:00.230 に答える