通过网络发送的hashmap的完整性

问题描述 投票:0回答:2

我的servlet加密并发送HashMap及其MD5哈希。 然后客户端接收它们,并将MD5与从HashMap中运行的MD5进行比较。

这有时会起作用但不会起作用,例如,如果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);

它不起作用 - 两个MD5哈希值不同。 (唯一不同的是关键'计数'而不是'国家')

程序发送类似的HashMaps,它们都包含只有字符串或整数的键/值,这是我第一次看到像这样的奇怪的东西。

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;
    }

使用相同类型的inputStream解密,以相同的方式计算出hashmap的md5,然后使用以下方法进行比较:

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

我不明白为什么这对于发送我尝试过的所有HashMaps都有效,但现在使用这个计数键不起作用。我已经测试了在客户端和servlet上比较HashMap内部的各个键/值对,它们是相同的,但是当比较整个HashMap的两个MD5时,它们不匹配。

另外,我不确定我是否在流链的正确部分使用缓冲流?

security stream hashmap equals digest
2个回答
0
投票

无法保证两个Java副本将产生与对象序列化完全相同的字节 - 只是它们将生成一个语义上等效的对象。

您可以通过在键和值上运行摘要来制作类似这样的工作,但您需要决定如何散列Object值。

如果您可以渲染到XML并将其规范化,那么您可以从那里开始。

您可以查看各种Web服务标准的安全性,而不是自己动手。

建议:将哈希映射复制到具有顺序的TreeMap中,并尝试使用相同的技巧。


0
投票

可能只是从一个JVM发送带有键值对的JSON,在接收器端,您可以反序列化并构造另一个HashMap

© www.soinside.com 2019 - 2024. All rights reserved.