如何模拟加密代码

时间:2018-03-15 18:07:26

标签: java mocking mockito

我使用testng作为我的测试框架,mockito for mocks。

我所拥有的是:我正在尝试为将要测试的一个类(数据包处理器)编写测试。分组处理器有两种称为发送和接收的方法,其中接收方法从源输入流接收一个特定网络协议的数据包,然后解析它的报头,返回实际的数据包内容。 send方法获取有效负载,创建数据包,并通过网络发送。

问题是这些数据包是可选的压缩,加密并为它们计算mac。我的问题一般是,加密,mac计算和压缩是由从一些抽象类派生的单独对象完成的,所以我需要模拟它们。但是,如何使解密器的模拟工作正常,以便返回可以验证的有意义的数据?

在调用decrypt方法时,我似乎无法创建一个虚拟数据包并返回一个好数据包。这是因为数据包是可变长度的,并且长度本身是加密的,因此被测对象需要做的是,读取第一个密文块,解密,从结果字节数组中读取长度,然后读取其余的密文。数据包,解密和合并以创建完整数据包。然后,如果足够长,每个数据包将有两个解密调用,我可能不仅需要生成一个虚假的可验证数据包,还要以某种方式拆分它,并做一些奇特的事情。我不太清楚如何处理这种情况。

我目前有针对没有加密,完整性保护和压缩的情况下的书面测试和数据包发送方/接收方。

这是接收方法的代码:

public byte[] receive(final DataInput in) throws SshProtocolException, SshIoException {
    assert in != null;
    try {
        int length = 0, paddingLength = 0;
        /* Read packet length, ignoring timeouts and returning null on eof. */
        while (true) {
            try {
                length = in.readInt();
                break;
            } catch (SocketTimeoutException e) {} catch (EOFException e) {
                return null;
            }
        }
        logger.debug("receiving next packet of length {}", length);
        /*
         * Minimum packet length is 16 bytes, the length field does not count itself, so
         * 12 bytes + length field size.
         */
        if (Integer.compareUnsigned(length, 12) < 0) {
            logger.error("malformed packet: packet is too small, must be at least 16 bytes");
            throw new SshProtocolException("malformet packet: packet is too small, must be at least 16 bytes");
        }
        /* Max packet size is 35000 bytes with length field. */
        if (Integer.compareUnsigned(length, 34996) > 0) {
            logger.error("malformed packet: packet too large");
            throw new SshProtocolException("malformed packet: packet too large");
        }
        /* Must be a multiple of cipher block size or 8, whichever is larger. */
        if (Integer.remainderUnsigned(length + 4, 8) != 0) {
            logger.error("malformed packet: packet must be aligned to the cipher block size");
            throw new SshProtocolException("malformed packet: packet must be aligned to the cipher block size");
        }
        /* Read packet. */
        byte[] packet = new byte[length];
        in.readFully(packet);
        paddingLength = packet[0] & 0xFF;
        if (paddingLength < 4) {
            logger.error("malformed packet: padding length must be at least 4 bytes");
            throw new SshProtocolException("malformed packet: padding length must be at least 4 bytes");
        }
        int payloadLength = length - paddingLength - 1;
        if (Integer.compareUnsigned(payloadLength, 32768) > 0) {
            logger.error("malformed packet: payload too large");
            throw new SshProtocolException("malformed packet: payload too large");
        }
        byte[] payload = new byte[payloadLength];
        System.arraycopy(packet, 1, payload, 0, payloadLength);
        logger.debug("padding length: {}, payload length: {}", paddingLength, payloadLength);
        return payload;
    } catch (EOFException e) {
        throw new SshProtocolException("malformed packet received, end of stream before the end of packet");
    } catch (IOException e) {
        throw new SshIoException("i/o error while receiving the ssh packet: " + e.getMessage(), e);
    }
}

这是测试成功的示例测试:

@Test
public void receivingPacketReturnsPayloadWhenPacketValid() throws SshException, IOException {
    byte[] packet = generatePacket(12, 7, "test".getBytes(), 7);
    DataInputStream in = new DataInputStream(new ByteArrayInputStream(packet));
    SshPacketProcessor proc = new SshPacketProcessor(random, inputHolder, outputHolder);
    byte[] payload = proc.receive(in);
    assertEquals(new String(payload), "test");
}

generatePacket()方法使用提供的数据生成测试数据包,并允许在需要时生成无效数据包。

0 个答案:

没有答案