0

私のサーブレットは、HashMapとそのMD5ハッシュを暗号化して送信します。
次に、クライアントはそれらを受け取り、MD5をHashMapから作成したものと比較します。

これは時々機能しますが、他の場合は機能しません。たとえば、HashMapが次の場合です。

    HashMap<String, Object> result = new HashMap<String, Object>();
    result.put("error", 0);
    result.put("coun", 0);

それはうまくいく

ただし、次の場合:

    HashMap<String, Object> result = new HashMap<String, Object>();
    result.put("error", 0);
    result.put("count", 0);

それは機能しません-2つのMD5ハッシュは異なります。(違いは「カウン」ではなく「カウント」のキーです)

プログラムは同様のHashMapを送信しますが、すべて文字列または整数のみのキー/値が含まれています。このような奇妙なものを見たのはこれが初めてです。

HashMap/MD5が実際に送信される方法の詳細-

サーバーは次のことを行います。

    //Work out MD5 of the HashMap result (convert it to bytes with objectOutputStream, and MD5 the bytes)
    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
    ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
    ObjectOutputStream out = new ObjectOutputStream(bos) ;
    out.writeObject(result);
    out.close();
    byte[] md5 = messageDigest.digest(bos.toByteArray();

    //Encrypt the httpURLConnection response stream, and send the HashMap result and the md5 over the stream
    Cipher symmetricCipher = Cipher.getInstance("DES");
    symmetricCipher.init(Cipher.ENCRYPT_MODE, symmetricKey);
    CipherOutputStream cipherOutput = new CipherOutputStream(response.getOutputStream(), symmetricCipher);
    BufferedOutputStream bufferedOutput = new BufferedOutputStream(cipherOutput);
    ObjectOutputStream objectOutput = new ObjectOutputStream(out);
    objectOutput.writeObject(result);
    objectOutput.writeObject(md5);
    objectOutput.flush();

クライアントは次のことを行います。

    //Decrypt the httpURLConnection response stream
    Cipher symmetricCipher = Cipher.getInstance("DES");
    symmetricCipher.init(Cipher.DECRYPT_MODE, symmetricKey);
    CipherInputStream cipherInput = new CipherInputStream(httpInput, symmetricCipher);
    BufferedInputStream bufferedInput = new BufferedInputStream(cipherInput);           

    //read HashMap and MD5
    ObjectInputStream objectInput = new ObjectInputStream(in);
    HashMap<String, Object> result = (HashMap<String, Object>) objectInput.readObject();
    byte[] hash1 = (byte[]) objectInput.readObject();

    //workout hash of the Hashmap received.
    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
    ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
    ObjectOutputStream out = new ObjectOutputStream(bos) ;
    out.writeObject(result);
    out.close();
    byte[] hash2 = messageDigest.digest(bos.toByteArray();

    // Compare two hashes
    if (!Arrays.equals(hash1, hash2)) {
        System.out.println("Result received does not match hash, stopping list operation");
        return;
    }

同じタイプのinputStreamsを使用して復号化し、同じ方法でハッシュマップのmd5を計算してから、次を使用して比較します。

    if (!Arrays.equals(hash1, hash2)) {
            System.out.println("Result received does not match hash, stopping get operation");
            return;
    }

試したすべてのHashMapを送信するためにこれが機能した理由はわかりませんが、このカウントキーでは機能しません。クライアントとサーブレットのHashMap内の個々のキーと値のペアを比較することをテストしましたが、それらは同じですが、HashMap全体の2つのMD5を比較すると一致しません。

また、ストリームチェーンの正しい部分でバッファリングされたストリームを使用しているかどうかわかりませんか?

4

2 に答える 2

0

Javaの2つのコピーがオブジェクトのシリアル化とまったく同じバイトを生成するという保証はありません。意味的に同等のオブジェクトを生成するという保証だけです。

キーと値に対してダイジェストを実行することで、このような機能を実現できますが、Object値をハッシュする方法を決定する必要があります。

XMLにレンダリングし、それを正規化できれば、そこから進むことができます。

独自の標準を作成する代わりに、セキュリティに関するさまざまなWebサービス標準を調べることができます。

提案:ハッシュマップを順序のあるTreeMapにコピーし、それを使って同じトリックを試してください。

于 2011-04-10T19:07:35.473 に答える
0

1 つの JVM からキーと値のペアを含む JSON を送信するだけで、受信側で別の HashMap をデシリアライズして構築できます。

于 2019-04-29T18:49:40.583 に答える