001// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.decryption_verification;
006
007import java.io.IOException;
008import java.io.InputStream;
009import javax.annotation.Nonnull;
010
011import org.bouncycastle.util.io.Streams;
012
013/**
014 * Decryption Stream that handles updating and verification of detached signatures,
015 * as well as verification of integrity-protected input streams once the stream gets closed.
016 */
017public class DecryptionStream extends CloseForResultInputStream {
018
019    private final InputStream inputStream;
020    private final IntegrityProtectedInputStream integrityProtectedInputStream;
021    private final InputStream armorStream;
022
023    /**
024     * Create an input stream that handles decryption and - if necessary - integrity protection verification.
025     *
026     * @param wrapped underlying input stream
027     * @param resultBuilder builder for decryption metadata like algorithms, recipients etc.
028     * @param integrityProtectedInputStream in case of data encrypted using SEIP packet close this stream to check integrity
029     * @param armorStream armor stream to verify CRC checksums
030     */
031    DecryptionStream(@Nonnull InputStream wrapped,
032                     @Nonnull OpenPgpMetadata.Builder resultBuilder,
033                     IntegrityProtectedInputStream integrityProtectedInputStream,
034                     InputStream armorStream) {
035        super(resultBuilder);
036        this.inputStream = wrapped;
037        this.integrityProtectedInputStream = integrityProtectedInputStream;
038        this.armorStream = armorStream;
039    }
040
041    @Override
042    public void close() throws IOException {
043        if (armorStream != null) {
044            Streams.drain(armorStream);
045        }
046        inputStream.close();
047        if (integrityProtectedInputStream != null) {
048            integrityProtectedInputStream.close();
049        }
050        super.close();
051    }
052
053    @Override
054    public int read() throws IOException {
055        int r = inputStream.read();
056        return r;
057    }
058
059    @Override
060    public int read(@Nonnull byte[] bytes, int offset, int length) throws IOException {
061        int read = inputStream.read(bytes, offset, length);
062        return read;
063    }
064
065}