001/*
002 * Copyright 2018 Paul Schaub.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.pgpainless.decryption_verification;
017
018import javax.annotation.Nonnull;
019import java.io.IOException;
020import java.io.InputStream;
021import java.util.HashSet;
022import java.util.Iterator;
023import java.util.Set;
024
025import org.bouncycastle.openpgp.PGPException;
026import org.bouncycastle.openpgp.PGPPublicKeyRing;
027import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
028import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
029import org.pgpainless.key.OpenPgpV4Fingerprint;
030import org.pgpainless.key.protection.SecretKeyRingProtector;
031
032public class DecryptionBuilder implements DecryptionBuilderInterface {
033
034    private InputStream inputStream;
035    private PGPSecretKeyRingCollection decryptionKeys;
036    private SecretKeyRingProtector decryptionKeyDecryptor;
037    private Set<PGPPublicKeyRing> verificationKeys = new HashSet<>();
038    private MissingPublicKeyCallback missingPublicKeyCallback = null;
039
040    @Override
041    public DecryptWith onInputStream(InputStream inputStream) {
042        this.inputStream = inputStream;
043        return new DecryptWithImpl();
044    }
045
046    class DecryptWithImpl implements DecryptWith {
047
048        @Override
049        public VerifyWith decryptWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRingCollection secretKeyRings) {
050            DecryptionBuilder.this.decryptionKeys = secretKeyRings;
051            DecryptionBuilder.this.decryptionKeyDecryptor = decryptor;
052            return new VerifyWithImpl();
053        }
054
055        @Override
056        public VerifyWith doNotDecrypt() {
057            DecryptionBuilder.this.decryptionKeys = null;
058            DecryptionBuilder.this.decryptionKeyDecryptor = null;
059            return new VerifyWithImpl();
060        }
061    }
062
063    class VerifyWithImpl implements VerifyWith {
064
065        @Override
066        public HandleMissingPublicKeys verifyWith(@Nonnull PGPPublicKeyRingCollection publicKeyRingCollection) {
067            Set<PGPPublicKeyRing> publicKeyRings = new HashSet<>();
068            for (Iterator<PGPPublicKeyRing> i = publicKeyRingCollection.getKeyRings(); i.hasNext(); ) {
069                publicKeyRings.add(i.next());
070            }
071            return verifyWith(publicKeyRings);
072        }
073
074        @Override
075        public HandleMissingPublicKeys verifyWith(@Nonnull Set<OpenPgpV4Fingerprint> trustedKeyIds,
076                                                  @Nonnull PGPPublicKeyRingCollection publicKeyRingCollection) {
077            Set<PGPPublicKeyRing> publicKeyRings = new HashSet<>();
078            for (Iterator<PGPPublicKeyRing> i = publicKeyRingCollection.getKeyRings(); i.hasNext(); ) {
079                PGPPublicKeyRing p = i.next();
080                OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(p);
081                if (trustedKeyIds.contains(fingerprint)) {
082                    publicKeyRings.add(p);
083                }
084            }
085            return verifyWith(publicKeyRings);
086        }
087
088        @Override
089        public HandleMissingPublicKeys verifyWith(@Nonnull Set<PGPPublicKeyRing> publicKeyRings) {
090            DecryptionBuilder.this.verificationKeys = publicKeyRings;
091            return new HandleMissingPublicKeysImpl();
092        }
093
094        @Override
095        public Build doNotVerify() {
096            DecryptionBuilder.this.verificationKeys = null;
097            return new BuildImpl();
098        }
099    }
100
101    class HandleMissingPublicKeysImpl implements HandleMissingPublicKeys {
102
103        @Override
104        public Build handleMissingPublicKeysWith(@Nonnull MissingPublicKeyCallback callback) {
105            DecryptionBuilder.this.missingPublicKeyCallback = callback;
106            return new BuildImpl();
107        }
108
109        @Override
110        public Build ignoreMissingPublicKeys() {
111            DecryptionBuilder.this.missingPublicKeyCallback = null;
112            return new BuildImpl();
113        }
114    }
115
116    class BuildImpl implements Build {
117
118        @Override
119        public DecryptionStream build() throws IOException, PGPException {
120            return DecryptionStreamFactory.create(inputStream,
121                    decryptionKeys, decryptionKeyDecryptor, verificationKeys, missingPublicKeyCallback);
122        }
123    }
124}