001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.decryption_verification.cleartext_signatures;
006
007import java.io.ByteArrayOutputStream;
008import java.io.File;
009import java.io.IOException;
010import java.io.InputStream;
011import java.io.OutputStream;
012
013/**
014 * Since the {@link CleartextSignatureProcessor} needs to read the whole data twice in order to verify signatures,
015 * a strategy for how to cache the read data is required.
016 * Otherwise, large data kept in memory could cause {@link OutOfMemoryError OutOfMemoryErrors} or other issues.
017 *
018 * This is an Interface that describes a strategy to deal with the fact that detached signatures require multiple passes
019 * to do verification.
020 *
021 * This interface can be used to write the signed data stream out via {@link #getMessageOutputStream()} and later
022 * get access to the data again via {@link #getMessageInputStream()}.
023 * Thereby the detail where the data is being stored (memory, file, etc.) can be abstracted away.
024 */
025public interface MultiPassStrategy {
026
027    /**
028     * Provide an {@link OutputStream} into which the signed data can be read into.
029     *
030     * @return output stream
031     * @throws IOException io error
032     */
033    OutputStream getMessageOutputStream() throws IOException;
034
035    /**
036     * Provide an {@link InputStream} which contains the data that was previously written away in
037     * {@link #getMessageOutputStream()}.
038     *
039     * As there may be multiple signatures that need to be processed, each call of this method MUST return
040     * a new {@link InputStream}.
041     *
042     * @return input stream
043     * @throws IOException io error
044     */
045    InputStream getMessageInputStream() throws IOException;
046
047    /**
048     * Write the message content out to a file and re-read it to verify signatures.
049     * This strategy is best suited for larger messages (e.g. plaintext signed files) which might not fit into memory.
050     * After the message has been processed completely, the messages content are available at the provided file.
051     *
052     * @param file target file
053     * @return strategy
054     */
055    static MultiPassStrategy writeMessageToFile(File file) {
056        return new WriteToFileMultiPassStrategy(file);
057    }
058
059    /**
060     * Read the message content into memory.
061     * This strategy is best suited for small messages which fit into memory.
062     * After the message has been processed completely, the message content can be accessed by calling
063     * {@link ByteArrayOutputStream#toByteArray()} on {@link #getMessageOutputStream()}.
064     *
065     * @return strategy
066     */
067    static InMemoryMultiPassStrategy keepMessageInMemory() {
068        return new InMemoryMultiPassStrategy();
069    }
070}