eu.mrbussy.security.crypto.pgp.PGPDecryptor.java Source code

Java tutorial

Introduction

Here is the source code for eu.mrbussy.security.crypto.pgp.PGPDecryptor.java

Source

/*
 * Java-Password-Store
 * Copyright (C) 2016  rudi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package eu.mrbussy.security.crypto.pgp;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPOnePassSignature;
import org.bouncycastle.openpgp.PGPOnePassSignatureList;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPUtil;

public class PGPDecryptor {

    private String privateKeyFilePath;
    private String password;

    private boolean isSigned;

    public boolean isSigned() {
        return isSigned;
    }

    public void setSigned(boolean isSigned) {
        this.isSigned = isSigned;
    }

    public String getSigningPublicKeyFilePath() {
        return signingPublicKeyFilePath;
    }

    public void setSigningPublicKeyFilePath(String signingPublicKeyFilePath) {
        this.signingPublicKeyFilePath = signingPublicKeyFilePath;
    }

    private String signingPublicKeyFilePath;

    public String getPrivateKeyFilePath() {
        return privateKeyFilePath;
    }

    public void setPrivateKeyFilePath(String privateKeyFilePath) {
        this.privateKeyFilePath = privateKeyFilePath;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void decryptFile(String inputFileNamePath, String outputFileNamePath) throws Exception {
        decryptFile(new File(inputFileNamePath), new File(outputFileNamePath));
    }

    public void decryptFile(File inputFile, File outputFile) throws Exception {
        decryptFile(new FileInputStream(inputFile), new FileOutputStream(outputFile));
    }

    public void decryptFile(InputStream in, OutputStream out) throws Exception {
        BufferedOutputStream bOut = new BufferedOutputStream(out);
        InputStream unc = decryptFile(in);
        int ch;
        while ((ch = unc.read()) >= 0) {
            bOut.write(ch);
        }
        bOut.close();
    }

    public InputStream decryptFile(InputStream in) throws Exception {
        InputStream is = null;
        byte[] bytes = null;
        InputStream keyIn = new FileInputStream(new File(privateKeyFilePath));
        char[] passwd = password.toCharArray();
        in = PGPUtil.getDecoderStream(in);

        PGPObjectFactory pgpF = new PGPObjectFactory(in);
        PGPEncryptedDataList enc;
        Object o = pgpF.nextObject();
        //
        // the first object might be a PGP marker packet.
        //
        if (o instanceof PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }

        //
        // find the secret key
        //
        Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        while (sKey == null && it.hasNext()) {
            pbe = it.next();
            sKey = PGPUtils.findPrivateKey(keyIn, pbe.getKeyID(), passwd);
        }

        if (sKey == null) {
            throw new IllegalArgumentException("secret key for message not found.");
        }

        InputStream clear = pbe.getDataStream(sKey, "BC");
        PGPObjectFactory plainFact = new PGPObjectFactory(clear);
        Object message = plainFact.nextObject();
        PGPObjectFactory pgpFact = null;
        if (message instanceof PGPCompressedData) {
            PGPCompressedData cData = (PGPCompressedData) message;
            pgpFact = new PGPObjectFactory(cData.getDataStream());
            message = pgpFact.nextObject();
        }

        PGPOnePassSignature ops = null;
        if (message instanceof PGPOnePassSignatureList) {
            if (isSigned) {
                PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) message;
                ops = p1.get(0);
                long keyId = ops.getKeyID();
                PGPPublicKey signerPublicKey = PGPUtils.readPublicKey(signingPublicKeyFilePath, keyId);
                ops.initVerify(signerPublicKey, "BC");
            }
            message = pgpFact.nextObject();
        }

        if (message instanceof PGPLiteralData) {
            PGPLiteralData ld = (PGPLiteralData) message;
            if (pbe.isIntegrityProtected()) {
                if (!pbe.verify()) {
                    throw new PGPException("message failed integrity check");
                }
            }
            is = ld.getInputStream();
            bytes = IOUtils.toByteArray(is);

            if (isSigned) {
                ops.update(bytes);
                PGPSignatureList p3 = (PGPSignatureList) pgpFact.nextObject();
                if (!ops.verify(p3.get(0))) {
                    throw new PGPException("Signature verification failed!");
                }
            }
        } else {
            throw new PGPException("message is not a simple encrypted file - type unknown.");
        }
        return new ByteArrayInputStream(bytes);
    }

}