001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.sop;
006
007import java.io.ByteArrayInputStream;
008import java.io.ByteArrayOutputStream;
009import java.io.IOException;
010import java.io.InputStream;
011import java.io.OutputStream;
012
013import org.bouncycastle.bcpg.ArmoredOutputStream;
014import org.bouncycastle.openpgp.PGPSignature;
015import org.bouncycastle.openpgp.PGPSignatureList;
016import org.bouncycastle.util.io.Streams;
017import org.pgpainless.exception.WrongConsumingMethodException;
018import org.pgpainless.decryption_verification.cleartext_signatures.ClearsignedMessageUtil;
019import org.pgpainless.util.ArmoredOutputStreamFactory;
020import sop.ReadyWithResult;
021import sop.Signatures;
022import sop.exception.SOPGPException;
023import sop.operation.DetachInbandSignatureAndMessage;
024
025public class DetachInbandSignatureAndMessageImpl implements DetachInbandSignatureAndMessage {
026
027    private boolean armor = true;
028
029    @Override
030    public DetachInbandSignatureAndMessage noArmor() {
031        this.armor = false;
032        return this;
033    }
034
035    @Override
036    public ReadyWithResult<Signatures> message(InputStream messageInputStream) {
037
038        return new ReadyWithResult<Signatures>() {
039
040            private final ByteArrayOutputStream sigOut = new ByteArrayOutputStream();
041
042            @Override
043            public Signatures writeTo(OutputStream messageOutputStream)
044                    throws SOPGPException.NoSignature, IOException {
045
046                PGPSignatureList signatures;
047                try {
048                    signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(messageInputStream, messageOutputStream);
049                } catch (WrongConsumingMethodException e) {
050                    throw new IOException(e);
051                }
052
053                if (armor) {
054                    ArmoredOutputStream armorOut = ArmoredOutputStreamFactory.get(sigOut);
055                    for (PGPSignature signature : signatures) {
056                        signature.encode(armorOut);
057                    }
058                    armorOut.close();
059                } else {
060                    for (PGPSignature signature : signatures) {
061                        signature.encode(sigOut);
062                    }
063                }
064
065                return new Signatures() {
066                    @Override
067                    public void writeTo(OutputStream signatureOutputStream) throws IOException {
068                        Streams.pipeAll(new ByteArrayInputStream(sigOut.toByteArray()), signatureOutputStream);
069                    }
070                };
071            }
072        };
073    }
074}