3

我正在开发一个接口,该接口将加密的字节流(可能是一个非常的字节流)作为输入,生成或多或少相同格式的输出。

输入格式是这样的:

{N byte envelope}
    - encryption key IDs &c.
{X byte encrypted body}

输出格式相同。

这是通常的用例(当然是大量伪代码):

Message incomingMessage = new Message (inputStream);

ProcessingResults results = process (incomingMessage);

MessageEnvelope messageEnvelope = new MessageEnvelope ();
// set message encryption options &c. ...

Message outgoingMessage = new Message ();
outgoingMessage.setEnvelope (messageEnvelope);

writeProcessingResults (results, message);

message.writeToOutput (outputStream);

对我来说,使用同一个对象来封装这种行为似乎是有意义的,但我对如何去做这件事有点茫然。一次加载所有加密的正文是不切实际的;我需要能够对其进行流式传输(因此,我将使用某种输入流过滤器对其进行解密),但同时我需要能够写出该对象的新实例。什么是使这项工作的好方法?内部应该是什么Message样子?

4

6 回答 6

1

我不会创建一个类来处理输入和输出——一个类,一个责任。我想要两个过滤器流,一个用于输入/解密,一个用于输出/加密:

InputStream decrypted = new DecryptingStream(inputStream, decryptionParameters);
...
OutputStream encrypted = new EncryptingStream(outputSream, encryptionOptions);

他们可能有类似惰性初始化机制的东西,在第一次调用之前读取信封read()/在第一次调用之前写入信封write()。您还可以在过滤器实现中使用 Message 或 MessageEnvelope 等类,但它们可能会保留包保护的非 API 类。

该处理对仅在流上工作的解密/加密一无所知。在处理流式处理输入和输出期间,您还可以同时使用两个流进行输入和输出。

于 2009-01-20T20:42:46.833 回答
0

您应该查看有关支持流加密的不同分组密码模式的Wikipedia 文章。不同的加密算法可能支持其中的一个子集。

缓冲流将允许您在循环中读取、加密/解密和写入。

演示 ZipInputStream 和 ZipOutputStream 的示例可以为您如何解决此问题提供一些指导。见例子

于 2009-01-07T22:31:58.463 回答
0

我同意Arne的观点,数据处理器不应该知道加密,它只需要读取消息的解密正文并写出结果,流过滤器应该负责加密。但是,由于这在逻辑上是对同一条信息(一条消息)进行操作,因此我认为它们应该封装在一个处理消息格式的类中,尽管加密/解密流确实与此无关。

这是我对结构的想法,稍微翻转架构,并将 Message 类移到加密流之外:

class Message {
  InputStream input;
  Envelope envelope;

  public Message(InputStream input) {
    assert input != null;
    this.input = input;
  }

  public Message(Envelope envelope) {
    assert envelope != null;
    this.envelope = envelope;
  }

  public Envelope getEnvelope() {
    if (envelope == null && input != null) {
      // Read envelope from beginning of stream
      envelope = new Envelope(input);
    }
    return envelope
  }

  public InputStream read() {
    assert input != null

    // Initialise the decryption stream
    return new DecryptingStream(input, getEnvelope().getEncryptionParameters());
  }

  public OutputStream write(OutputStream output) {
    // Write envelope header to output stream
    getEnvelope().write(output);

    // Initialise the encryption
    return new EncryptingStream(output, getEnvelope().getEncryptionParameters());
  }
}

现在您可以通过为输入和输出创建一条新消息来使用它:OutputStream 输出;// 这是发送消息的流 Message inputMessage = new Message(input); 消息 outputMessage = new Message(inputMessage.getEnvelope()); 过程(inputMessage.read(),outputMessage.write(输出));

现在 process 方法只需要从输入中读取需要的数据块,并将结果写入输出:

public void process(InputStream input, OutputStream output) {
  byte[] buffer = new byte[1024];
  int read;
  while ((read = input.read(buffer) > 0) {
    // Process buffer, writing to output as you go.
  }
}

现在这一切都在同步进行,您不需要任何额外的线程。您也可以提前中止,而不必处理整个消息(例如,如果输出流已关闭)。

于 2009-01-21T19:33:25.803 回答
0

What you need is using Cipher Streams (CipherInputStream). Here is an example of how to use it.

于 2009-01-18T21:35:45.043 回答
0

如果您需要同时读取和写入,则必须使用线程(不同的线程读取和写入)或异步 I/O(java.nio 包)。使用来自不同线程的输入和输出流不是问题。

如果你想在java中制作一个流API,你通常应该提供InputStream用于读取和OutputStream用于写入。通过这种方式,可以将它们传递给其他 API,以便您可以链接事物,从而使流一直作为流传输。

输入示例:

Message message = new Message(inputStream);
results = process(message.getInputStream());

输出示例:

Message message = new Message(outputStream);
writeContent(message.getOutputStream());

消息需要使用执行所需加密和解密的类来包装给定的流。

请注意,同时读取多条消息或同时写入多条消息也需要协议的支持。您需要正确同步。

于 2009-01-02T17:19:24.057 回答
0

你可以在任意位置分割身体吗?

如果是这样,我将有两个线程,输入线程和输出线程,并有一个输出线程监控的并发字符串队列。就像是:

ConcurrentLinkedQueue<String> outputQueue = new ConcurrentLinkedQueue<String>();
...

private void readInput(Stream stream) {
    String str;
    while ((str = stream.readLine()) != null) {
       outputQueue.put(processStream(str));
    }
}

private String processStream(String input) {
    // do something
    return output;
}

private void writeOutput(Stream out) {
    while (true) {
        while (outputQueue.peek() == null) {
            sleep(100);
        }

        String msg = outputQueue.poll();
        out.write(msg);
    }
}

注意:这肯定不会按原样工作。只是一个设计建议。欢迎有人对此进行编辑。

于 2008-12-12T13:49:33.670 回答